from collections.abc import Generator from dataclasses import dataclass from typing import Annotated from fastapi import Depends, Header, HTTPException, status from sqlalchemy.orm import Session from app.db.session import get_session_factory def get_db() -> Generator[Session, None, None]: db = get_session_factory()() try: yield db finally: db.close() @dataclass(slots=True) class CurrentUserContext: username: str name: str role_codes: list[str] is_admin: bool def get_current_user( x_auth_username: Annotated[ str | None, Header(description="当前登录用户名。知识库接口至少需要提供用户名或姓名。"), ] = None, x_auth_name: Annotated[ str | None, Header(description="当前登录人展示姓名。未传时默认回退到用户名。"), ] = None, x_auth_role_codes: Annotated[ str | None, Header(description="角色编码列表,多个角色使用英文逗号分隔,例如 `manager,finance`。"), ] = None, x_auth_is_admin: Annotated[ str | None, Header(description="是否管理员,支持 `true/false/1/0`。"), ] = None, ) -> CurrentUserContext: role_codes = [item.strip() for item in (x_auth_role_codes or "").split(",") if item.strip()] is_admin = str(x_auth_is_admin or "").strip().lower() in {"1", "true", "yes", "on"} username = (x_auth_username or "").strip() name = (x_auth_name or username).strip() if not username and not name: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="请先登录后再访问知识库。", ) return CurrentUserContext( username=username or name, name=name or username, role_codes=role_codes, is_admin=is_admin, ) def require_admin_user( current_user: Annotated[CurrentUserContext, Depends(get_current_user)], ) -> CurrentUserContext: if current_user.is_admin or "manager" in current_user.role_codes: return current_user raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="只有管理员可以上传、删除或修改知识库文件。", )