Refactor acls app

This commit is contained in:
Roberto Rosario
2015-06-30 02:38:22 -04:00
parent 29447f16f4
commit 070c3b648c
14 changed files with 302 additions and 453 deletions

View File

@@ -2,15 +2,14 @@ from __future__ import unicode_literals
from django.contrib import admin
from .models import AccessEntry
from .models import AccessControlList
class AccessEntryAdmin(admin.ModelAdmin):
model = AccessEntry
class AccessControlListAdmin(admin.ModelAdmin):
list_display = ('pk', 'role', 'permission', 'content_object')
list_display_links = ('pk',)
related_lookup_fields = {
'generic': (('content_type', 'object_id'),),
}
admin.site.register(AccessEntry, AccessEntryAdmin)
admin.site.register(AccessControlList, AccessControlListAdmin)

View File

@@ -1,19 +1,12 @@
from __future__ import unicode_literals
from django.db.models.signals import post_migrate
from django.utils.translation import ugettext_lazy as _
from common import (
MayanAppConfig, menu_multi_item, menu_object, menu_secondary, menu_setup,
menu_sidebar
)
from common import MayanAppConfig, menu_object, menu_sidebar
from .links import link_acl_new, link_acl_delete, link_acl_permissions
from .models import AccessControlList
from .classes import (
AccessHolder, AccessObject, AccessObjectClass
)
from .links import (
link_acl_detail, link_acl_grant, link_acl_holder_new, link_acl_revoke
)
class ACLsApp(MayanAppConfig):
name = 'acls'
@@ -22,6 +15,5 @@ class ACLsApp(MayanAppConfig):
def ready(self):
super(ACLsApp, self).ready()
menu_multi_item.bind_links(links=[link_acl_grant, link_acl_revoke], sources=['acls:acl_detail'])
menu_object.bind_links(links=[link_acl_detail], sources=[AccessHolder])
menu_sidebar.bind_links(links=[link_acl_holder_new], sources=[AccessObject])
menu_object.bind_links(links=[link_acl_permissions, link_acl_delete], sources=[AccessControlList])
menu_sidebar.bind_links(links=[link_acl_new], sources=['acls:acl_list'])

View File

@@ -1,8 +1,6 @@
from __future__ import unicode_literals
import logging
import sys
import types
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
@@ -138,12 +136,3 @@ class AccessObject(EncapsulatedObject):
class AccessObjectClass(EncapsulatedObject):
source_object_name = 'cls'
if sys.version_info < (2, 5):
# Prior to Python 2.5, Exception was an old-style class
def subclass_exception(name, parents, unused):
return types.ClassType(name, parents, {})
else:
def subclass_exception(name, parents, module):
return type(name, parents, {'__module__': module})

View File

@@ -3,9 +3,7 @@ from __future__ import absolute_import, unicode_literals
from django import forms
from django.contrib.auth.models import User, Group
from django.utils.translation import ugettext_lazy as _
from django.utils.functional import SimpleLazyObject
from common.models import AnonymousUserSingleton
from common.utils import get_object_name
from permissions.models import Role

View File

@@ -1,14 +1,22 @@
from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
from navigation import Link
from .permissions import acls_edit_acl, acls_view_acl
from .permissions import permission_acl_view, permission_acl_edit
link_acl_list = Link(permissions=[acls_view_acl], text=_('ACLs'), view='acls:acl_list')
link_acl_detail = Link(permissions=[acls_view_acl], text=_('Details'), view='acls:acl_detail', args=['access_object.gid', 'object.gid'])
link_acl_grant = Link(permissions=[acls_edit_acl], text=_('Grant'), view='acls:acl_multiple_grant')
link_acl_revoke = Link(permissions=[acls_edit_acl], text=_('Revoke'), view='acls:acl_multiple_revoke')
link_acl_holder_new = Link(permissions=[acls_edit_acl], text=_('New holder'), view='acls:acl_holder_new', args='access_object.gid')
def get_kwargs_factory(variable_name):
def get_kwargs(context):
content_type = ContentType.objects.get_for_model(context[variable_name])
return {'app_label': '"{}"'.format(content_type.app_label), 'model': '"{}"'.format(content_type.model), 'object_id': '{}.pk'.format(variable_name)}
return get_kwargs
link_acl_delete = Link(permissions=[permission_acl_edit], tags='dangerous', text=_('Delete'), view='acls:acl_delete', args='resolved_object.pk')
link_acl_new = Link(permissions=[permission_acl_edit], text=_('New entry'), view='acls:acl_new', kwargs=get_kwargs_factory('resolved_object'))
link_acl_list = Link(permissions=[permission_acl_view], text=_('ACLs'), view='acls:acl_list', kwargs=get_kwargs_factory('resolved_object'))
link_acl_permissions = Link(permissions=[permission_acl_edit], text=_('Permissions'), view='acls:acl_permissions', args='resolved_object.pk')

View File

@@ -18,6 +18,27 @@ from .classes import AccessHolder, get_source_object
logger = logging.getLogger(__name__)
class AccessControlListManager(models.Manager):
"""
Implement a 3 tier permission system, involving a permissions, an actor
and an object
"""
def check_access(self, permission, actor, obj):
if actor.is_superuser or actor.is_staff:
return True
user_roles = []
for group in user.groups.all():
for role in group.roles.all():
user_roles.append(role)
if not self.filter(content_object=obj, permissions=permission, role__in=user_roles):
raise PermissionDenied(ugettext('Insufficient access.'))
# TODO: add filter_objects_by_access
class AccessEntryManager(models.Manager):
"""
Implement a 3 tier permission system, involving a permissions, an actor
@@ -252,80 +273,3 @@ class AccessEntryManager(models.Manager):
raise PermissionDenied
return object_list
class DefaultAccessEntryManager(models.Manager):
"""
Implement a 3 tier permission system, involving a permission, an actor
and a class or content type. This model keeps track of the access
control lists that will be added when an instance of the recorded
content type is created.
"""
def get_holders_for(self, cls):
cls = get_source_object(cls)
content_type = ContentType.objects.get_for_model(cls)
holder_list = []
#for access_entry in self.model.objects.filter(content_type=content_type):
#if access_entry.holder_object:
# Don't add references to non existant content type objects
#TODO: FIX
#entry = ClassAccessHolder.encapsulate(access_entry.holder_object)
#if entry not in holder_list:
# holder_list.append(entry)
return holder_list
def has_access(self, permission, actor, cls):
if isinstance(actor, User):
if actor.is_superuser or actor.is_staff:
return True
try:
self.model.objects.get(
permission=permission.stored_permission,
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(cls),
)
except self.model.DoesNotExist:
return False
else:
return True
def grant(self, permission, actor, cls):
"""
Grant a permission (what), (to) an actor, (on) a specific class
"""
access_entry, created = self.model.objects.get_or_create(
permission=permission,
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(cls),
)
return created
def revoke(self, permission, actor, cls):
"""
Revoke a permission (what), (from) an actor, (on) a specific class
"""
try:
access_entry = self.model.objects.get(
permission=permission,
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(cls),
)
access_entry.delete()
return True
except self.model.DoesNotExist:
return False
def get_holder_permissions_for(self, cls, actor):
if isinstance(actor, User):
if actor.is_superuser or actor.is_staff:
return Permission.all()
actor_type = ContentType.objects.get_for_model(actor)
content_type = ContentType.objects.get_for_model(cls)
return [access.permission for access in self.model.objects.filter(content_type=content_type, holder_type=actor_type, holder_id=actor.pk)]

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('permissions', '0002_auto_20150628_0533'),
('acls', '0001_initial'),
]
operations = [
migrations.DeleteModel(
name='CreatorSingleton',
),
migrations.RemoveField(
model_name='defaultaccessentry',
name='content_type',
),
migrations.RemoveField(
model_name='defaultaccessentry',
name='holder_type',
),
migrations.RemoveField(
model_name='defaultaccessentry',
name='permission',
),
migrations.DeleteModel(
name='DefaultAccessEntry',
),
migrations.RemoveField(
model_name='accessentry',
name='holder_id',
),
migrations.RemoveField(
model_name='accessentry',
name='holder_type',
),
migrations.AddField(
model_name='accessentry',
name='role',
field=models.ForeignKey(default=1, verbose_name='Role', to='permissions.Role'),
preserve_default=False,
),
]

View File

@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0001_initial'),
('permissions', '0002_auto_20150628_0533'),
('acls', '0002_auto_20150629_1852'),
]
operations = [
migrations.CreateModel(
name='AccessControlList',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('object_id', models.PositiveIntegerField()),
('content_type', models.ForeignKey(related_name='object_content_type', to='contenttypes.ContentType')),
('permissions', models.ManyToManyField(related_name='acls', verbose_name='Permissions', to='permissions.StoredPermission')),
('role', models.ForeignKey(related_name='acls', verbose_name='Role', to='permissions.Role')),
],
options={
'verbose_name': 'Access entry',
'verbose_name_plural': 'Access entries',
},
bases=(models.Model,),
),
migrations.AlterField(
model_name='accessentry',
name='content_type',
field=models.ForeignKey(related_name='object_content_type_1', to='contenttypes.ContentType'),
preserve_default=True,
),
]

View File

@@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('acls', '0003_auto_20150630_0442'),
]
operations = [
migrations.AlterUniqueTogether(
name='accesscontrollist',
unique_together=set([('content_type', 'object_id', 'role')]),
),
]

View File

@@ -6,19 +6,46 @@ from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _, ugettext
from solo.models import SingletonModel
from django.utils.translation import ugettext_lazy as _
from permissions.models import Role, StoredPermission
from .api import get_classes
from .classes import AccessObjectClass
from .managers import AccessEntryManager, DefaultAccessEntryManager
from .managers import AccessControlListManager, AccessEntryManager
logger = logging.getLogger(__name__)
@python_2_unicode_compatible
class AccessControlList(models.Model):
"""
Model that hold the permission, object, actor relationship
"""
content_type = models.ForeignKey(
ContentType,
related_name='object_content_type'
)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey(
ct_field='content_type',
fk_field='object_id'
)
# TODO: limit choices to the permissions valid for the content_object
permissions = models.ManyToManyField(StoredPermission, blank=True, related_name='acls', verbose_name=_('Permissions'))
role = models.ForeignKey(Role, related_name='acls', verbose_name=_('Role'))
objects = AccessControlListManager()
class Meta:
unique_together = ('content_type', 'object_id', 'role')
verbose_name = _('Access entry')
verbose_name_plural = _('Access entries')
def __str__(self):
return '{} <=> {}'.format(self.content_object, self.role)
# TODO: remove
@python_2_unicode_compatible
class AccessEntry(models.Model):
"""
@@ -28,7 +55,7 @@ class AccessEntry(models.Model):
role = models.ForeignKey(Role, verbose_name=_('Role'))
content_type = models.ForeignKey(
ContentType,
related_name='object_content_type'
related_name='object_content_type_1'
)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey(

View File

@@ -4,7 +4,7 @@ from django.utils.translation import ugettext_lazy as _
from permissions import PermissionNamespace
acls_namespace = PermissionNamespace('acls', _('Access control lists'))
namespace = PermissionNamespace('acls', _('Access control lists'))
acls_edit_acl = acls_namespace.add_permission(name='acl_edit', label=_('Edit ACLs'))
acls_view_acl = acls_namespace.add_permission(name='acl_view', label=_('View ACLs'))
permission_acl_edit = namespace.add_permission(name='acl_edit', label=_('Edit ACLs'))
permission_acl_view = namespace.add_permission(name='acl_view', label=_('View ACLs'))

View File

@@ -2,13 +2,12 @@ from __future__ import unicode_literals
from django.conf.urls import patterns, url
from .views import ACLCreateView, ACLDeleteView, ACLListView, ACLPermissionsView
urlpatterns = patterns(
'acls.views',
url(r'^new_holder_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_new_holder_for', name='acl_new_holder_for'),
url(r'^list_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_list', name='acl_list'),
url(r'^details/(?P<access_object_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_detail', name='acl_detail'),
url(r'^holder/new/(?P<access_object_gid>[.\w]+)/$', 'acl_holder_new', name='acl_holder_new'),
url(r'^multiple/grant/$', 'acl_grant', name='acl_multiple_grant'),
url(r'^multiple/revoke/$', 'acl_revoke', name='acl_multiple_revoke'),
url(r'^(?P<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/new/$', ACLCreateView.as_view(), name='acl_new'),
url(r'^(?P<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/list/$', ACLListView.as_view(), name='acl_list'),
url(r'^(?P<pk>\d+)/delete/$', ACLDeleteView.as_view(), name='acl_delete'),
url(r'^(?P<pk>\d+)/permissions/$', ACLPermissionsView.as_view(), name='acl_permissions'),
)

View File

@@ -1,29 +1,24 @@
from __future__ import absolute_import, unicode_literals
import itertools
import logging
from json import loads
from django.conf import settings
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.utils.http import urlencode
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _
from common.utils import encapsulate
from common.widgets import two_state_template
from permissions import Permission
from common.views import (
AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectListView
)
from permissions import Permission, PermissionNamespace
from permissions.models import StoredPermission
from .api import get_class_permissions_for
from .classes import AccessHolder, AccessObject, AccessObjectClass
from .forms import ClassHolderSelectionForm, HolderSelectionForm
from .models import AccessEntry
from .permissions import acls_edit_acl, acls_view_acl
from .widgets import object_indentifier
from .models import AccessControlList
from .permissions import permission_acl_edit, permission_acl_view
logger = logging.getLogger(__name__)
@@ -32,327 +27,143 @@ def _permission_titles(permission_list):
return ', '.join([unicode(permission) for permission in permission_list])
def acl_list_for(request, obj, extra_context=None):
try:
Permission.check_permissions(request.user, [acls_view_acl])
except PermissionDenied:
AccessEntry.objects.check_access(acls_view_acl, request.user, obj)
class ACLListView(SingleObjectListView):
def dispatch(self, request, *args, **kwargs):
self.content_type = get_object_or_404(ContentType, app_label=self.kwargs['app_label'], model=self.kwargs['model'])
logger.debug('obj: %s', obj)
try:
self.content_object = self.content_type.get_object_for_this_type(pk=self.kwargs['object_id'])
except self.content_type.model_class().DoesNotExist:
raise Http404
context = {
'object_list': AccessEntry.objects.get_holders_for(obj),
'title': _('Access control lists for: %s' % obj),
'extra_columns': [
{'name': _('Holder'), 'attribute': encapsulate(lambda x: object_indentifier(x.source_object))},
{'name': _('Permissions'), 'attribute': encapsulate(lambda x: _permission_titles(AccessEntry.objects.get_holder_permissions_for(obj, x.source_object, db_only=True)))},
],
'hide_object': True,
'access_object': AccessObject.encapsulate(obj),
'object': obj,
'navigation_object_list': ['object', 'access_object'],
}
try:
Permission.check_permissions(request.user, permissions=(permission_acl_view,))
except PermissionDenied:
AccessControlList.objects.check_access(permission_acl_view, request.user, self.content_object)
if extra_context:
context.update(extra_context)
return super(ACLListView, self).dispatch(request, *args, **kwargs)
return render_to_response('appearance/generic_list.html', context,
context_instance=RequestContext(request))
def get_queryset(self):
return AccessControlList.objects.filter(content_type=self.content_type, object_id=self.content_object.pk)
def acl_list(request, app_label, model_name, object_id):
ct = get_object_or_404(ContentType, app_label=app_label, model=model_name)
obj = get_object_or_404(ct.get_object_for_this_type, pk=object_id)
return acl_list_for(request, obj)
def acl_detail(request, access_object_gid, holder_object_gid):
try:
holder = AccessHolder.get(gid=holder_object_gid)
access_object = AccessObject.get(gid=access_object_gid)
except ObjectDoesNotExist:
raise Http404
# return acl_detail_for(request, holder.source_object, access_object.source_object)
return acl_detail_for(request, holder, access_object)
def acl_detail_for(request, actor, obj):
try:
Permission.check_permissions(request.user, [acls_view_acl])
except PermissionDenied:
AccessEntry.objects.check_accesses([acls_view_acl], actor, obj)
permission_list = get_class_permissions_for(obj.source_object)
# TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware)
subtemplates_list = [
{
'name': 'appearance/generic_list_subtemplate.html',
'context': {
'title': _('Permissions available to: %(actor)s for %(obj)s' % {
'actor': actor,
'obj': obj
}
),
'object_list': permission_list,
def get_context_data(self, **kwargs):
context = super(ACLListView, self).get_context_data(**kwargs)
context.update(
{
'hide_object': True,
'object': self.content_object,
'title': _('Access control lists for: %s' % self.content_object),
'extra_columns': [
{'name': _('Namespace'), 'attribute': 'namespace'},
{'name': _('Label'), 'attribute': 'label'},
{
'name': _('Has permission'),
'attribute': encapsulate(lambda permission: two_state_template(AccessEntry.objects.has_access(permission, actor, obj, db_only=True)))
'name': _('Role'),
'attribute': 'role'
},
{
'name': _('Permissions'),
'attribute': encapsulate(lambda x: _permission_titles(x.permissions.all()))
},
],
'hide_object': True,
}
},
]
)
context = {
'object': obj.source_object,
'subtemplates_list': subtemplates_list,
'multi_select_item_properties': {
'permission_pk': lambda x: x.pk,
'holder_gid': lambda x: actor.gid,
'object_gid': lambda x: obj.gid,
},
'access_object': obj,
'navigation_object_list': ['object', 'access_object'],
'read_only': True,
}
return render_to_response('appearance/generic_form.html', context,
context_instance=RequestContext(request))
return context
def acl_grant(request):
items_property_list = loads(request.GET.get('items_property_list', []))
class ACLCreateView(SingleObjectCreateView):
model = AccessControlList
fields = ('role',)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
def dispatch(self, request, *args, **kwargs):
content_type = get_object_or_404(ContentType, app_label=self.kwargs['app_label'], model=self.kwargs['model'])
items = {}
title_suffix = []
navigation_object = None
navigation_object_count = 0
for item_properties in items_property_list:
try:
permission = Permission.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist:
self.content_object = content_type.get_object_for_this_type(pk=self.kwargs['object_id'])
except content_type.model_class().DoesNotExist:
raise Http404
try:
requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object = AccessObject.get(gid=item_properties['object_gid'])
except ObjectDoesNotExist:
raise Http404
try:
Permission.check_permissions(request.user, [acls_edit_acl])
Permission.check_permissions(request.user, permissions=(permission_acl_edit,))
except PermissionDenied:
try:
AccessEntry.objects.check_access(acls_edit_acl, request.user, access_object)
except PermissionDenied:
raise
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
AccessControlList.objects.check_access(permission_acl_edit, request.user, self.content_object)
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(', ').join(['"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(' for %s') % obj)
title_suffix.append(_(' to %s') % requester)
return super(ACLCreateView, self).dispatch(request, *args, **kwargs)
if len(items_property_list) == 1:
title_prefix = _('Are you sure you wish to grant the permission %(title_suffix)s?')
else:
title_prefix = _('Are you sure you wish to grant the permissions %(title_suffix)s?')
def form_valid(self, form):
instance = form.save(commit=False)
instance.content_object = self.content_object
instance.save()
if request.method == 'POST':
for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items():
for permission in permissions:
if AccessEntry.objects.grant(permission, requester.source_object, obj.source_object):
messages.success(request, _('Permission "%(permission)s" granted to %(actor)s for %(object)s.') % {
'permission': permission,
'actor': requester,
'object': obj
})
else:
messages.warning(request, _('%(actor)s, already had the permission "%(permission)s" granted for %(object)s.') % {
'actor': requester,
'permission': permission,
'object': obj,
})
return super(ACLCreateView, self).form_valid(form)
return HttpResponseRedirect(next)
def get_context_data(self, **kwargs):
context = super(ACLCreateView, self).get_context_data(**kwargs)
context.update(
{
'object': self.content_object,
'title': _('New access control lists for: %s' % self.content_object),
}
)
context = {
'previous': previous,
'next': next,
}
context['title'] = title_prefix % {
'title_suffix': ''.join(title_suffix),
}
logger.debug('navigation_object_count: %d', navigation_object_count)
logger.debug('navigation_object: %s', navigation_object)
if navigation_object_count == 1:
context['object'] = navigation_object.source_object
return render_to_response('appearance/generic_confirm.html', context,
context_instance=RequestContext(request))
return context
def acl_revoke(request):
items_property_list = loads(request.GET.get('items_property_list', []))
class ACLDeleteView(SingleObjectDeleteView):
model = AccessControlList
object_permission = permission_acl_edit
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
def get_context_data(self, **kwargs):
context = super(ACLDeleteView, self).get_context_data(**kwargs)
context.update(
{
'object': self.get_object().content_object,
}
)
items = {}
title_suffix = []
navigation_object = None
navigation_object_count = 0
for item_properties in items_property_list:
try:
permission = Permission.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist:
raise Http404
try:
requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object = AccessObject.get(gid=item_properties['object_gid'])
except ObjectDoesNotExist:
raise Http404
try:
Permission.check_permissions(request.user, [acls_edit_acl])
except PermissionDenied:
try:
AccessEntry.objects.check_access(acls_edit_acl, request.user, access_object)
except PermissionDenied:
raise
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(', ').join(['"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(' for %s') % obj)
title_suffix.append(_(' from %s') % requester)
if len(items_property_list) == 1:
title_prefix = _('Are you sure you wish to revoke the permission %(title_suffix)s?')
else:
title_prefix = _('Are you sure you wish to revoke the permissions %(title_suffix)s?')
if request.method == 'POST':
for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items():
for permission in permissions:
if AccessEntry.objects.revoke(permission, requester.source_object, obj.source_object):
messages.success(request, _('Permission "%(permission)s" revoked of %(actor)s for %(object)s.') % {
'permission': permission,
'actor': requester,
'object': obj
})
else:
messages.warning(request, _('%(actor)s, didn\'t had the permission "%(permission)s" for %(object)s.') % {
'actor': requester,
'permission': permission,
'object': obj,
})
return HttpResponseRedirect(next)
context = {
'previous': previous,
'next': next,
}
context['title'] = title_prefix % {
'title_suffix': ''.join(title_suffix),
}
logger.debug('navigation_object_count: %d', navigation_object_count)
logger.debug('navigation_object: %s', navigation_object)
if navigation_object_count == 1:
context['object'] = navigation_object.source_object
return render_to_response('appearance/generic_confirm.html', context,
context_instance=RequestContext(request))
return context
def acl_new_holder_for(request, obj, extra_context=None, navigation_object=None):
try:
Permission.check_permissions(request.user, [acls_edit_acl])
except PermissionDenied:
AccessEntry.objects.check_access(acls_edit_acl, request.user, obj)
class ACLPermissionsView(AssignRemoveView):
grouped = True
object_permission = permission_acl_edit
left_list_title = _('Available permissions')
right_list_title = _('Granted permissions')
if request.method == 'POST':
form = HolderSelectionForm(request.POST)
if form.is_valid():
try:
access_object = AccessObject.encapsulate(obj)
access_holder = AccessHolder.get(form.cleaned_data['holder_gid'])
def add(self, item):
permission = get_object_or_404(StoredPermission, pk=item)
self.get_object().permissions.add(permission)
query_string = {'navigation_object': navigation_object}
def get_object(self):
return get_object_or_404(AccessControlList, pk=self.kwargs['pk'])
return HttpResponseRedirect(
'%s?%s' % (
reverse('acls:acl_detail', args=[access_object.gid, access_holder.gid]),
urlencode(query_string)
)
)
except ObjectDoesNotExist:
raise Http404
else:
form = HolderSelectionForm()
def left_list(self):
results = []
for namespace, permissions in itertools.groupby(StoredPermission.objects.exclude(id__in=self.get_object().permissions.values_list('pk', flat=True)), lambda entry: entry.namespace):
permission_options = [(unicode(permission.pk), permission) for permission in permissions]
results.append((PermissionNamespace.get(namespace), permission_options))
context = {
'form': form,
'title': _('Add new holder for: %s') % obj,
'submit_label': _('Select'),
'object': obj,
'access_object': AccessObject.encapsulate(obj),
'navigation_object_list': ['object', 'access_object'],
}
return results
if extra_context:
context.update(extra_context)
def right_list(self):
results = []
for namespace, permissions in itertools.groupby(self.get_object().permissions.all(), lambda entry: entry.namespace):
permission_options = [(unicode(permission.pk), permission) for permission in permissions]
results.append((PermissionNamespace.get(namespace), permission_options))
return render_to_response('appearance/generic_form.html', context,
context_instance=RequestContext(request))
return results
def get_context_data(self, **kwargs):
context = super(ACLPermissionsView, self).get_context_data(**kwargs)
context.update(
{
'object': self.get_object().content_object,
'title': _('Role "%(role)s" permission\'s for "%(object)s"') % {
'role': self.get_object().role,
'object': self.get_object().content_object,
}
}
)
return context
def acl_holder_new(request, access_object_gid):
try:
access_object = AccessObject.get(gid=access_object_gid)
except ObjectDoesNotExist:
raise Http404
return acl_new_holder_for(request, access_object.source_object)
def remove(self, item):
permission = get_object_or_404(StoredPermission, pk=item)
self.get_object().permissions.remove(permission)

View File

@@ -1,20 +0,0 @@
from __future__ import unicode_literals
from django.utils.safestring import mark_safe
from django.contrib.contenttypes.models import ContentType
from django.db.models.base import ModelBase
def object_indentifier(obj):
content_type = ContentType.objects.get_for_model(obj)
ct_fullname = '%s.%s' % (content_type.app_label, content_type.name)
if isinstance(obj, ModelBase):
label = getattr(obj._meta, 'verbose_name_plural', unicode(content_type))
else:
if ct_fullname == 'auth.user':
label = obj.get_full_name()
else:
label = unicode(obj)
return mark_safe('<span>{}</span>'.format(label))