generic.backend 源代码
from django.contrib.auth.backends import AllowAllUsersModelBackend
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.db.models import QuerySet
import utils.models.query as SQ
from generic.models import User, PermissionBlacklist
[文档]
class BlacklistBackend(AllowAllUsersModelBackend):
'''
在django自带的认证后端的基础上,除去在黑名单中记录的用户权限。
'''
def _revoked_perms(self, user: User) -> set[str]:
return PermissionBlacklist.objects.get_revoked_permissions(user)
[文档]
def get_user_permissions(self, user: User, obj = None) -> set[str]:
'''获取用户自身权限,不包括组权限和黑名单中的权限。'''
return super().get_user_permissions(user, obj) - self._revoked_perms(user)
[文档]
def get_all_permissions(self, user: User, obj = None) -> set[str]:
'''获取用户的所有权限,也就是用户所在组的权限 + 用户自身权限 - 黑名单中的权限'''
return super().get_all_permissions(user, obj) - self._revoked_perms(user)
[文档]
def get_group_permissions(self, user: User, obj = None) -> set[str]:
'''获取用户通过其所在组获得的权限,不包括黑名单中的权限。'''
return super().get_group_permissions(user, obj) - self._revoked_perms(user)
[文档]
def has_perm(self, user: User, perm: str, obj = None) -> bool:
'''检查用户的特定权限。暂不支持对于某一个特定的obj查询。'''
return perm not in self._revoked_perms(user) and super().has_perm(user, perm, obj)
[文档]
def has_module_perms(self, user: User, app_label: str) -> bool:
'''
检查用户的应用权限
如果用户有其中任何一个权限,就认为他具有这个应用的权限。
'''
return user.is_active and any(
perm[: perm.index('.')] == app_label
for perm in self.get_all_permissions(user)
)
[文档]
def with_perm(self, perm: str | Permission, is_active: bool = True,
include_superusers: bool = True, obj = None) -> QuerySet[User]:
'''
返回所有具有perm权限的用户列表。默认要求用户is_active,且包括超级用户。
Args:
perm (str | Permission): 权限,字符串格式为app_label.codename
is_active (bool, optional): 是否要求用户是激活状态,默认为True
include_superusers (bool, optional): 是否包括超级用户
obj (Any, optional): 查询对于某一个特定的对象的权限,父类暂不支持
Returns:
具有权限的用户集合
'''
_M = PermissionBlacklist
# 父类的with_perm方法会检查传入的perm是否符合格式
users: QuerySet[User] = super().with_perm(perm, is_active, include_superusers, obj)
if isinstance(perm, str):
app_label, codename = perm.split('.')
banned_records = _M.objects.filter(
SQ.sq((_M.permission, Permission.codename), codename),
SQ.sq((_M.permission, Permission.content_type, ContentType.app_label), app_label)
)
elif isinstance(perm, Permission):
banned_records = SQ.sfilter(_M.permission, perm)
return users.exclude(pk__in=SQ.qsvlist(banned_records, _M.user, 'pk'))