diff --git a/apps/permissions/api.py b/apps/permissions/api.py index 15fa2a253f..9b1942a676 100644 --- a/apps/permissions/api.py +++ b/apps/permissions/api.py @@ -1,5 +1,5 @@ -from django.contrib.auth.models import User -from django.contrib.auth.models import Group +#from django.contrib.auth.models import User +#from django.contrib.auth.models import Group from django.db.utils import DatabaseError from django.shortcuts import get_object_or_404 from django.contrib.contenttypes.models import ContentType @@ -29,49 +29,16 @@ def register_permissions(namespace, permissions): #TODO: Handle anonymous users def check_permissions(requester, namespace, permission_list): - if isinstance(requester, User): - if requester.is_superuser: - return True - for permission_item in permission_list: permission = get_object_or_404(Permission, namespace=namespace, name=permission_item) - if check_permission(requester, permission): + #if check_permission(requester, permission): + if permission.has_permission(requester): return True raise PermissionDenied(ugettext(u'Insufficient permissions.')) -def check_permission(requester, permission): - for permission_holder in permission.permissionholder_set.all(): - if check_requester(requester, permission_holder): - return True - - -def check_requester(requester, permission_holder): - ct = ContentType.objects.get_for_model(requester) - if permission_holder.holder_type == ct and permission_holder.holder_id == requester.id: - return True - - if isinstance(permission_holder.holder_object, Role): - requester_list = [role_member.member_object for role_member in permission_holder.holder_object.rolemember_set.all()] - if check_elements(requester, requester_list): - return True - - #Untested - if isinstance(permission_holder.holder_object, Group): - if check_elements(requester, permission_holder.holder_object.user_set.all()): - return True - - -#TODO: a role may contain groups, make recursive -def check_elements(requester, requester_list): - #ct = ContentType.objects.get_for_model(requester) - for requester_object in requester_list: - if requester == requester_object: - return True - - register_permissions('permissions', [ {'name': PERMISSION_ROLE_VIEW, 'label':_(u'View roles')}, {'name': PERMISSION_ROLE_EDIT, 'label':_(u'Edit roles')}, diff --git a/apps/permissions/models.py b/apps/permissions/models.py index 2319cf7c5d..45fa68d10d 100644 --- a/apps/permissions/models.py +++ b/apps/permissions/models.py @@ -2,6 +2,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes import generic +from django.contrib.auth.models import User, Group class PermissionManager(models.Manager): @@ -25,7 +26,34 @@ class Permission(models.Model): def __unicode__(self): return self.label + + def get_holders(self): + return [holder.holder_object for holder in self.permissionholder_set.all()] + + def has_permission(self, requester): + if isinstance(requester, User): + if requester.is_superuser or requester.is_staff: + return True + # Request is one of the permission's holders? + if requester in self.get_holders(): + return True + + # If not check if the requesters memberships objects is one of + # the permission's holder? + roles = RoleMember.objects.get_roles_for_member(requester) + + if isinstance(requester, User): + groups = requester.groups.all() + else: + groups = [] + + result = False + for membership in list(set(roles) | set(groups)): + result |= self.has_permission(membership) + + return result + class PermissionHolder(models.Model): permission = models.ForeignKey(Permission, verbose_name=_(u'permission')) @@ -40,7 +68,7 @@ class PermissionHolder(models.Model): verbose_name_plural = _(u'permission holders') def __unicode__(self): - return unicode(self.holder_object) + return u'%s: %s' % (self.holder_type, self.holder_object) class Role(models.Model): @@ -66,6 +94,12 @@ class Role(models.Model): return ('role_list',) +class RoleMemberManager(models.Manager): + def get_roles_for_member(self, member_obj): + member_type = ContentType.objects.get_for_model(member_obj) + return [role_member.role for role_member in RoleMember.objects.filter(member_type=member_type, member_id=member_obj.pk)] + + class RoleMember(models.Model): role = models.ForeignKey(Role, verbose_name=_(u'role')) member_type = models.ForeignKey(ContentType, @@ -74,6 +108,8 @@ class RoleMember(models.Model): member_id = models.PositiveIntegerField() member_object = generic.GenericForeignKey(ct_field='member_type', fk_field='member_id') + objects = RoleMemberManager() + class Meta: #ordering = ('label',) verbose_name = _(u'role member')