Added encapsulation and semi working acl edititing view

This commit is contained in:
Roberto Rosario
2011-10-27 07:44:51 -04:00
parent d45ad40233
commit 3f9e79f0bc
4 changed files with 255 additions and 116 deletions
+6
View File
@@ -1,6 +1,9 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from permissions.api import register_permission, set_namespace_title from permissions.api import register_permission, set_namespace_title
from navigation.api import register_links
from acls.models import AccessHolder
ACLS_EDIT_ACL = {'namespace': 'acls', 'name': 'acl_edit', 'label': _(u'Edit ACLs')} ACLS_EDIT_ACL = {'namespace': 'acls', 'name': 'acl_edit', 'label': _(u'Edit ACLs')}
@@ -11,3 +14,6 @@ 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]}
acl_detail = {'text': _(u'Edit'), 'view': 'acl_detail', 'args': ['access_object.gid', 'object.gid'], 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
register_links(AccessHolder, [acl_detail])
+155 -86
View File
@@ -5,109 +5,178 @@ from django.contrib.contenttypes import generic
from django.contrib.auth.models import User from django.contrib.auth.models import User
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 django.core.exceptions import ObjectDoesNotExist
from permissions.models import Permission from permissions.models import Permission
from acls.widgets import object_w_content_type_icon #from acls.widgets import object_w_content_type_icon
_encapsulation_cache = {}
class EncapsulatedObject(object):
source_object_name = u'source_object'
'''
@classmethod
def get_by_ct(cls, content_type, object_id):
"""
Return a single ACLHolder instance corresponding to the content
type object given as argument
"""
try:
return AccessHolder(
holder_object=ContentType.objects.get(content_type=access_entry.holder_type, object_id=access_entry.holder_id)
)
except ContentType.DoesNotExits:
raise ObjectDoesNotExist
'''
@classmethod
def set_source_object_name(cls, new_name):
cls.source_object_name = new_name
@classmethod
def encapsulate(cls, source_object):
if source_object not in _encapsulation_cache:
encapsulated_object = cls(source_object)
_encapsulation_cache[source_object] = encapsulated_object
else:
return _encapsulation_cache[source_object]
return encapsulated_object
@classmethod
def get(cls, gid):
app_label, model, pk = gid.split('.')
content_type = ContentType.objects.get(app_label=app_label, model=model)
source_object = content_type.get_object_for_this_type(pk=pk)
return cls.encapsulate(source_object)
def __init__(self, source_object):
content_type = ContentType.objects.get_for_model(source_object)
self.gid = '%s.%s.%s' % (content_type.app_label, content_type.name, source_object.pk)
#self.source_object_name = self.__class__.source_object_name
#self.source_object = source_object
setattr(self, self.__class__.source_object_name, source_object)
def __unicode__(self):
return unicode(getattr(self, self.__class__.source_object_name, None))
def __repr__(self):
return self.__unicode__()
@property
def source_object(self):
return getattr(self, self.__class__.source_object_name, None)
class AccessHolder(EncapsulatedObject):
source_object_name = u'holder_object'
class AccessObject(EncapsulatedObject):
source_object_name = u'obj'
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 = self.model.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,
content_type=ContentType.objects.get_for_model(obj), content_type=ContentType.objects.get_for_model(obj),
object_id=obj.pk object_id=obj.pk
) )
return created return created
def revoke(self, permission, holder, obj): def revoke(self, permission, holder, obj):
try: try:
access_entry = self.model.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,
content_type=ContentType.objects.get_for_model(obj), content_type=ContentType.objects.get_for_model(obj),
object_id=obj.pk object_id=obj.pk
) )
access_entry.delete() access_entry.delete()
return True return True
except self.model.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):
for permission_item in permission_list: for permission_item in permission_list:
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 = self.model.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,
content_type=ContentType.objects.get_for_model(obj), content_type=ContentType.objects.get_for_model(obj),
object_id=obj.pk object_id=obj.pk
) )
return True return True
except self.model.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) 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): def get_holders_for(self, obj):
content_type = ContentType.objects.get_for_model(obj) content_type = ContentType.objects.get_for_model(obj)
holder_list = [] holder_list = []
for access_entry in self.model.objects.filter(content_type=content_type, object_id=obj.pk): for access_entry in self.model.objects.filter(content_type=content_type, object_id=obj.pk):
entry = { #entry = {
'object': access_entry.holder_object, # 'object': access_entry.holder_object,
'label': '%s: %s' % (access_entry.holder_type, 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), # #'widget': object_w_content_type_icon(access_entry.holder_object),
} # 'compound_id': '9',
if entry not in holder_list: #}
holder_list.append(entry) #entry = ACLHolder.objects.get(content_type=access_entry.holder_type, object_id=access_entry.holder_id)
#entry = access_entry.holder_object
entry = AccessHolder.encapsulate(access_entry.holder_object)
return holder_list if entry not in holder_list:
holder_list.append(entry)
def get_acls_for_holder(self, obj, holder): return holder_list
holder_type = ContentType.objects.get_for_model(holder)
content_type = ContentType.objects.get_for_model(obj) def get_permissions_for_holder(self, obj, holder):
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)] 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( holder_type = models.ForeignKey(
ContentType, ContentType,
related_name='access_holder', related_name='access_holder',
limit_choices_to={'model__in': ('user', 'group', 'role')} limit_choices_to={'model__in': ('user', 'group', 'role')}
) )
holder_id = models.PositiveIntegerField() holder_id = models.PositiveIntegerField()
holder_object = generic.GenericForeignKey( holder_object = generic.GenericForeignKey(
ct_field='holder_type', ct_field='holder_type',
fk_field='holder_id' fk_field='holder_id'
) )
content_type = models.ForeignKey( content_type = models.ForeignKey(
ContentType, ContentType,
related_name='object_content_type' related_name='object_content_type'
) )
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey( content_object = generic.GenericForeignKey(
ct_field='content_type', ct_field='content_type',
fk_field='object_id' fk_field='object_id'
) )
objects = AccessEntryManager() objects = AccessEntryManager()
class Meta: class Meta:
verbose_name = _(u'access entry') verbose_name = _(u'access entry')
verbose_name_plural = _(u'access entries') verbose_name_plural = _(u'access entries')
def __unicode__(self): def __unicode__(self):
return u'%s: %s' % (self.content_type, self.content_object) return u'%s: %s' % (self.content_type, self.content_object)
+2
View File
@@ -2,6 +2,8 @@ from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('acls.views', urlpatterns = patterns('acls.views',
url(r'^list_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_list', (), 'acl_list'), url(r'^list_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_list', (), 'acl_list'),
#url(r'^object/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/holder/(?P<holder_app_label>[-\w]+)/(?P<holder_model_name>[-\w]+)/(?P<holder_id>\d+)/$', 'acl_detail', (), 'acl_detail'),
url(r'^details/(?P<access_object_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_detail', (), 'acl_detail'),
# url(r'^role/list/$', 'role_list', (), 'role_list'), # url(r'^role/list/$', 'role_list', (), 'role_list'),
# url(r'^role/create/$', 'role_create', (), 'role_create'), # url(r'^role/create/$', 'role_create', (), 'role_create'),
+87 -25
View File
@@ -9,45 +9,107 @@ 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, get_permission_label from permissions.api import check_permissions, namespace_titles, get_permission_label, get_permission_namespace_label
from common.utils import generate_choices_w_labels, encapsulate 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 from acls.models import AccessEntry, AccessObject, AccessHolder
from acls.widgets import object_w_content_type_icon
def _permission_titles(permission_list): def _permission_titles(permission_list):
return u', '.join([get_permission_label(permission) for permission in 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 = { ct = ContentType.objects.get_for_model(obj)
'object_list': AccessEntry.objects.get_holders_for(obj),
'title': _(u'access control lists for: %s' % obj),
#'multi_select_as_buttons': 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: context = {
context.update(extra_context) #'app_label': ct.app_label,
#'model_name': ct.model,
'object_list': AccessEntry.objects.get_holders_for(obj),
'title': _(u'access control lists for: %s' % obj),
#'multi_select_as_buttons': True,
#'hide_links': True,
'extra_columns': [
#{'name': _(u'holder'), 'attribute': 'label'},
#{'name': _(u'obj'), 'attribute': 'holder_object'},
{'name': _(u'gid'), 'attribute': 'gid'},
{'name': _(u'holder'), 'attribute': encapsulate(lambda x: object_w_content_type_icon(x.source_object))},
{'name': _(u'permissions'), 'attribute': encapsulate(lambda x: _permission_titles(AccessEntry.objects.get_permissions_for_holder(obj, x.source_object)))},
#{'name': _(u'arguments'), 'attribute': 'arguments'}
],
#'hide_link': True,
#'hide_object': True,
'access_object': AccessObject.encapsulate(obj)
}
return render_to_response('generic_list.html', context, if extra_context:
context_instance=RequestContext(request)) context.update(extra_context)
return render_to_response('generic_list.html', context,
context_instance=RequestContext(request))
def acl_list(request, app_label, model_name, object_id): def acl_list(request, app_label, model_name, object_id):
ct = get_object_or_404(ContentType, app_label=app_label, model=model_name) ct = get_object_or_404(ContentType, app_label=app_label, model=model_name)
obj = get_object_or_404(ContentType.user_type.get_object_for_this_type, pk=object_id) obj = get_object_or_404(ct.get_object_for_this_type, pk=object_id)
return acl_list_for(request, obj) return acl_list_for(request, obj)
#def acl_detail(request, app_label, model_name, object_id, holder_app_label, holder_model_name, holder_id):
def acl_detail(request, access_object_gid, holder_object_gid):
#check_permissions(request.user, [PERMISSION_PERMISSION_GRANT, PERMISSION_PERMISSION_REVOKE])
#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)
#ct = get_object_or_404(ContentType, app_label=holder_app_label, model=holder_model_name)
#holder = get_object_or_404(ct.get_object_for_this_type, pk=holder_id)
#access_entry = get_object_or_404(AccessEntry, pk=access_entry_id)
#holder =
#role = get_object_or_404(Role, pk=role_id)
#form = RoleForm_view(instance=role)
#role_permissions_list = Permission.objects.get_for_holder(role)
#try;
holder = AccessHolder.get(gid=holder_object_gid)
access_object = AccessObject.get(gid=access_object_gid)
#raise 404
subtemplates_list = [
{
'name': u'generic_list_subtemplate.html',
'context': {
'title': _(u'permissions held by: %s for %s' % (holder, access_object)),
'object_list': AccessEntry.objects.get_permissions_for_holder(access_object.source_object, holder.source_object),
'extra_columns': [
{'name': _(u'namespace'), 'attribute': encapsulate(lambda x: get_permission_namespace_label(x))},
{'name': _(u'name'), 'attribute': encapsulate(lambda x: get_permission_label(x))},
#{
# 'name':_(u'has permission'),
# 'attribute': encapsulate(lambda x: two_state_template(x.has_permission(role))),
#},
],
#'hide_link': True,
#'hide_object': True,
}
},
]
return render_to_response('generic_detail.html', {
#'form': form,
'object': access_object.obj,
'object_name': _(u'object'),
'subtemplates_list': subtemplates_list,
#'multi_select_as_buttons': True,
#'multi_select_item_properties': {
# 'permission_id': lambda x: x.pk,
# 'requester_id': lambda x: role.pk,
# 'requester_app_label': lambda x: ContentType.objects.get_for_model(role).app_label,
# 'requester_model': lambda x: ContentType.objects.get_for_model(role).model,
#},
}, context_instance=RequestContext(request))