Files
amb_rag/backend/app/api/auth.py
T
2026-09-02 11:19:49 +08:00

158 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""认证路由:注册、登录、登出、用户信息。"""
from fastapi import APIRouter, Depends, Response
from sqlalchemy.orm import Session
from app.api.deps import get_current_user, get_db
from app.core.session import get_cookie_params
from app.models.user import User
from app.schemas.user import (
LoginRequest,
MeResponse,
RegisterRequest,
StorageInfoResponse,
UpdateMeRequest,
UserResponse,
)
from app.services.auth_service import AuthService
router = APIRouter(prefix="/auth", tags=["auth"])
@router.post("/register", response_model=UserResponse, status_code=201)
def register(body: RegisterRequest, response: Response, db: Session = Depends(get_db)) -> UserResponse:
"""注册新用户(默认 role=customer)并自动登录。"""
auth_service = AuthService(db)
user, token = auth_service.register(body.username, body.email, body.password, role="customer")
response.set_cookie(value=token, **get_cookie_params())
return _user_response(user)
@router.post("/register-internal", response_model=UserResponse, status_code=201)
def register_internal(
body: RegisterRequest,
response: Response,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db),
) -> UserResponse:
"""注册内部员工账号(仅已登录的内部用户可调用)。"""
if current_user.role != "internal":
from app.core.errors import PermissionDeniedError
raise PermissionDeniedError("仅内部员工可创建内部账号。")
auth_service = AuthService(db)
user, token = auth_service.register(body.username, body.email, body.password, role="internal")
response.set_cookie(value=token, **get_cookie_params())
return _user_response(user)
@router.post("/login", response_model=UserResponse)
def login(body: LoginRequest, response: Response, db: Session = Depends(get_db)) -> UserResponse:
"""普通登录(所有用户可用)。"""
auth_service = AuthService(db)
user, token = auth_service.login(body.username_or_email, body.password)
response.set_cookie(value=token, **get_cookie_params())
return _user_response(user)
@router.post("/internal-login", response_model=UserResponse)
def internal_login(body: LoginRequest, response: Response, db: Session = Depends(get_db)) -> UserResponse:
"""内部登录(仅 role=internal 用户可用)。"""
auth_service = AuthService(db)
user, token = auth_service.internal_login(body.username_or_email, body.password)
response.set_cookie(value=token, **get_cookie_params())
return _user_response(user)
@router.post("/logout", status_code=204)
def logout(
response: Response,
user: User = Depends(get_current_user),
db: Session = Depends(get_db),
) -> None:
"""登出:删除 session 并清除 Cookie。"""
from app.core.session import SESSION_COOKIE_NAME
token = "" # 不需要实际 tokenlogout 内部通过 user_id 找 session
auth_service = AuthService(db)
# 直接删除所有该用户的 session(MVP 简化:单设备)
from app.core.session import _store
to_delete = [t for t, e in _store.items() if e.user_id == user.id]
for t in to_delete:
auth_service.logout(t)
response.delete_cookie(SESSION_COOKIE_NAME, path="/")
return None
@router.get("/me", response_model=MeResponse)
def get_me(user: User = Depends(get_current_user)) -> MeResponse:
"""获取当前用户信息。"""
from app.core.config import get_settings
settings = get_settings()
return MeResponse(
id=user.id,
username=user.username,
email=user.email,
status=user.status,
role=user.role,
storage_used=user.storage_used,
storage_quota=settings.default_storage_quota,
created_at=user.created_at,
)
@router.patch("/me", response_model=MeResponse)
def update_me(
body: UpdateMeRequest,
user: User = Depends(get_current_user),
db: Session = Depends(get_db),
) -> MeResponse:
"""修改密码。"""
auth_service = AuthService(db)
if body.password is not None:
auth_service.change_password(user, body.password)
from app.core.config import get_settings
settings = get_settings()
return MeResponse(
id=user.id,
username=user.username,
email=user.email,
status=user.status,
role=user.role,
storage_used=user.storage_used,
storage_quota=settings.default_storage_quota,
created_at=user.created_at,
)
@router.get("/storage", response_model=StorageInfoResponse)
def get_storage(user: User = Depends(get_current_user)) -> StorageInfoResponse:
"""获取存储用量信息。"""
from app.core.config import get_settings
settings = get_settings()
return StorageInfoResponse(
storage_used=user.storage_used,
storage_quota=settings.default_storage_quota,
storage_used_mb=round(user.storage_used / (1024 * 1024), 2),
storage_quota_mb=round(settings.default_storage_quota / (1024 * 1024), 2),
)
def _user_response(user: User) -> UserResponse:
from app.core.config import get_settings
settings = get_settings()
return UserResponse(
id=user.id,
username=user.username,
email=user.email,
status=user.status,
role=user.role,
storage_used=user.storage_used,
storage_quota=settings.default_storage_quota,
created_at=user.created_at,
)