Files
mayan-edms/mayan/apps/acls/models.py
Roberto Rosario 18e5ee1e4f ACL app updates
Update the ACL permission view to use the new AddRemoveView.

Add ACL created and ACL edit events.

Add permission adding and removal accesors to the ACL model.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
2019-02-14 02:30:51 -04:00

117 lines
3.9 KiB
Python

from __future__ import absolute_import, unicode_literals
import logging
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models, transaction
from django.urls import reverse
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from mayan.apps.permissions.models import Role, StoredPermission
from .events import event_acl_created, event_acl_edited
from .managers import AccessControlListManager
logger = logging.getLogger(__name__)
@python_2_unicode_compatible
class AccessControlList(models.Model):
"""
ACL means Access Control List it is a more fine-grained method of
granting access to objects. In the case of ACLs, they grant access using
3 elements: actor, permission, object. In this case the actor is the role,
the permission is the Mayan permission and the object can be anything:
a document, a folder, an index, etc. This means = "Grant X permissions
to role Y for object Z". This model holds the permission, object, actor
relationship for one access control list.
Fields:
* Role - Custom role that is being granted a permission. Roles are created
in the Setup menu.
"""
content_type = models.ForeignKey(
on_delete=models.CASCADE, related_name='object_content_type',
to=ContentType
)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey(
ct_field='content_type', fk_field='object_id',
)
# TODO: limit choices to the permissions valid for the content_object
permissions = models.ManyToManyField(
blank=True, related_name='acls', to=StoredPermission,
verbose_name=_('Permissions')
)
role = models.ForeignKey(
on_delete=models.CASCADE, related_name='acls', to=Role,
verbose_name=_('Role')
)
objects = AccessControlListManager()
class Meta:
ordering = ('pk',)
unique_together = ('content_type', 'object_id', 'role')
verbose_name = _('Access entry')
verbose_name_plural = _('Access entries')
def __str__(self):
return _(
'Role "%(role)s" permission\'s for "%(object)s"'
) % {
'object': self.content_object,
'role': self.role,
}
def get_absolute_url(self):
return reverse(
viewname='acls:acl_permissions', kwargs={'acl_id': self.pk}
)
def get_inherited_permissions(self):
return AccessControlList.objects.get_inherited_permissions(
role=self.role, obj=self.content_object
)
def get_permission_titles(self):
"""
Returns the descriptibe labels for the permissions.
"""
result = ', '.join(
[force_text(permission) for permission in self.permissions.all()]
)
return result or _('None')
get_permission_titles.short_description = _('Permissions')
def permissions_add(self, queryset, _user=None):
with transaction.atomic():
event_acl_edited.commit(
actor=_user, target=self
)
self.permissions.add(*queryset)
def permissions_remove(self, queryset, _user=None):
with transaction.atomic():
event_acl_edited.commit(
actor=_user, target=self
)
self.permissions.remove(*queryset)
def save(self, *args, **kwargs):
_user = kwargs.pop('_user', None)
with transaction.atomic():
is_new = not self.pk
super(AccessControlList, self).save(*args, **kwargs)
if is_new:
event_acl_created.commit(
actor=_user, target=self
)
else:
event_acl_edited.commit(
actor=_user, target=self
)