From 6dd88d4e2d0da9da490b52b46d24ddeec70bf468 Mon Sep 17 00:00:00 2001 From: fullsizemalt <106900403+fullsizemalt@users.noreply.github.com> Date: Wed, 24 Dec 2025 21:44:26 -0800 Subject: [PATCH] fix: improve session persistence and review saving - Increase token expiry from 30 minutes to 7 days - Remove internal session.commit() calls from gamification services - Add try/except around gamification logic in review creation - Add elmeg.runfoo.run hostname support in frontend api-config --- backend/auth.py | 2 +- backend/routers/reviews.py | 14 ++++++++++---- backend/services/gamification.py | 7 +------ frontend/lib/api-config.ts | 5 +++-- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/backend/auth.py b/backend/auth.py index 2fb0725..37e5f27 100644 --- a/backend/auth.py +++ b/backend/auth.py @@ -12,7 +12,7 @@ import os # Configuration SECRET_KEY = os.getenv("SECRET_KEY", "supersecretkey") # Change this in production! ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = 30 +ACCESS_TOKEN_EXPIRE_MINUTES = 10080 # 7 days pwd_context = CryptContext(schemes=["argon2"], deprecated="auto") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/token") diff --git a/backend/routers/reviews.py b/backend/routers/reviews.py index e37cf5d..cdfcc7b 100644 --- a/backend/routers/reviews.py +++ b/backend/routers/reviews.py @@ -18,20 +18,26 @@ def create_review( db_review = Review.model_validate(review) db_review.user_id = current_user.id session.add(db_review) + session.flush() # Ensure ID is generated for badge checks if needed # Check if this is user's first review for bonus XP + # We check relative to THIS review just being added (id > 0) review_count = session.exec( select(func.count(Review.id)).where(Review.user_id == current_user.id) ).one() or 0 # Award XP xp_amount = XP_REWARDS["review_write"] - if review_count == 0: + if review_count <= 1: # This is the first one xp_amount += XP_REWARDS["first_review"] # Bonus for first review - award_xp(session, current_user, xp_amount, "review") - update_streak(session, current_user) - check_and_award_badges(session, current_user) + try: + award_xp(session, current_user, xp_amount, "review") + update_streak(session, current_user) + check_and_award_badges(session, current_user) + except Exception as e: + # Don't fail the review if gamification fails, but log it + print(f"Error in gamification service during review: {e}") session.commit() session.refresh(db_review) diff --git a/backend/services/gamification.py b/backend/services/gamification.py index b45dd47..41c9ea6 100644 --- a/backend/services/gamification.py +++ b/backend/services/gamification.py @@ -214,9 +214,7 @@ def check_and_award_badges(session: Session, user: User) -> List[Badge]: awarded.append(badge) existing_slugs.add(slug) - if awarded: - session.commit() - + # awarded badges will be added to session but not committed here return awarded @@ -422,7 +420,6 @@ def purchase_title(session: Session, user: User, title: str) -> Tuple[bool, str] user.xp -= cost user.custom_title = title session.add(user) - session.commit() return True, f"Title '{title}' acquired!" + (f" (-{cost} XP)" if cost > 0 else " (Free!)") @@ -444,7 +441,6 @@ def purchase_color(session: Session, user: User, color_name: str) -> Tuple[bool, user.xp -= cost user.title_color = info["hex"] session.add(user) - session.commit() return True, f"Color '{color_name}' applied!" + (f" (-{cost} XP)" if cost > 0 else " (Free!)") @@ -466,7 +462,6 @@ def purchase_flair(session: Session, user: User, flair: str) -> Tuple[bool, str] user.xp -= cost user.flair = flair session.add(user) - session.commit() return True, f"Flair {flair} acquired!" + (f" (-{cost} XP)" if cost > 0 else " (Free!)") diff --git a/frontend/lib/api-config.ts b/frontend/lib/api-config.ts index 6eaf8ad..1b30ccf 100644 --- a/frontend/lib/api-config.ts +++ b/frontend/lib/api-config.ts @@ -4,8 +4,9 @@ export function getApiUrl() { return process.env.INTERNAL_API_URL || 'http://localhost:8000' } // Client-side - if (window.location.hostname === 'elmeg.xyz') { - return 'https://elmeg.xyz/api' + const hostname = window.location.hostname + if (hostname === 'elmeg.xyz' || hostname === 'elmeg.runfoo.run') { + return '/api' } return process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000' }