Rednote / backend /core /guest.py
orakzai-io
Intial 2
3dbd619
Raw History Blame Contribute Delete
2.32 kB
from typing import Any, cast
from uuid import UUID
from fastapi import Depends, HTTPException, Header, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from db.session import get_async_session
from models.db import User
from core.security import fastapi_users
# Use fastapi_users to optionally fetch current logged in user
optional_current_user = fastapi_users.current_user(active=True, optional=True)
async def get_current_user_or_guest(
current_user: User | None = Depends(optional_current_user),
x_guest_id: str | None = Header(None, alias="X-Guest-ID"),
db: AsyncSession = Depends(get_async_session),
) -> User:
"""
Dependency that resolves the request identity.
If authenticated via JWT, returns the logged in User.
Otherwise, expects an X-Guest-ID header, validates it,
and returns (or creates) a temporary guest User record in the database.
"""
if current_user:
return current_user
if not x_guest_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Authentication required or X-Guest-ID header missing."
)
try:
guest_uuid = UUID(x_guest_id)
except ValueError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid X-Guest-ID header format. Must be a valid UUID."
)
# Lookup guest user in database
stmt = select(User).where(cast(Any, User.id) == guest_uuid)
result = await db.execute(stmt)
guest_user = result.scalars().first()
if not guest_user:
# Create a new inactive/guest User row
guest_user = User(
id=guest_uuid,
email=f"guest_{guest_uuid}@guest.rednote",
hashed_password="!", # invalid hash to prevent standard login
is_active=True,
is_verified=True,
is_superuser=False,
)
db.add(guest_user)
try:
await db.commit()
await db.refresh(guest_user)
except Exception as e:
await db.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Could not initialize guest session: {str(e)}"
)
return guest_user