Files
item_bank/app/api/auth.py
T
2026-08-01 16:50:55 +08:00

64 lines
2.0 KiB
Python

"""认证接口:注册、登录、当前用户。"""
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