db_auth.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. """地磅模块认证适配:门户 JWT 用户 → db 业务上下文。"""
  2. from __future__ import annotations
  3. from dataclasses import dataclass
  4. from typing import Any, Dict, Optional
  5. from fastapi import Depends, HTTPException
  6. from fastapi.security import OAuth2PasswordBearer
  7. from sqlalchemy.orm import Session
  8. from app.core.auth import get_current_user_by_token
  9. from app.core.database import get_db
  10. from app.core.menu_guard import ADMIN_ROLES, require_admin_or_super_admin
  11. optional_oauth2_scheme = OAuth2PasswordBearer(
  12. tokenUrl="/api/public/login",
  13. auto_error=False,
  14. )
  15. @dataclass
  16. class DbUserContext:
  17. """db Router/Service 使用的当前用户上下文。"""
  18. id: str
  19. name: str
  20. dept_id: str
  21. role: str
  22. tenant_no: str
  23. def to_tenant_user_dict(self) -> Dict[str, Any]:
  24. return {
  25. "user_id": self.id,
  26. "role": self.role,
  27. "tenant_no": self.tenant_no,
  28. }
  29. def to_user_info(self) -> Dict[str, Any]:
  30. """与门户 JWT / apply_data_scope 所需的 user_info 字段对齐。"""
  31. return {
  32. "user_id": self.id,
  33. "role": self.role,
  34. "tenant_no": self.tenant_no,
  35. "dept_id": self.dept_id,
  36. "region_id": self.dept_id,
  37. }
  38. def get_db_current_user(
  39. user: dict = Depends(require_admin_or_super_admin),
  40. ) -> DbUserContext:
  41. return DbUserContext(
  42. id=(user.get("user_id") or "").strip(),
  43. name=(user.get("real_name") or user.get("username") or "").strip(),
  44. dept_id=(user.get("region_id") or "").strip(),
  45. role=(user.get("role") or "").strip(),
  46. tenant_no=(user.get("tenant_no") or "").strip(),
  47. )
  48. def get_db_current_user_optional(
  49. token: Optional[str] = Depends(optional_oauth2_scheme),
  50. db: Session = Depends(get_db),
  51. ) -> DbUserContext | None:
  52. """有 Bearer 且为 admin/super_admin 时返回上下文,否则 None(供三方 H5 无登录调用)。"""
  53. if not token:
  54. return None
  55. try:
  56. user = get_current_user_by_token(token, db)
  57. except HTTPException:
  58. return None
  59. role = user.get("role")
  60. if role not in ADMIN_ROLES:
  61. return None
  62. return DbUserContext(
  63. id=(user.get("user_id") or "").strip(),
  64. name=(user.get("real_name") or user.get("username") or "").strip(),
  65. dept_id=(user.get("region_id") or "").strip(),
  66. role=(role or "").strip(),
  67. tenant_no=(user.get("tenant_no") or "").strip(),
  68. )