Files
2026-10-15 20:36:59 +08:00

78 lines
2.9 KiB
Python

"""认证模块路由(/auth/*,对应《03-接口文档》第 3 章)"""
import redis.asyncio as aioredis
from fastapi import APIRouter, Depends, Header, Request
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.response import ok
from app.core.security import decode_token
from app.database import get_db
from app.deps import Identity, get_identity, require_user
from app.redis_client import get_redis
from app.schemas.auth import (
EmailSendReq,
LoginReq,
PasswordResetReq,
RefreshReq,
RegisterReq,
SmsSendReq,
)
from app.services import auth_service
router = APIRouter(prefix="/auth", tags=["认证"])
def _client_ip(request: Request) -> str:
# Nginx 反代后取真实 IP
return request.headers.get("X-Real-IP") or (request.client.host if request.client else "")
@router.post("/sms/send")
async def sms_send(req: SmsSendReq, request: Request, db: AsyncSession = Depends(get_db),
redis: aioredis.Redis = Depends(get_redis)):
data = await auth_service.send_code(db, redis, "sms", req.phone, req.scene, _client_ip(request))
return ok(data)
@router.post("/email/send")
async def email_send(req: EmailSendReq, request: Request, db: AsyncSession = Depends(get_db),
redis: aioredis.Redis = Depends(get_redis)):
data = await auth_service.send_code(db, redis, "email", req.email, req.scene, _client_ip(request))
return ok(data)
@router.post("/register")
async def register(req: RegisterReq, request: Request, db: AsyncSession = Depends(get_db),
redis: aioredis.Redis = Depends(get_redis),
identity: Identity = Depends(get_identity)):
data = await auth_service.register(db, redis, req, identity.device_id, _client_ip(request))
return ok(data)
@router.post("/login")
async def login(req: LoginReq, request: Request, db: AsyncSession = Depends(get_db),
redis: aioredis.Redis = Depends(get_redis)):
data = await auth_service.login(db, redis, req, _client_ip(request))
return ok(data)
@router.post("/token/refresh")
async def token_refresh(req: RefreshReq, db: AsyncSession = Depends(get_db),
redis: aioredis.Redis = Depends(get_redis)):
return ok(await auth_service.refresh(db, redis, req.refresh_token))
@router.post("/logout")
async def logout(authorization: str = Header(...),
redis: aioredis.Redis = Depends(get_redis),
identity: Identity = Depends(require_user)):
payload = decode_token(authorization.removeprefix("Bearer ").strip())
await auth_service.logout(redis, identity.user_id, payload.get("jti", ""), int(payload.get("exp", 0)))
return ok()
@router.post("/password/reset")
async def password_reset(req: PasswordResetReq, db: AsyncSession = Depends(get_db),
redis: aioredis.Redis = Depends(get_redis)):
await auth_service.reset_password(db, redis, req)
return ok()