diff --git a/apps/acls/__init__.py b/apps/acls/__init__.py index eae1816727..c6dd477306 100644 --- a/apps/acls/__init__.py +++ b/apps/acls/__init__.py @@ -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]) diff --git a/apps/acls/api.py b/apps/acls/api.py index 8dc3f2d931..bfcdcf1e7b 100644 --- a/apps/acls/api.py +++ b/apps/acls/api.py @@ -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() diff --git a/apps/acls/classes.py b/apps/acls/classes.py index bcca9a6971..016a4ca797 100644 --- a/apps/acls/classes.py +++ b/apps/acls/classes.py @@ -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' diff --git a/apps/acls/literals.py b/apps/acls/literals.py index 50c6626b8e..5d86e0a013 100644 --- a/apps/acls/literals.py +++ b/apps/acls/literals.py @@ -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', } diff --git a/apps/acls/models.py b/apps/acls/models.py index 7aa847a88d..865e44e567 100644 --- a/apps/acls/models.py +++ b/apps/acls/models.py @@ -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( diff --git a/apps/acls/urls.py b/apps/acls/urls.py index 1ef00855a7..ff1e9dd4b3 100644 --- a/apps/acls/urls.py +++ b/apps/acls/urls.py @@ -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[.\w]+)/holder/(?P[.\w]+)/$', 'acls_class_acl_detail', (), 'acls_class_acl_detail'), + url(r'^class/details/(?P[.\w]+)/holder/(?P[.\w]+)/$', 'acl_class_acl_detail', (), 'acl_class_acl_detail'), url(r'^class/list_for/(?P[.\w]+)/$', 'acl_class_acl_list', (), 'acl_class_acl_list'), url(r'^class/holder/new/(?P[.\w]+)/$', 'acl_class_new_holder_for', (), 'acl_class_new_holder_for'), diff --git a/apps/acls/views.py b/apps/acls/views.py index f0332fe33e..375ab37b6e 100644 --- a/apps/acls/views.py +++ b/apps/acls/views.py @@ -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) diff --git a/apps/acls/widgets.py b/apps/acls/widgets.py index 8a410fd171..3c13fce54b 100644 --- a/apps/acls/widgets.py +++ b/apps/acls/widgets.py @@ -14,7 +14,7 @@ from .literals import CONTENT_TYPE_ICON_MAP def content_type_icon(content_type): - return mark_safe(u'' % CONTENT_TYPE_ICON_MAP.get('%s.%s' % (content_type.app_label, content_type.name), 'help')) + return mark_safe(u'' % CONTENT_TYPE_ICON_MAP.get('%s.%s' % (content_type.app_label, content_type.model), 'help')) def object_w_content_type_icon(obj): diff --git a/apps/documents/__init__.py b/apps/documents/__init__.py index 45fd4c5ad7..1d052cfa24 100644 --- a/apps/documents/__init__.py +++ b/apps/documents/__init__.py @@ -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 diff --git a/apps/linking/__init__.py b/apps/linking/__init__.py index 0354346f7e..cb1c98cbff 100644 --- a/apps/linking/__init__.py +++ b/apps/linking/__init__.py @@ -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') diff --git a/apps/linking/views.py b/apps/linking/views.py index 7aacd67a66..5f72d8f393 100644 --- a/apps/linking/views.py +++ b/apps/linking/views.py @@ -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', diff --git a/apps/permissions/__init__.py b/apps/permissions/__init__.py index 77f5c6119e..6eb0d68be5 100644 --- a/apps/permissions/__init__.py +++ b/apps/permissions/__init__.py @@ -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'] diff --git a/apps/tags/__init__.py b/apps/tags/__init__.py index 8cfeacf58b..79a04dbd03 100644 --- a/apps/tags/__init__.py +++ b/apps/tags/__init__.py @@ -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, [ diff --git a/apps/user_management/__init__.py b/apps/user_management/__init__.py index 133f60df71..fb751fb6c2 100644 --- a/apps/user_management/__init__.py +++ b/apps/user_management/__init__.py @@ -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 = [