252 lines
8.5 KiB
Python
252 lines
8.5 KiB
Python
from __future__ import absolute_import, unicode_literals
|
|
|
|
import logging
|
|
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.http import Http404
|
|
from django.shortcuts import get_object_or_404
|
|
from django.template import RequestContext
|
|
from django.urls import reverse
|
|
from django.utils.encoding import force_text
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from mayan.apps.common.generics import (
|
|
AddRemoveView, SingleObjectCreateView, SingleObjectDeleteView,
|
|
SingleObjectListView
|
|
)
|
|
from mayan.apps.permissions.models import Role
|
|
|
|
from .classes import ModelPermission
|
|
from .forms import ACLCreateForm
|
|
from .icons import icon_acl_list
|
|
from .links import link_acl_create
|
|
from .models import AccessControlList
|
|
from .permissions import permission_acl_edit, permission_acl_view
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ACLCreateView(SingleObjectCreateView):
|
|
form_class = ACLCreateForm
|
|
model = AccessControlList
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
self.object_content_type = get_object_or_404(
|
|
klass=ContentType, app_label=self.kwargs['app_label'],
|
|
model=self.kwargs['model']
|
|
)
|
|
|
|
try:
|
|
self.content_object = self.object_content_type.get_object_for_this_type(
|
|
pk=self.kwargs['object_id']
|
|
)
|
|
except self.object_content_type.model_class().DoesNotExist:
|
|
raise Http404
|
|
|
|
AccessControlList.objects.check_access(
|
|
obj=self.content_object, permissions=(permission_acl_edit,),
|
|
user=request.user
|
|
)
|
|
|
|
return super(ACLCreateView, self).dispatch(request, *args, **kwargs)
|
|
|
|
def get_instance_extra_data(self):
|
|
return {
|
|
'content_object': self.content_object
|
|
}
|
|
|
|
def get_extra_context(self):
|
|
return {
|
|
'object': self.content_object,
|
|
'title': _(
|
|
'New access control lists for: %s'
|
|
) % self.content_object
|
|
}
|
|
|
|
def get_form_extra_kwargs(self):
|
|
acls = AccessControlList.objects.filter(
|
|
content_type=self.content_type, object_id=self.content_object.pk
|
|
)
|
|
|
|
return {
|
|
'queryset': Role.objects.exclude(
|
|
pk__in=acls.values('role')
|
|
),
|
|
'user': self.request.user
|
|
}
|
|
|
|
def get_success_url(self):
|
|
return self.object.get_absolute_url()
|
|
|
|
|
|
class ACLDeleteView(SingleObjectDeleteView):
|
|
model = AccessControlList
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
acl = get_object_or_404(klass=AccessControlList, pk=self.kwargs['pk'])
|
|
|
|
AccessControlList.objects.check_access(
|
|
obj=acl.content_object, permissions=(permission_acl_edit,),
|
|
user=request.user
|
|
)
|
|
|
|
return super(ACLDeleteView, self).dispatch(request, *args, **kwargs)
|
|
|
|
def get_extra_context(self):
|
|
return {
|
|
'acl': self.get_object(),
|
|
'navigation_object_list': ('object', 'acl'),
|
|
'object': self.get_object().content_object,
|
|
'title': _('Delete ACL: %s') % self.get_object(),
|
|
}
|
|
|
|
def get_post_action_redirect(self):
|
|
instance = self.get_object()
|
|
return reverse(
|
|
viewname='acls:acl_list', kwargs={
|
|
'app_label': instance.content_type.app_label,
|
|
'model': instance.content_type.model,
|
|
'object_id': instance.object_id
|
|
}
|
|
)
|
|
|
|
|
|
class ACLListView(SingleObjectListView):
|
|
def dispatch(self, request, *args, **kwargs):
|
|
self.object_content_type = get_object_or_404(
|
|
klass=ContentType, app_label=self.kwargs['app_label'],
|
|
model=self.kwargs['model']
|
|
)
|
|
|
|
try:
|
|
self.content_object = self.object_content_type.get_object_for_this_type(
|
|
pk=self.kwargs['object_id']
|
|
)
|
|
except self.object_content_type.model_class().DoesNotExist:
|
|
raise Http404
|
|
|
|
AccessControlList.objects.check_access(
|
|
obj=self.content_object, permissions=(permission_acl_view,),
|
|
user=request.user
|
|
)
|
|
|
|
return super(ACLListView, self).dispatch(request, *args, **kwargs)
|
|
|
|
def get_extra_context(self):
|
|
return {
|
|
'hide_object': True,
|
|
'no_results_icon': icon_acl_list,
|
|
'no_results_main_link': link_acl_create.resolve(
|
|
context=RequestContext(
|
|
request=self.request, dict_={
|
|
'resolved_object': self.content_object
|
|
}
|
|
)
|
|
),
|
|
'no_results_title': _(
|
|
'There are no ACLs for this object'
|
|
),
|
|
'no_results_text': _(
|
|
'ACL stands for Access Control List and is a precise method '
|
|
' to control user access to objects in the system.'
|
|
),
|
|
'object': self.content_object,
|
|
'title': _('Access control lists for: %s' % self.content_object),
|
|
}
|
|
|
|
def get_source_queryset(self):
|
|
return AccessControlList.objects.filter(
|
|
content_type=self.object_content_type,
|
|
object_id=self.content_object.pk
|
|
)
|
|
|
|
|
|
class ACLPermissionsView(AddRemoveView):
|
|
main_object_method_add = 'permissions_add'
|
|
main_object_method_remove = 'permissions_remove'
|
|
main_object_model = AccessControlList
|
|
main_object_permission = permission_acl_edit
|
|
main_object_pk_url_kwarg = 'pk'
|
|
list_added_title = _('Granted permissions')
|
|
list_available_title = _('Available permissions')
|
|
related_field = 'permissions'
|
|
|
|
def generate_choices(self, queryset):
|
|
namespaces_dictionary = {}
|
|
|
|
# Sort permissions by their translatable label
|
|
object_list = sorted(
|
|
queryset,
|
|
key=lambda permission: permission.volatile_permission.label
|
|
)
|
|
|
|
# Group permissions by namespace
|
|
for permission in object_list:
|
|
namespaces_dictionary.setdefault(
|
|
permission.volatile_permission.namespace.label,
|
|
[]
|
|
)
|
|
namespaces_dictionary[
|
|
permission.volatile_permission.namespace.label
|
|
].append(
|
|
(permission.pk, force_text(permission))
|
|
)
|
|
|
|
# Sort permissions by their translatable namespace label
|
|
return sorted(namespaces_dictionary.items())
|
|
|
|
def get_actions_extra_kwargs(self):
|
|
return {'_user': self.request.user}
|
|
|
|
def get_disabled_choices(self):
|
|
"""
|
|
Get permissions from a parent's ACLs or directly granted to the role.
|
|
We return a list since that is what the form widget's can process.
|
|
"""
|
|
return self.main_object.get_inherited_permissions().values_list(
|
|
'pk', flat=True
|
|
)
|
|
|
|
def get_extra_context(self):
|
|
return {
|
|
'acl': self.main_object,
|
|
'object': self.main_object.content_object,
|
|
'navigation_object_list': ('object', 'acl'),
|
|
'title': _('Role "%(role)s" permission\'s for "%(object)s".') % {
|
|
'role': self.main_object.role,
|
|
'object': self.main_object.content_object,
|
|
}
|
|
}
|
|
|
|
def get_list_added_help_text(self):
|
|
if self.main_object.get_inherited_permissions():
|
|
return _(
|
|
'Disabled permissions are inherited from a parent object or '
|
|
'directly granted to the role and can\'t be removed from this '
|
|
'view. Inherited permissions need to be removed from the '
|
|
'parent object\'s ACL or from them role via the Setup menu.'
|
|
)
|
|
else:
|
|
return super(ACLPermissionsView, self).get_list_added_help_text()
|
|
|
|
def get_list_added_queryset(self):
|
|
"""
|
|
Merge of permissions we hold for this object and the permissions we
|
|
hold for this object's parents via another ACL. .distinct() is added
|
|
in case the permission was added to the ACL and then added to a
|
|
parent ACL's and thus inherited and would appear twice. If
|
|
order to remove the double permission from the ACL it would need to be
|
|
remove from the parent first to enable the choice in the form,
|
|
remove it from the ACL and then re-add it to the parent ACL.
|
|
"""
|
|
queryset_acl = super(ACLPermissionsView, self).get_list_added_queryset()
|
|
|
|
return (
|
|
queryset_acl | self.main_object.get_inherited_permissions()
|
|
).distinct()
|
|
|
|
def get_secondary_object_source_queryset(self):
|
|
return ModelPermission.get_for_instance(
|
|
instance=self.main_object.content_object
|
|
)
|