ACL app updates, display generic object proper ACL holders list with content type icon widget

This commit is contained in:
Roberto Rosario
2011-10-24 20:34:01 -04:00
parent 0cb468ca9b
commit acd23eebab
5 changed files with 96 additions and 28 deletions

View File

@@ -1,9 +1,5 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
#from documents.models import Document
from navigation.api import register_links, register_multi_item_links
from project_setup.api import register_setup
from permissions.api import register_permission, set_namespace_title from permissions.api import register_permission, set_namespace_title
@@ -15,7 +11,3 @@ register_permission(ACLS_EDIT_ACL)
register_permission(ACLS_VIEW_ACL) register_permission(ACLS_VIEW_ACL)
acl_list = {'text': _(u'ACLs'), 'view': 'acl_list', 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]} acl_list = {'text': _(u'ACLs'), 'view': 'acl_list', 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
#register_links(Document, [acl_list], menu_name='form_header')

7
apps/acls/literals.py Normal file
View File

@@ -0,0 +1,7 @@
CONTENT_TYPE_ICON_MAP = {
'auth.user': 'user',
'auth.group': 'group',
'documents.document': 'page',
'permissions.role': 'medal_gold_1',
}

View File

@@ -3,21 +3,20 @@ 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 from django.contrib.auth.models import User
#from django.shortcuts import get_object_or_404
#from django.utils.translation import ugettext
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from permissions.models import Permission from permissions.models import Permission
from acls.widgets import object_w_content_type_icon
class AccessEntryManager(models.Manager): class AccessEntryManager(models.Manager):
def grant(self, permission, requester, obj): def grant(self, permission, requester, obj):
""" """
Grant a permission (what), (to) a requester, (on) a specific object Grant a permission (what), (to) a requester, (on) a specific object
""" """
access_entry, created = AccessEntry.objects.get_or_create( access_entry, created = self.model.objects.get_or_create(
permission=permission, permission=permission,
holder_type=ContentType.objects.get_for_model(requester), holder_type=ContentType.objects.get_for_model(requester),
holder_id=requester.pk, holder_id=requester.pk,
@@ -28,7 +27,7 @@ class AccessEntryManager(models.Manager):
def revoke(self, permission, holder, obj): def revoke(self, permission, holder, obj):
try: try:
access_entry = AccessEntry.objects.get( access_entry = self.model.objects.get(
permission=permission, permission=permission,
holder_type=ContentType.objects.get_for_model(holder), holder_type=ContentType.objects.get_for_model(holder),
holder_id=holder.pk, holder_id=holder.pk,
@@ -37,7 +36,7 @@ class AccessEntryManager(models.Manager):
) )
access_entry.delete() access_entry.delete()
return True return True
except AccessEntry.DoesNotExist: except self.model.DoesNotExist:
return False return False
def check_accesses(self, permission_list, requester, obj): def check_accesses(self, permission_list, requester, obj):
@@ -45,7 +44,7 @@ class AccessEntryManager(models.Manager):
permission = get_object_or_404(Permission, permission = get_object_or_404(Permission,
namespace=permission_item['namespace'], name=permission_item['name']) namespace=permission_item['namespace'], name=permission_item['name'])
try: try:
access_entry = AccessEntry.objects.get( access_entry = self.model.objects.get(
permission=permission, permission=permission,
holder_type=ContentType.objects.get_for_model(requester), holder_type=ContentType.objects.get_for_model(requester),
holder_id=requester.pk, holder_id=requester.pk,
@@ -53,26 +52,56 @@ class AccessEntryManager(models.Manager):
object_id=obj.pk object_id=obj.pk
) )
return True return True
except AccessEntry.DoesNotExist: except self.model.DoesNotExist:
raise PermissionDenied(ugettext(u'Insufficient permissions.')) raise PermissionDenied(ugettext(u'Insufficient permissions.'))
def get_acl_url(self, obj): def get_acl_url(self, obj):
content_type = ContentType.objects.get_for_model(obj.__class__) content_type = ContentType.objects.get_for_model(obj)
return reverse('acl_list', args=[content_type.app_label, content_type.model, obj.pk]) return reverse('acl_list', args=[content_type.app_label, content_type.model, obj.pk])
def get_holders_for(self, obj):
content_type = ContentType.objects.get_for_model(obj)
holder_list = []
for access_entry in self.model.objects.filter(content_type=content_type, object_id=obj.pk):
entry = {
'object': access_entry.holder_object,
'label': '%s: %s' % (access_entry.holder_type, access_entry.holder_object),
'widget': object_w_content_type_icon(access_entry.holder_object),
}
if entry not in holder_list:
holder_list.append(entry)
return holder_list
def get_acls_for_holder(self, obj, holder):
holder_type = ContentType.objects.get_for_model(holder)
content_type = ContentType.objects.get_for_model(obj)
return [access.permission for access in self.model.objects.filter(content_type=content_type, object_id=obj.pk, holder_type=holder_type, holder_id=holder.pk)]
class AccessEntry(models.Model): class AccessEntry(models.Model):
permission = models.ForeignKey(Permission, verbose_name=_(u'permission')) permission = models.ForeignKey(Permission, verbose_name=_(u'permission'))
holder_type = models.ForeignKey(ContentType,
related_name='access_holder',
limit_choices_to={'model__in': ('user', 'group', 'role')})
holder_id = models.PositiveIntegerField()
holder_object = generic.GenericForeignKey(ct_field='holder_type', fk_field='holder_id')
content_type = models.ForeignKey(ContentType, holder_type = models.ForeignKey(
related_name='object_content_type') ContentType,
related_name='access_holder',
limit_choices_to={'model__in': ('user', 'group', 'role')}
)
holder_id = models.PositiveIntegerField()
holder_object = generic.GenericForeignKey(
ct_field='holder_type',
fk_field='holder_id'
)
content_type = models.ForeignKey(
ContentType,
related_name='object_content_type'
)
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey(ct_field='content_type', fk_field='object_id') content_object = generic.GenericForeignKey(
ct_field='content_type',
fk_field='object_id'
)
objects = AccessEntryManager() objects = AccessEntryManager()

View File

@@ -9,19 +9,33 @@ from django.views.generic.create_update import create_object, delete_object, upd
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from permissions.api import check_permissions, namespace_titles from permissions.api import check_permissions, namespace_titles, get_permission_label
from common.utils import generate_choices_w_labels, encapsulate
from acls import ACLS_EDIT_ACL, ACLS_VIEW_ACL from acls import ACLS_EDIT_ACL, ACLS_VIEW_ACL
from acls.models import AccessEntry
def _permission_titles(permission_list):
return u', '.join([get_permission_label(permission) for permission in permission_list])
def acl_list_for(request, obj, extra_context=None): def acl_list_for(request, obj, extra_context=None):
check_permissions(request.user, [ACLS_VIEW_ACL]) check_permissions(request.user, [ACLS_VIEW_ACL])
context = { context = {
'object_list': [], 'object_list': AccessEntry.objects.get_holders_for(obj),
'title': _(u'access control lists for: %s' % obj), 'title': _(u'access control lists for: %s' % obj),
#'multi_select_as_buttons': True, #'multi_select_as_buttons': True,
#'hide_links': True, #'hide_links': True,
'extra_columns': [
#{'name': _(u'holder'), 'attribute': 'label'},
{'name': _(u'holder'), 'attribute': 'widget'},
{'name': _(u'permissions'), 'attribute': encapsulate(lambda x: _permission_titles(AccessEntry.objects.get_acls_for_holder(obj, x['object'])))},
#{'name': _(u'arguments'), 'attribute': 'arguments'}
],
#'hide_link': True,
'hide_object': True,
} }
if extra_context: if extra_context:

26
apps/acls/widgets.py Normal file
View File

@@ -0,0 +1,26 @@
from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe
from django import forms
from django.forms.util import flatatt
from django.utils.html import conditional_escape
from django.utils.encoding import force_unicode
from django.contrib.contenttypes.models import ContentType
from acls.literals import CONTENT_TYPE_ICON_MAP
def content_type_icon(content_type):
return mark_safe(u'<span class="famfam active famfam-%s"></span>' % CONTENT_TYPE_ICON_MAP.get('%s.%s' % (content_type.app_label, content_type.name), 'help'))
def object_w_content_type_icon(obj):
content_type = ContentType.objects.get_for_model(obj)
ct_fullname = '%s.%s' % (content_type.app_label, content_type.name)
if ct_fullname == 'auth.user':
label = obj.get_full_name()
else:
label = unicode(obj)
return mark_safe('%s<span>%s</span>' % (content_type_icon(content_type), label))