"""认证接口:注册、登录、当前用户。""" from fastapi import APIRouter, Depends, HTTPException, Request, status from fastapi.security import OAuth2PasswordRequestForm from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.db import get_db from app.deps import get_current_user from app.models.user import User from app.ratelimit import AUTH_LIMIT, limiter from app.schemas.auth import RegisterRequest, Token, UserOut from app.services.security import ( create_access_token, hash_password, verify_password, ) router = APIRouter(prefix="/api/auth", tags=["auth"]) @router.post("/register", response_model=UserOut, status_code=status.HTTP_201_CREATED) @limiter.limit(AUTH_LIMIT) async def register( request: Request, payload: RegisterRequest, db: AsyncSession = Depends(get_db), ): exists = await db.scalar(select(User).where(User.username == payload.username)) if exists: raise HTTPException(status.HTTP_409_CONFLICT, detail="用户名已存在") user = User( username=payload.username, email=payload.email, password_hash=hash_password(payload.password), ) db.add(user) await db.commit() await db.refresh(user) return user @router.post("/login", response_model=Token) @limiter.limit(AUTH_LIMIT) async def login( request: Request, form: OAuth2PasswordRequestForm = Depends(), db: AsyncSession = Depends(get_db), ): user = await db.scalar(select(User).where(User.username == form.username)) if not user or not verify_password(form.password, user.password_hash): raise HTTPException( status.HTTP_401_UNAUTHORIZED, detail="用户名或密码错误", headers={"WWW-Authenticate": "Bearer"}, ) if not user.is_active: raise HTTPException(status.HTTP_403_FORBIDDEN, detail="账户已禁用") return Token(access_token=create_access_token(user.id)) @router.get("/me", response_model=UserOut) async def me(current: User = Depends(get_current_user)): return current