File size: 3,970 Bytes
50925ca 5019340 50925ca bfea95e 50925ca db1baa2 50925ca 5019340 5e64563 5019340 5e64563 5019340 5e64563 e8aaec2 5e64563 e8aaec2 bfea95e 5e64563 50925ca 1520141 50925ca 1520141 5019340 50925ca 1520141 50925ca 5019340 1520141 5e64563 1520141 5e64563 1520141 5019340 50925ca 1520141 50925ca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | from fastapi import Request, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from datetime import datetime, timedelta, timezone
from app.database import get_db
from app import models
from app.utils.auth import verify_supabase_jwt
async def get_current_user(request: Request, db: AsyncSession = Depends(get_db)) -> models.User:
session_cookie = request.cookies.get("archvise_session")
# Fallback to Authorization header if cookie is missing (e.g. cross-domain/proxy environment)
if not session_cookie:
auth_header = request.headers.get("Authorization")
if auth_header and auth_header.startswith("Bearer "):
session_cookie = auth_header.split(" ")[1]
if not session_cookie:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Not authenticated"
)
try:
# Guest session: token starts with 'guest_' prefix — look up uid from Redis (async)
if session_cookie.startswith("guest_"):
import redis.asyncio as redis_async
from app.config import settings as cfg
try:
r = redis_async.Redis.from_url(cfg.REDIS_URL, decode_responses=True)
guest_uid = await r.get(f"guest_session:{session_cookie}")
await r.aclose()
except Exception:
guest_uid = None
if not guest_uid:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Guest session expired. Please start a new session."
)
decoded_claims = {
"uid": guest_uid,
"email": f"{guest_uid}@guest.archvise.com",
"name": "Archvise Guest",
"picture": None
}
else:
# Verify Supabase JWT Offline
decoded_claims = verify_supabase_jwt(session_cookie)
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Session expired or invalid"
)
firebase_uid = decoded_claims.get("uid")
email = decoded_claims.get("email")
name = decoded_claims.get("name")
avatar_url = decoded_claims.get("picture")
# Query database for user
result = await db.execute(select(models.User).where(models.User.firebase_uid == firebase_uid))
user = result.scalars().first()
if not user:
# Seamless registration: Create new user if not found in db
user = models.User(
firebase_uid=firebase_uid,
email=email,
name=name,
avatar_url=avatar_url,
plan="free",
display_mode="founder",
credits_remaining=2,
credits_reset_at=datetime.now(timezone.utc) + timedelta(days=30),
is_active=True
)
db.add(user)
await db.commit()
await db.refresh(user)
# Check if monthly credits need to be reset (timezone-aware comparison)
now_utc = datetime.now(timezone.utc)
reset_at = user.credits_reset_at
# Ensure reset_at is timezone-aware for comparison
if reset_at and reset_at.tzinfo is None:
reset_at = reset_at.replace(tzinfo=timezone.utc)
if reset_at and now_utc > reset_at:
if user.plan == "pro":
user.credits_remaining = -1 # -1 = unlimited
elif user.plan == "starter":
user.credits_remaining = 15
else:
user.credits_remaining = 2
user.credits_reset_at = now_utc + timedelta(days=30)
db.add(user)
await db.commit()
if not user.is_active:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="User account is deactivated"
)
return user
|