Merge branch 'feature/class_default_acl_support' into development

This commit is contained in:
Roberto Rosario
2012-01-09 04:57:32 -04:00
14 changed files with 91 additions and 66 deletions

View File

@@ -11,14 +11,14 @@ from .permissions import (ACLS_EDIT_ACL, ACLS_VIEW_ACL,
acl_list = {'text': _(u'ACLs'), 'view': 'acl_list', 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
acl_detail = {'text': _(u'details'), 'view': 'acl_detail', 'args': ['access_object.gid', 'object.gid'], 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
acl_detail = {'text': _(u'details'), 'view': 'acl_detail', 'args': ['access_object.gid', 'object.gid'], 'famfam': 'key_go', 'permissions': [ACLS_VIEW_ACL]}
acl_grant = {'text': _(u'grant'), 'view': 'acl_multiple_grant', 'famfam': 'key_add', 'permissions': [ACLS_EDIT_ACL]}
acl_revoke = {'text': _(u'revoke'), 'view': 'acl_multiple_revoke', 'famfam': 'key_delete', 'permissions': [ACLS_EDIT_ACL]}
acl_setup_valid_classes = {'text': _(u'Default ACLs'), 'view': 'acl_setup_valid_classes', 'icon': 'lock.png', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_list = {'text': _(u'List of classes'), 'view': 'acl_setup_valid_classes', 'famfam': 'package', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_acl_list = {'text': _(u'ACLs for class'), 'view': 'acl_class_acl_list', 'args': 'object.gid', 'famfam': 'lock', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_acl_detail = {'text': _(u'edit'), 'view': 'acls_class_acl_detail', 'args': ['access_object_class.gid', 'object.gid'], 'famfam': 'lock', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_acl_list = {'text': _(u'ACLs for class'), 'view': 'acl_class_acl_list', 'args': 'object.gid', 'famfam': 'lock_go', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_acl_detail = {'text': _(u'details'), 'view': 'acl_class_acl_detail', 'args': ['access_object_class.gid', 'object.gid'], 'famfam': 'key_go', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_new_holder_for = {'text': _(u'New holder'), 'view': 'acl_class_new_holder_for', 'args': 'object.gid', 'famfam': 'user', 'permissions': [ACLS_CLASS_EDIT_ACL]}
acl_class_grant = {'text': _(u'grant'), 'view': 'acl_class_multiple_grant', 'famfam': 'key_add', 'permissions': [ACLS_CLASS_EDIT_ACL]}
acl_class_revoke = {'text': _(u'revoke'), 'view': 'acl_class_multiple_revoke', 'famfam': 'key_delete', 'permissions': [ACLS_CLASS_EDIT_ACL]}
@@ -27,10 +27,9 @@ register_links(AccessHolder, [acl_detail])
register_multi_item_links(['acl_detail'], [acl_grant, acl_revoke])
register_setup(acl_setup_valid_classes)
register_links(['acl_setup_valid_classes', 'acl_class_acl_list', 'acl_class_new_holder_for', 'acl_class_acl_detail'], [acl_class_list], menu_name='sidebar')
register_links(['acl_setup_valid_classes', 'acl_class_acl_list', 'acl_class_new_holder_for', 'acl_class_acl_detail'], [acl_class_list], menu_name='secondary_menu')
register_links(ClassAccessHolder, [acl_class_acl_detail])
register_links(AccessObjectClass, [acl_class_acl_list])
register_links(AccessObjectClass, [acl_class_new_holder_for])
register_multi_item_links(['acls_class_acl_detail'], [acl_class_grant, acl_class_revoke])
register_links(AccessObjectClass, [acl_class_acl_list, acl_class_new_holder_for])
register_multi_item_links(['acl_class_acl_detail'], [acl_class_grant, acl_class_revoke])

View File

@@ -1,13 +1,28 @@
from __future__ import absolute_import
from django.contrib.contenttypes.models import ContentType
_class_permissions = {}
def class_permissions(cls, permission_list):
"""
Associate a permissions list to a class
"""
stored_permissions = _class_permissions.setdefault(cls, [])
stored_permissions.extend(permission_list)
def get_class_permissions_for(obj):
"""
Return a list of permissions associated with a content type
"""
content_type = ContentType.objects.get_for_model(obj)
return _class_permissions.get(content_type.model_class(), [])
def get_classes():
"""
Return a list of encapsulated classes that have been registered
"""
return _class_permissions.keys()

View File

@@ -1,3 +1,5 @@
from __future__ import absolute_import
import logging
import sys
import types
@@ -5,6 +7,7 @@ import types
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.db.models.base import ModelBase
from django.template.defaultfilters import capfirst
from common.models import AnonymousUserSingleton
@@ -15,6 +18,13 @@ _cache = {}
class EncapsulatedObject(object):
source_object_name = u'source_object'
@classmethod
def object_key(cls, app_label=None, model=None, pk=None):
if pk:
return '%s.%s.%s.%s' % (cls.__name__, app_label, model, pk)
else:
return '%s.%s.%s' % (cls.__name__, app_label, model)
@classmethod
def add_to_class(cls, name, value):
@@ -27,34 +37,21 @@ class EncapsulatedObject(object):
def set_source_object_name(cls, new_name):
cls.source_object_name = new_name
#@classmethod
#def encapsulate_list(cls, source_object=None, app_label=None, model=None, pk=None):
@classmethod
def encapsulate(cls, source_object=None, app_label=None, model=None, pk=None):
if source_object:
source_object = AnonymousUserSingleton.objects.passthru_check(source_object)
content_type = ContentType.objects.get_for_model(source_object)
elif app_label and model:
try:
content_type = ContentType.objects.get(app_label=app_label, model=model)
source_object_model_class = content_type.model_class()
if pk:
source_object = content_type.get_object_for_this_type(pk=pk)
else:
source_object = source_object_model_class
except ContentType.DoesNotExist:
#cls.add_to_class('DoesNotExist', subclass_exception('DoesNotExist', (ObjectDoesNotExist,), cls.__name__))
#raise cls.DoesNotExist("%s matching query does not exist." % ContentType._meta.object_name)
raise ObjectDoesNotExist("%s matching query does not exist." % ContentType._meta.object_name)
except source_object_model_class.DoesNotExist:
#cls.add_to_class('DoesNotExist', subclass_exception('DoesNotExist', (ObjectDoesNotExist,), cls.__name__))
#raise cls.DoesNotExist("%s matching query does not exist." % source_object_model_class._meta.object_name)
raise ObjectDoesNotExist("%s matching query does not exist." % source_object_model_class._meta.object_name)
def encapsulate(cls, source_object):
source_object = AnonymousUserSingleton.objects.passthru_check(source_object)
content_type = ContentType.objects.get_for_model(source_object)
if hasattr(source_object, 'pk'):
# Object
object_key = '%s.%s.%s.%s' % (cls.__name__, content_type.app_label, content_type.model, source_object.pk)
object_key = cls.object_key(content_type.app_label, content_type.model, source_object.pk)
else:
# Class
object_key = '%s.%s.%s' % (cls.__name__, content_type.app_label, content_type.model)
object_key = cls.object_key(content_type.app_label, content_type.model)
try:
return _cache[object_key]
@@ -68,19 +65,34 @@ class EncapsulatedObject(object):
elements = gid.split('.')
if len(elements) == 3:
app_label, model, pk = elements[0], elements[1], elements[2]
object_key = '%s.%s.%s.%s' % (cls.__name__, app_label, model, pk)
elif len(elements) == 2:
app_label, model = elements[0], elements[1]
pk = None
object_key = '%s.%s.%s' % (cls.__name__, app_label, model)
object_key = cls.object_key(*elements)
try:
return _cache[object_key]
except KeyError:
if pk:
return cls.encapsulate(app_label=app_label, model=model, pk=pk)
try:
content_type = ContentType.objects.get(app_label=app_label, model=model)
except ContentType.DoesNotExist:
#cls.add_to_class('DoesNotExist', subclass_exception('DoesNotExist', (ObjectDoesNotExist,), cls.__name__))
#raise cls.DoesNotExist("%s matching query does not exist." % ContentType._meta.object_name)
raise ObjectDoesNotExist("%s matching query does not exist." % ContentType._meta.object_name)
else:
return cls.encapsulate(app_label=app_label, model=model)
source_object_model_class = content_type.model_class()
if pk:
try:
source_object = content_type.get_object_for_this_type(pk=pk)
except source_object_model_class.DoesNotExist:
#cls.add_to_class('DoesNotExist', subclass_exception('DoesNotExist', (ObjectDoesNotExist,), cls.__name__))
#raise cls.DoesNotExist("%s matching query does not exist." % source_object_model_class._meta.object_name)
raise ObjectDoesNotExist("%s matching query does not exist." % source_object_model_class._meta.object_name)
else:
source_object = source_object_model_class
return cls.encapsulate(source_object)
def __init__(self, source_object):
self.content_type = ContentType.objects.get_for_model(source_object)
@@ -111,9 +123,6 @@ class EncapsulatedObject(object):
def source_object(self):
return getattr(self, self.__class__.source_object_name, None)
def get_class_permissions(self):
return _class_permissions.get(self.content_type.model_class(), [])
class AccessHolder(EncapsulatedObject):
source_object_name = u'holder_object'

View File

@@ -1,8 +1,12 @@
# Content type <-> fam fam icon mapping
CONTENT_TYPE_ICON_MAP = {
'auth.user': 'user',
'auth.group': 'group',
'documents.document': 'page',
'permissions.role': 'medal_gold_1',
'folders.folder': 'folder',
'taggit.tag': 'tag_blue',
'linking.smartlink': 'page_link',
'common.anonymoususersingleton': 'user',
}

View File

@@ -11,11 +11,12 @@ from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import get_object_or_404
from django.template.defaultfilters import capfirst
from permissions.models import StoredPermission
from .managers import AccessEntryManager, DefaultAccessEntryManager
from .classes import AccessObjectClass
from .api import get_classes
logger = logging.getLogger(__name__)
@@ -24,7 +25,6 @@ class AccessEntry(models.Model):
'''
Model that hold the permission, object, actor relationship
'''
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
holder_type = models.ForeignKey(
@@ -63,11 +63,10 @@ class DefaultAccessEntry(models.Model):
Model that holds the permission, class, actor relationship, that will
be added upon the creation of an instance of said class
'''
@classmethod
def get_classes(cls):
return [AccessObjectClass.encapsulate(cls) for cls in _class_permissions.keys()]
return [AccessObjectClass.encapsulate(cls) for cls in get_classes()]
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
holder_type = models.ForeignKey(

View File

@@ -9,7 +9,7 @@ urlpatterns = patterns('acls.views',
url(r'^multiple/revoke/$', 'acl_revoke', (), 'acl_multiple_revoke'),
url(r'^class/$', 'acl_setup_valid_classes', (), 'acl_setup_valid_classes'),
url(r'^class/details/(?P<access_object_class_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acls_class_acl_detail', (), 'acls_class_acl_detail'),
url(r'^class/details/(?P<access_object_class_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_class_acl_detail', (), 'acl_class_acl_detail'),
url(r'^class/list_for/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_acl_list', (), 'acl_class_acl_list'),
url(r'^class/holder/new/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_new_holder_for', (), 'acl_class_new_holder_for'),

View File

@@ -29,7 +29,7 @@ from .classes import (AccessHolder, AccessObject, AccessObjectClass,
ClassAccessHolder)
from .widgets import object_w_content_type_icon
from .forms import HolderSelectionForm
from .api import get_class_permissions_for
from .api import get_class_permissions_for, get_classes
logger = logging.getLogger(__name__)
@@ -85,9 +85,9 @@ def acl_detail(request, access_object_gid, holder_object_gid):
def acl_detail_for(request, actor, obj, navigation_object=None):
try:
Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL, ACLS_EDIT_ACL])
Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL])
except PermissionDenied:
AccessEntry.objects.check_accesses([ACLS_VIEW_ACL, ACLS_EDIT_ACL], actor, obj)
AccessEntry.objects.check_accesses([ACLS_VIEW_ACL], actor, obj)
permission_list = get_class_permissions_for(obj)
@@ -110,7 +110,6 @@ def acl_detail_for(request, actor, obj, navigation_object=None):
'attribute': encapsulate(lambda permission: two_state_template(AccessEntry.objects.has_access(permission, actor, obj)))
},
],
#'hide_link': True,
'hide_object': True,
}
},
@@ -187,7 +186,7 @@ def acl_grant(request):
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(u' and ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' to %s') % requester)
@@ -281,7 +280,7 @@ def acl_revoke(request):
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(u' and ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' from %s') % requester)
@@ -371,7 +370,7 @@ def acl_new_holder_for(request, obj, extra_context=None, navigation_object=None)
# Setup views
def acl_setup_valid_classes(request):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL, ACLS_CLASS_EDIT_ACL])
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL])
logger.debug('DefaultAccessEntry.get_classes(): %s' % DefaultAccessEntry.get_classes())
context = {
@@ -388,7 +387,7 @@ def acl_setup_valid_classes(request):
def acl_class_acl_list(request, access_object_class_gid):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL, ACLS_CLASS_EDIT_ACL])
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL])
access_object_class = AccessObjectClass.get(gid=access_object_class_gid)
context = {
@@ -400,21 +399,23 @@ def acl_class_acl_list(request, access_object_class_gid):
],
'hide_object': True,
'access_object_class': access_object_class,
'object': access_object_class,
}
return render_to_response('generic_list.html', context,
context_instance=RequestContext(request))
def acls_class_acl_detail(request, access_object_class_gid, holder_object_gid):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL, ACLS_CLASS_EDIT_ACL])
def acl_class_acl_detail(request, access_object_class_gid, holder_object_gid):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL])
try:
actor = AccessHolder.get(gid=holder_object_gid)
access_object_class = AccessObjectClass.get(gid=access_object_class_gid)
except ObjectDoesNotExist:
raise Http404
permission_list = list(access_object_class.get_class_permissions())
#permission_list = list(access_object_class.get_class_permissions())
permission_list = get_class_permissions_for(access_object_class.content_type.model_class())
#TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware)
subtemplates_list = [
{
@@ -462,7 +463,7 @@ def acl_class_new_holder_for(request, access_object_class_gid):
try:
access_holder = ClassAccessHolder.get(form.cleaned_data['holder_gid'])
return HttpResponseRedirect(reverse('acls_class_acl_detail', args=[access_object_class.gid, access_holder.gid]))
return HttpResponseRedirect(reverse('acl_class_acl_detail', args=[access_object_class.gid, access_holder.gid]))
except ObjectDoesNotExist:
raise Http404
else:
@@ -512,7 +513,7 @@ def acl_class_multiple_grant(request):
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(u' and ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' to %s') % requester)
@@ -592,7 +593,7 @@ def acl_class_multiple_revoke(request):
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(u' and ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' from %s') % requester)

View File

@@ -14,7 +14,7 @@ from .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'))
return mark_safe(u'<span class="famfam active famfam-%s"></span>' % CONTENT_TYPE_ICON_MAP.get('%s.%s' % (content_type.app_label, content_type.model), 'help'))
def object_w_content_type_icon(obj):

View File

@@ -129,7 +129,7 @@ register_links(['setup_document_type_metadata', 'document_type_filename_delete',
register_links(['document_type_filename_create', 'document_type_filename_list', 'document_type_filename_edit', 'document_type_filename_delete'], [document_type_filename_create], menu_name='sidebar')
# Register document links
register_links(Document, [document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations, document_create_siblings])
register_links(Document, [document_view_simple, document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations, document_create_siblings])
register_multi_item_links(['document_find_duplicates', 'folder_view', 'index_instance_list', 'document_type_document_list', 'search', 'results', 'document_group_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete, document_multiple_download])
# Document Version links

View File

@@ -36,7 +36,7 @@ register_links(['smart_link_acl_list', 'smart_link_new_holder'], [smart_link_new
register_links(Document, [smart_link_instances_for_document], menu_name='form_header')
register_links(SmartLink, [smart_link_edit, smart_link_delete, smart_link_condition_list, smart_link_acl_list])
register_links([SmartLink, 'smart_link_list', 'smart_link_create'], [smart_link_list, smart_link_create], menu_name='sidebar')
register_links([SmartLink, 'smart_link_list', 'smart_link_create'], [smart_link_list, smart_link_create], menu_name='secondary_menu')
register_links(SmartLinkCondition, [smart_link_condition_edit, smart_link_condition_delete])
register_links(['smart_link_condition_list', 'smart_link_condition_create', 'smart_link_condition_edit', 'smart_link_condition_delete'], [smart_link_condition_create], menu_name='sidebar')

View File

@@ -359,8 +359,6 @@ def smart_link_new_holder(request, smart_link_pk):
smart_link,
extra_context={
'smart_link': smart_link,
'submit_label': _(u'Select'),
'submit_icon_famfam': 'tick',
'object': smart_link,
},
navigation_object=u'smart_link',

View File

@@ -25,7 +25,7 @@ permission_grant = {'text': _(u'grant'), 'view': 'permission_multiple_grant', 'f
permission_revoke = {'text': _(u'revoke'), 'view': 'permission_multiple_revoke', 'famfam': 'key_delete', 'permissions': [PERMISSION_PERMISSION_REVOKE]}
register_links(Role, [role_edit, role_delete, role_permissions, role_members])
register_links(['role_members', 'role_list', 'role_view', 'role_create', 'role_edit', 'role_permissions', 'role_delete'], [role_list, role_create], menu_name='sidebar')
register_links(['role_members', 'role_list', 'role_view', 'role_create', 'role_edit', 'role_permissions', 'role_delete'], [role_list, role_create], menu_name='secondary_menu')
register_multi_item_links(['role_permissions'], [permission_grant, permission_revoke])
permission_views = ['role_list', 'role_create', 'role_edit', 'role_members', 'role_permissions', 'role_delete']

View File

@@ -59,7 +59,7 @@ register_top_menu('tags', link={'text': _(u'tags'), 'view': 'tag_list', 'famfam'
register_links(['tag_acl_list', 'tag_new_holder'], [tag_new_holder], menu_name='sidebar')
register_links(Document, [tag_document_list], menu_name='form_header')
register_links(['document_tags', 'tag_add_attach', 'tag_remove', 'tag_multiple_remove'], [tag_attach], menu_name='sidebar')
register_links(['document_tags', 'tag_remove', 'tag_multiple_remove', 'tag_attach'], [tag_attach], menu_name='sidebar')
register_multi_item_links(['document_tags'], [tag_document_remove_multiple])
class_permissions(Document, [

View File

@@ -28,11 +28,11 @@ group_multiple_delete = {u'text': _('delete'), 'view': 'group_multiple_delete',
group_members = {'text': _(u'members'), 'view': 'group_members', 'args': 'object.id', 'famfam': 'group_link', 'permissions': [PERMISSION_GROUP_EDIT]}
register_links(User, [user_edit, user_set_password, user_delete])
register_links(['user_multiple_set_password', 'user_set_password', 'user_multiple_delete', 'user_delete', 'user_edit', 'user_list', 'user_add'], [user_list, user_add], menu_name=u'sidebar')
register_links(['user_multiple_set_password', 'user_set_password', 'user_multiple_delete', 'user_delete', 'user_edit', 'user_list', 'user_add'], [user_list, user_add], menu_name=u'secondary_menu')
register_multi_item_links(['user_list'], [user_multiple_set_password, user_multiple_delete])
register_links(Group, [group_edit, group_members, group_delete])
register_links(['group_multiple_delete', 'group_delete', 'group_edit', 'group_list', 'group_add', 'group_members'], [group_list, group_add], menu_name=u'sidebar')
register_links(['group_multiple_delete', 'group_delete', 'group_edit', 'group_list', 'group_add', 'group_members'], [group_list, group_add], menu_name=u'secondary_menu')
register_multi_item_links(['group_list'], [group_multiple_delete])
user_management_views = [