Spaces:
Sleeping
Sleeping
| from fastapi import Header, HTTPException, Depends | |
| import jwt | |
| import os | |
| from datetime import datetime, timezone | |
| from app.database import users_collection | |
| SECRET_KEY = os.getenv("JWT_SECRET", "super-secret-fakeshield-key-for-project") | |
| ALGORITHM = "HS256" | |
| def _as_utc_datetime(value): | |
| if value is None: | |
| return None | |
| if isinstance(value, datetime): | |
| return value.replace(tzinfo=timezone.utc) if value.tzinfo is None else value.astimezone(timezone.utc) | |
| if isinstance(value, str): | |
| try: | |
| normalized = value.replace("Z", "+00:00") | |
| parsed = datetime.fromisoformat(normalized) | |
| return parsed.replace(tzinfo=timezone.utc) if parsed.tzinfo is None else parsed.astimezone(timezone.utc) | |
| except ValueError: | |
| return None | |
| return None | |
| def is_subscription_active(user: dict) -> bool: | |
| if user.get("subscription_tier") != "paid": | |
| return False | |
| expires_at = _as_utc_datetime(user.get("subscription_expires_at")) | |
| if not expires_at: | |
| return False | |
| return expires_at > datetime.now(timezone.utc) | |
| def serialize_subscription_expires_at(user: dict): | |
| expires_at = _as_utc_datetime(user.get("subscription_expires_at")) | |
| return expires_at.isoformat().replace("+00:00", "Z") if expires_at else None | |
| def public_user_payload(user: dict) -> dict: | |
| active = is_subscription_active(user) | |
| return { | |
| "name": user.get("fullName") or user.get("name") or user.get("full_name"), | |
| "email": user.get("email"), | |
| "subscription_tier": "paid" if active else "free", | |
| "subscription_expires_at": serialize_subscription_expires_at(user) if active else None, | |
| "profile_pic": user.get("profile_pic"), | |
| } | |
| async def get_current_user(authorization: str = Header(None)): | |
| if not authorization: | |
| raise HTTPException(status_code=401, detail="Authorization header missing") | |
| try: | |
| token = authorization.replace("Bearer ", "") | |
| payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) | |
| email = payload.get("sub") | |
| if email is None: | |
| raise HTTPException(status_code=401, detail="Invalid token") | |
| except jwt.PyJWTError: | |
| raise HTTPException(status_code=401, detail="Invalid token") | |
| try: | |
| user = await users_collection.find_one({"email": email}) | |
| if user is None: | |
| print(f"[AUTH] User {email} not in DB. Granting limited guest access.") | |
| return { | |
| "email": email, | |
| "full_name": "Guest User", | |
| "subscription_tier": "free", | |
| "is_offline": True | |
| } | |
| return user | |
| except Exception as e: | |
| print(f"[AUTH] DB Error during auth: {e}. Granting limited guest access.") | |
| return { | |
| "email": email, | |
| "full_name": "Offline Tester", | |
| "subscription_tier": "free", | |
| "is_offline": True | |
| } | |
| async def verify_paid_tier(user: dict = Depends(get_current_user)): | |
| if not is_subscription_active(user): | |
| raise HTTPException( | |
| status_code=403, | |
| detail="This feature requires an active Pro subscription. Please upgrade to access." | |
| ) | |
| return user | |