Moved permission checking logic to model, simplyfing it and adding group support too
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from django.contrib.auth.models import User
|
#from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.models import Group
|
#from django.contrib.auth.models import Group
|
||||||
from django.db.utils import DatabaseError
|
from django.db.utils import DatabaseError
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
@@ -29,49 +29,16 @@ def register_permissions(namespace, permissions):
|
|||||||
|
|
||||||
#TODO: Handle anonymous users
|
#TODO: Handle anonymous users
|
||||||
def check_permissions(requester, namespace, permission_list):
|
def check_permissions(requester, namespace, permission_list):
|
||||||
if isinstance(requester, User):
|
|
||||||
if requester.is_superuser:
|
|
||||||
return True
|
|
||||||
|
|
||||||
for permission_item in permission_list:
|
for permission_item in permission_list:
|
||||||
permission = get_object_or_404(Permission,
|
permission = get_object_or_404(Permission,
|
||||||
namespace=namespace, name=permission_item)
|
namespace=namespace, name=permission_item)
|
||||||
if check_permission(requester, permission):
|
#if check_permission(requester, permission):
|
||||||
|
if permission.has_permission(requester):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
raise PermissionDenied(ugettext(u'Insufficient permissions.'))
|
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', [
|
register_permissions('permissions', [
|
||||||
{'name': PERMISSION_ROLE_VIEW, 'label':_(u'View roles')},
|
{'name': PERMISSION_ROLE_VIEW, 'label':_(u'View roles')},
|
||||||
{'name': PERMISSION_ROLE_EDIT, 'label':_(u'Edit roles')},
|
{'name': PERMISSION_ROLE_EDIT, 'label':_(u'Edit roles')},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from django.db import models
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.contenttypes import generic
|
from django.contrib.contenttypes import generic
|
||||||
|
from django.contrib.auth.models import User, Group
|
||||||
|
|
||||||
|
|
||||||
class PermissionManager(models.Manager):
|
class PermissionManager(models.Manager):
|
||||||
@@ -26,6 +27,33 @@ class Permission(models.Model):
|
|||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.label
|
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):
|
class PermissionHolder(models.Model):
|
||||||
permission = models.ForeignKey(Permission, verbose_name=_(u'permission'))
|
permission = models.ForeignKey(Permission, verbose_name=_(u'permission'))
|
||||||
@@ -40,7 +68,7 @@ class PermissionHolder(models.Model):
|
|||||||
verbose_name_plural = _(u'permission holders')
|
verbose_name_plural = _(u'permission holders')
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return unicode(self.holder_object)
|
return u'%s: %s' % (self.holder_type, self.holder_object)
|
||||||
|
|
||||||
|
|
||||||
class Role(models.Model):
|
class Role(models.Model):
|
||||||
@@ -66,6 +94,12 @@ class Role(models.Model):
|
|||||||
return ('role_list',)
|
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):
|
class RoleMember(models.Model):
|
||||||
role = models.ForeignKey(Role, verbose_name=_(u'role'))
|
role = models.ForeignKey(Role, verbose_name=_(u'role'))
|
||||||
member_type = models.ForeignKey(ContentType,
|
member_type = models.ForeignKey(ContentType,
|
||||||
@@ -74,6 +108,8 @@ class RoleMember(models.Model):
|
|||||||
member_id = models.PositiveIntegerField()
|
member_id = models.PositiveIntegerField()
|
||||||
member_object = generic.GenericForeignKey(ct_field='member_type', fk_field='member_id')
|
member_object = generic.GenericForeignKey(ct_field='member_type', fk_field='member_id')
|
||||||
|
|
||||||
|
objects = RoleMemberManager()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
#ordering = ('label',)
|
#ordering = ('label',)
|
||||||
verbose_name = _(u'role member')
|
verbose_name = _(u'role member')
|
||||||
|
|||||||
Reference in New Issue
Block a user