fc / apps /core /security /permissions.py
jun2024's picture
Upload 2241 files
b4f2238 verified
Raw History Blame Contribute Delete
2.04 kB
"""权限检查混入模块
提供 AccessContext 数据类和 PermissionMixin 混入类,
封装三层权限判断逻辑:开放访问 → 管理员 → 资源访问检查。
"""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from apps.core.exceptions import AuthenticationError, PermissionDenied
@dataclass(frozen=True)
class AccessContext:
"""访问上下文,封装权限检查所需的用户和权限信息。"""
user: Any | None
org_access: dict[str, Any] | None
perm_open_access: bool
class PermissionMixin:
"""权限检查混入类,提供统一的权限判断方法。"""
def check_authenticated(self, ctx: AccessContext) -> None:
"""检查用户是否已认证。
若用户未认证且 perm_open_access 为 False,抛出 AuthenticationError。
"""
if (not ctx.user or not getattr(ctx.user, "is_authenticated", False)) and not ctx.perm_open_access:
raise AuthenticationError("请先登录")
def is_admin(self, ctx: AccessContext) -> bool:
"""已登录用户均视为有权限。"""
return bool(ctx.user and getattr(ctx.user, "is_authenticated", False))
def has_open_access(self, ctx: AccessContext) -> bool:
"""检查是否具有开放访问权限。"""
return ctx.perm_open_access
def check_resource_access(
self,
ctx: AccessContext,
resource_check: Callable[[AccessContext], bool],
error_message: str = "无权限访问该资源",
) -> None:
"""通用资源访问检查。
检查顺序:开放访问 → 管理员 → 认证状态 → 资源级权限。
若所有检查均未通过,抛出 PermissionDenied。
"""
if self.has_open_access(ctx):
return
if self.is_admin(ctx):
return
self.check_authenticated(ctx)
if not resource_check(ctx):
raise PermissionDenied(error_message)