"""Authentication FastAPI dependencies (isolated to avoid circular imports).""" from typing import Optional from fastapi import Depends from fastapi.security import OAuth2PasswordBearer from sqlalchemy.ext.asyncio import AsyncSession from app.core.db import get_async_db from app.core.errors import AuthenticationError from app.core.security import verify_token from app.features.user.service import UserService oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/auth/login") oauth2_scheme_optional = OAuth2PasswordBearer( tokenUrl="/api/auth/login", auto_error=False ) async def get_current_user( token: str = Depends(oauth2_scheme), db: AsyncSession = Depends(get_async_db), ): """Resolve authenticated user from JWT access token.""" payload = verify_token(token) if payload is None: raise AuthenticationError("无法验证凭据") user_id: str | None = payload.get("sub") if user_id is None: raise AuthenticationError("无法验证凭据") if payload.get("type") != "access": raise AuthenticationError("无法验证凭据") user = await UserService(db).get_by_id(user_id) if user is None: raise AuthenticationError("无法验证凭据") return user async def get_optional_user( token: Optional[str] = Depends(oauth2_scheme_optional), db: AsyncSession = Depends(get_async_db), ): """Return user if a valid token is provided, else None.""" if token is None: return None try: return await get_current_user(token, db) except AuthenticationError: return None