81 lines
3.2 KiB
Python
81 lines
3.2 KiB
Python
"""路由级鉴权依赖:Bearer JWT → 校验 token → 按 user_id 回查 sys_user → 注入用户。"""
|
|
from fastapi import Depends, Request
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from config.deps import get_db
|
|
from model.sys_user import SysUser
|
|
from repositories.sys_user import SysUserRepo
|
|
from service.auth import decode_token
|
|
from utils.exceptions import AuthError, ForbiddenError
|
|
from service.advisor_agent.audit import write_advisor_audit, audit_action_for_path
|
|
|
|
|
|
KNOWLEDGE_OPERATOR_ROLES = {"ADMIN", "KNOWLEDGE_ADMIN", "KNOWLEDGE_OPERATOR", "运营"}
|
|
|
|
|
|
async def get_current_user(
|
|
request: Request, db: AsyncSession = Depends(get_db)
|
|
) -> SysUser:
|
|
header = request.headers.get("Authorization", "")
|
|
if not header.startswith("Bearer "):
|
|
raise AuthError()
|
|
try:
|
|
user_id = int(decode_token(header.removeprefix("Bearer "))["user_id"])
|
|
except Exception:
|
|
raise AuthError("Token 无效或已过期")
|
|
user = await SysUserRepo(db).get(user_id)
|
|
if user is None:
|
|
raise AuthError("用户不存在")
|
|
if user.status != "正常":
|
|
raise ForbiddenError("账号已被禁用或冻结")
|
|
return user
|
|
|
|
|
|
async def require_knowledge_operator(user: SysUser = Depends(get_current_user)) -> SysUser:
|
|
"""Allow only administrators or explicitly assigned knowledge operators."""
|
|
if user.user_type == "ADMIN":
|
|
return user
|
|
if user.user_type != "EMPLOYEE" or user.employee_role not in KNOWLEDGE_OPERATOR_ROLES:
|
|
raise ForbiddenError("仅运营人员可以管理知识库")
|
|
return user
|
|
|
|
|
|
async def require_customer(user: SysUser = Depends(get_current_user)) -> SysUser:
|
|
"""Allow only authenticated customer accounts to use client Agent APIs."""
|
|
if user.user_type != "CUSTOMER":
|
|
raise ForbiddenError("仅客户用户可以访问 client_agent")
|
|
return user
|
|
|
|
|
|
async def require_risk_officer(user: SysUser = Depends(get_current_user)) -> SysUser:
|
|
"""仅允许管理员或风控专员执行风控处置/工单操作。"""
|
|
if user.user_type == "ADMIN":
|
|
return user
|
|
if user.user_type != "EMPLOYEE" or user.employee_role != "风控专员":
|
|
raise ForbiddenError("仅风控专员可执行风控处置")
|
|
return user
|
|
|
|
async def require_advisor(user: SysUser = Depends(get_current_user)) -> SysUser:
|
|
"""Allow only advisor employees to access the advisor workbench."""
|
|
if user.user_type != "EMPLOYEE" or user.employee_role not in {"投顾", "ADMIN"}:
|
|
raise ForbiddenError("仅投顾人员可以访问投顾工作台")
|
|
return user
|
|
|
|
|
|
async def audited_advisor(request: Request, db: AsyncSession = Depends(get_db)):
|
|
"""Authenticate an advisor Agent request and leave a failure audit trail."""
|
|
try:
|
|
user = await get_current_user(request, db)
|
|
if user.user_type != "EMPLOYEE" or user.employee_role not in {"投顾", "ADMIN"}:
|
|
raise ForbiddenError("仅投顾人员可以访问 advisor_agent")
|
|
yield user
|
|
except Exception:
|
|
await write_advisor_audit(
|
|
db,
|
|
user=None,
|
|
action=audit_action_for_path(request.url.path),
|
|
target=None,
|
|
trace_id=request.headers.get("X-Trace-Id", ""),
|
|
status="失败",
|
|
)
|
|
raise |