Add method to grant and revoke access via ACLs.

Granting will also check if the permission has been
authorized to the object class using ModelPermission.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2017-07-17 20:39:41 -04:00
parent 804b077115
commit 3cbe90567f
3 changed files with 70 additions and 25 deletions

View File

@@ -26,6 +26,10 @@ class ModelPermission(object):
model.add_to_class('acls', GenericRelation(AccessControlList))
@classmethod
def get_for_class(cls, klass):
return cls._registry.get(klass, ())
@classmethod
def get_for_instance(cls, instance):
StoredPermission = apps.get_model(

View File

@@ -0,0 +1,16 @@
from __future__ import unicode_literals
class ACLsBaseException(Exception):
"""
Base exception for the acls app
"""
pass
class PermissionNotValidForClass(ACLsBaseException):
"""
The permission is not one that has been registered for a class using the
ModelPermission class.
"""
pass

View File

@@ -12,6 +12,7 @@ from common.utils import return_attrib
from permissions import Permission
from permissions.models import StoredPermission
from .exceptions import PermissionNotValidForClass
from .classes import ModelPermission
logger = logging.getLogger(__name__)
@@ -22,31 +23,6 @@ class AccessControlListManager(models.Manager):
Implement a 3 tier permission system, involving a permissions, an actor
and an object
"""
def get_inherited_permissions(self, role, obj):
try:
instance = obj.first()
except AttributeError:
instance = obj
else:
if not instance:
return StoredPermission.objects.none()
try:
parent_accessor = ModelPermission.get_inheritance(type(instance))
except KeyError:
return StoredPermission.objects.none()
else:
parent_object = return_attrib(instance, parent_accessor)
content_type = ContentType.objects.get_for_model(parent_object)
try:
return self.get(
role=role, content_type=content_type,
object_id=parent_object.pk
).permissions.all()
except self.model.DoesNotExist:
return StoredPermission.objects.none()
def check_access(self, permissions, user, obj, related=None):
if user.is_superuser or user.is_staff:
logger.debug(
@@ -191,3 +167,52 @@ class AccessControlListManager(models.Manager):
return queryset.filter(parent_acl_query | acl_query)
else:
return queryset
def get_inherited_permissions(self, role, obj):
try:
instance = obj.first()
except AttributeError:
instance = obj
else:
if not instance:
return StoredPermission.objects.none()
try:
parent_accessor = ModelPermission.get_inheritance(type(instance))
except KeyError:
return StoredPermission.objects.none()
else:
parent_object = return_attrib(instance, parent_accessor)
content_type = ContentType.objects.get_for_model(parent_object)
try:
return self.get(
role=role, content_type=content_type,
object_id=parent_object.pk
).permissions.all()
except self.model.DoesNotExist:
return StoredPermission.objects.none()
def grant(self, permission, role, obj):
class_permissions = ModelPermission.get_for_class(klass=obj.__class__)
if permission not in class_permissions:
raise PermissionNotValidForClass
content_type = ContentType.objects.get_for_model(model=obj)
acl, created = self.get_or_create(
content_type=content_type, object_id=obj.pk,
role=role
)
acl.permissions.add(permission.stored_permission)
def revoke(self, permission, role, obj):
content_type = ContentType.objects.get_for_model(model=obj)
acl, created = self.get_or_create(
content_type=content_type, object_id=obj.pk,
role=role
)
acl.permissions.remove(permission.stored_permission)
if acl.permissions.count() == 0:
acl.delete()