"""认证 API 路由 - 登录/登出/令牌验证/用户信息""" import logging from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from sqlalchemy.ext.asyncio import AsyncSession from app import auth_service from app.database import get_db from app.schemas import LoginRequest, LoginResponse logger = logging.getLogger(__name__) router = APIRouter(prefix="/auth", tags=["用户认证"]) security = HTTPBearer() async def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), db: AsyncSession = Depends(get_db), ) -> object: """依赖注入 - 获取当前已登录用户。""" user = await auth_service.verify_token(credentials.credentials, db) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="请先登录", ) return user async def require_admin( current_user=Depends(get_current_user), ) -> object: """依赖注入 - 验证管理员权限。""" if current_user.role != "admin": raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="需要管理员权限", ) return current_user @router.post("/login", response_model=LoginResponse) async def login( request: LoginRequest, db: AsyncSession = Depends(get_db), ): """用户登录。""" user = await auth_service.authenticate_user(db, request.username, request.password) if not user: return LoginResponse(success=False, message="用户名或密码错误") token = await auth_service.create_token(user.id, db) await auth_service.update_last_login(user, db) return LoginResponse( success=True, token=token, user={ "id": user.id, "username": user.username, "role": user.role, "email": user.email, }, message="登录成功", ) @router.post("/logout") async def logout( credentials: HTTPAuthorizationCredentials = Depends(security), db: AsyncSession = Depends(get_db), ): """用户登出。""" await auth_service.invalidate_session(credentials.credentials, db) return {"success": True, "message": "已登出"} @router.get("/verify") async def verify_token( credentials: HTTPAuthorizationCredentials = Depends(security), db: AsyncSession = Depends(get_db), ): """验证用户令牌。""" user = await auth_service.verify_token(credentials.credentials, db) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="无效的会话令牌", ) return { "success": True, "user": { "id": user.id, "username": user.username, "role": user.role, "email": user.email, "last_login": user.last_login.isoformat() if user.last_login else None, }, } @router.get("/me") async def get_me( credentials: HTTPAuthorizationCredentials = Depends(security), db: AsyncSession = Depends(get_db), ): """获取当前用户信息。""" user = await auth_service.verify_token(credentials.credentials, db) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="无效的会话令牌", ) return { "id": user.id, "username": user.username, "role": user.role, "email": user.email, "is_active": user.is_active, "created_at": user.created_at.isoformat(), "last_login": user.last_login.isoformat() if user.last_login else None, }