You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

152 lines
4.6 KiB

from django.utils.translation import ugettext_lazy as _, gettext
from django.db import models
from common.db.models import JMSModel
from common.utils import lazyproperty
from .permission import Permission
from ..builtin import BuiltinRole
from .. import const
__all__ = ['Role', 'SystemRole', 'OrgRole']
class SystemRoleManager(models.Manager):
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(scope=const.Scope.system)
class OrgRoleManager(models.Manager):
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(scope=const.Scope.org)
class Role(JMSModel):
""" 定义 角色 | 角色-权限 关系 """
Scope = const.Scope
name = models.CharField(max_length=128, verbose_name=_('Name'))
scope = models.CharField(
max_length=128, choices=Scope.choices, default=Scope.system, verbose_name=_('Scope')
)
permissions = models.ManyToManyField(
'rbac.Permission', related_name='roles', blank=True, verbose_name=_('Permissions')
)
builtin = models.BooleanField(default=False, verbose_name=_('Built-in'))
comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment'))
BuiltinRole = BuiltinRole
objects = models.Manager()
org_roles = OrgRoleManager()
system_roles = SystemRoleManager()
class Meta:
unique_together = [('name', 'scope')]
verbose_name = _('Role')
def __str__(self):
return '%s(%s)' % (self.name, self.get_scope_display())
def is_system_admin(self):
return str(self.id) == self.BuiltinRole.system_admin.id and self.builtin
def is_org_admin(self):
return str(self.id) == self.BuiltinRole.org_admin.id and self.builtin
def is_admin(self):
yes = self.is_system_admin() or self.is_org_admin()
return yes
@staticmethod
def get_scope_roles_perms(roles, scope):
has_admin = any([r.is_admin() for r in roles])
if has_admin:
perms = Permission.objects.all()
else:
perms = Permission.objects.filter(roles__in=roles).distinct()
perms = Permission.clean_permissions(perms, scope=scope)
return perms
@classmethod
def get_roles_permissions(cls, roles):
org_roles = [role for role in roles if role.scope == cls.Scope.org]
org_perms_id = cls.get_scope_roles_perms(org_roles, cls.Scope.org)\
.values_list('id', flat=True)
system_roles = [role for role in roles if role.scope == cls.Scope.system]
system_perms_id = cls.get_scope_roles_perms(system_roles, cls.Scope.system)\
.values_list('id', flat=True)
perms_id = set(org_perms_id) | set(system_perms_id)
permissions = Permission.objects.filter(id__in=perms_id)\
.prefetch_related('content_type')
return permissions
@classmethod
def get_roles_perms(cls, roles):
permissions = cls.get_roles_permissions(roles)
return Permission.to_perms(permissions)
def get_permissions(self):
if self.is_admin():
permissions = Permission.objects.all()
else:
permissions = self.permissions.all()
permissions = Permission.clean_permissions(permissions, self.scope)
return permissions
@lazyproperty
def users(self):
from .rolebinding import RoleBinding
return RoleBinding.get_role_users(self)
@lazyproperty
def users_amount(self):
return self.users.count()
@lazyproperty
def permissions_amount(self):
return self.permissions.count()
@classmethod
def create_builtin_roles(cls):
BuiltinRole.sync_to_db()
@property
def display_name(self):
if not self.builtin:
return self.name
return gettext(self.name)
def is_org(self):
return self.scope == const.Scope.org
@classmethod
def get_roles_by_perm(cls, perm):
app_label, codename = perm.split('.')
p = Permission.objects.filter(
codename=codename,
content_type__app_label=app_label
).first()
if not p:
return p.roles.none()
role_ids = list(p.roles.all().values_list('id', flat=True))
admin_ids = [BuiltinRole.system_admin.id, BuiltinRole.org_admin.id]
role_ids += admin_ids
return cls.objects.filter(id__in=role_ids)
class SystemRole(Role):
objects = SystemRoleManager()
class Meta:
proxy = True
verbose_name = _('System role')
class OrgRole(Role):
objects = OrgRoleManager()
class Meta:
proxy = True
verbose_name = _('Organization role')