access.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """租户侧访问控制:登录与请求阶段校验租户是否可用;租户表管理权限。"""
  2. from datetime import datetime
  3. from sqlalchemy import select
  4. from sqlalchemy.ext.asyncio import AsyncSession
  5. from app.api.v1.module_system.auth.schema import AuthSchema
  6. from app.api.v1.module_system.tenant.model import TenantModel
  7. from app.api.v1.module_system.user.model import UserModel
  8. from app.core.exceptions import CustomException
  9. from .constants import PLATFORM_TENANT_ID
  10. def _naive(dt: datetime) -> datetime:
  11. if dt.tzinfo is not None:
  12. return dt.replace(tzinfo=None)
  13. return dt
  14. def ensure_platform_tenant_management(auth: AuthSchema) -> None:
  15. """
  16. 租户表 ``sys_tenant`` 无 ``tenant_id`` 列,ORM 无法自动按租户过滤行。
  17. 凡增删改查租户元数据,必须仅限「平台超级管理员」(与 ``should_skip_tenant_filter`` 一致),
  18. 否则仅依赖菜单权限时误配可能导致看见或操作全部租户,破坏多租户隔离。
  19. """
  20. if not auth.user or not auth.user.is_superuser or auth.user.tenant_id != PLATFORM_TENANT_ID:
  21. raise CustomException(msg="无权访问租户管理,仅平台管理员可操作", code=10403, status_code=403)
  22. async def ensure_tenant_allows_access(db: AsyncSession, user: UserModel) -> None:
  23. """
  24. 非超级管理员:所属租户须存在、状态为启用,且在 start_time ~ end_time 有效期内(若配置)。
  25. 超级管理员、系统租户(平台租户)下用户不拦截。
  26. """
  27. if getattr(user, "is_superuser", False):
  28. return
  29. tid = getattr(user, "tenant_id", None)
  30. if tid is None:
  31. raise CustomException(msg="用户未关联租户", code=10401, status_code=403)
  32. if tid == PLATFORM_TENANT_ID:
  33. return
  34. result = await db.execute(select(TenantModel).where(TenantModel.id == tid))
  35. tenant = result.scalar_one_or_none()
  36. if not tenant:
  37. raise CustomException(msg="租户不存在", code=10401, status_code=403)
  38. if tenant.status == "1":
  39. raise CustomException(msg="租户已停用,无法使用", code=10401, status_code=403)
  40. now = datetime.now()
  41. if tenant.start_time:
  42. st = _naive(tenant.start_time)
  43. if now < st:
  44. raise CustomException(msg="租户未生效,请在生效时间后重试", code=10401, status_code=403)
  45. if tenant.end_time:
  46. et = _naive(tenant.end_time)
  47. if now > et:
  48. raise CustomException(msg="租户已过期,请联系管理员", code=10401, status_code=403)