diff --git a/apps/main/__init__.py b/apps/main/__init__.py index 0b7901daf3..11a3118e91 100644 --- a/apps/main/__init__.py +++ b/apps/main/__init__.py @@ -7,6 +7,7 @@ from permissions import role_list from documents import document_find_all_duplicates from filesystem_serving import filesystem_serving_recreate_all_links from ocr import all_document_ocr_cleanup +from user_management import user_list from main.conf.settings import SIDE_BAR_SEARCH @@ -45,7 +46,7 @@ main_menu = [ ], 'famfam': 'wrench', 'name': 'tools', 'position': 7}, {'text': _(u'setup'), 'view': 'check_settings', 'links': [ - check_settings, role_list + check_settings, role_list, user_list ], 'famfam': 'cog', 'name': 'setup', 'position': 8}, {'text': _(u'about'), 'view': 'about', 'position': 9}, diff --git a/apps/user_management/__init__.py b/apps/user_management/__init__.py new file mode 100644 index 0000000000..beff92e2ed --- /dev/null +++ b/apps/user_management/__init__.py @@ -0,0 +1,37 @@ +from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth.models import User + +from navigation.api import register_links, register_menu, \ + register_model_list_columns, register_multi_item_links +from permissions.api import register_permissions +from navigation.api import register_sidebar_template + +PERMISSION_USER_CREATE = 'user_create' +PERMISSION_USER_EDIT = 'user_edit' +PERMISSION_USER_VIEW = 'user_view' +PERMISSION_USER_DELETE = 'user_delete' + +register_permissions('user_management', [ + {'name': PERMISSION_USER_CREATE, 'label': _(u'Create new users')}, + {'name': PERMISSION_USER_EDIT, 'label': _(u'Edit exising users')}, + {'name': PERMISSION_USER_VIEW, 'label': _(u'View exising users')}, + {'name': PERMISSION_USER_DELETE, 'label': _(u'Delete exising users')}, +]) + +user_list = {'text': _(u'users'), 'view': 'user_list', 'famfam': 'user', 'permissions': {'namespace': 'user_management', 'permissions': [PERMISSION_USER_VIEW]}} +user_edit = {'text': _(u'edit'), 'view': 'user_edit', 'args': 'object.id', 'famfam': 'user_edit', 'permissions': {'namespace': 'user_management', 'permissions': [PERMISSION_USER_EDIT]}} +user_add = {'text': _(u'create new user'), 'view': 'user_add', 'args': 'object.id', 'famfam': 'user_add', 'permissions': {'namespace': 'user_management', 'permissions': [PERMISSION_USER_CREATE]}} +user_multiple_delete = {u'text': _('delete'), 'view': 'user_multiple_delete', 'famfam': 'user_delete', 'permissions': {'namespace': 'user_management', 'permissions': [PERMISSION_USER_DELETE]}} + +register_links(User, [user_edit]) +register_links('user_list', [user_add], menu_name=u'sidebar') +register_multi_item_links(['user_list'], [user_multiple_delete]) + +#tags_menu = [ +# { +# 'text': _(u'tags'), 'view': 'tag_list', 'famfam': 'tag_blue', 'position': 4, 'links': [ +# tag_list +# ] +# }, +#] +#register_menu(tags_menu) diff --git a/apps/user_management/forms.py b/apps/user_management/forms.py new file mode 100644 index 0000000000..3bcd271802 --- /dev/null +++ b/apps/user_management/forms.py @@ -0,0 +1,10 @@ +from django import forms +from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth.models import User + + +class UserForm(forms.ModelForm): + class Meta: + model = User + fields = ('username', 'first_name', 'last_name', 'email', 'is_active',) + diff --git a/apps/user_management/models.py b/apps/user_management/models.py new file mode 100644 index 0000000000..71a8362390 --- /dev/null +++ b/apps/user_management/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/apps/user_management/tests.py b/apps/user_management/tests.py new file mode 100644 index 0000000000..2247054b35 --- /dev/null +++ b/apps/user_management/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/apps/user_management/urls.py b/apps/user_management/urls.py new file mode 100644 index 0000000000..66876b4ed0 --- /dev/null +++ b/apps/user_management/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import patterns, url + +urlpatterns = patterns('user_management.views', + url(r'^list/$', 'user_list', (), 'user_list'), + url(r'^add/$', 'user_add', (), 'user_add'), + url(r'^(?P\d+)/edit/$', 'user_edit', (), 'user_edit'), + url(r'^(?P\d+)/delete/$', 'user_delete', (), 'user_delete'), + url(r'^multiple/delete/$', 'user_multiple_delete', (), 'user_multiple_delete'), +) diff --git a/apps/user_management/views.py b/apps/user_management/views.py new file mode 100644 index 0000000000..ad20f17487 --- /dev/null +++ b/apps/user_management/views.py @@ -0,0 +1,133 @@ +from django.utils.translation import ugettext_lazy as _ +from django.http import HttpResponseRedirect +from django.shortcuts import render_to_response, get_object_or_404 +from django.template import RequestContext +from django.contrib import messages +from django.views.generic.list_detail import object_list +from django.core.urlresolvers import reverse +from django.views.generic.create_update import create_object, delete_object, update_object +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist +from django.contrib.auth.models import User + +from permissions.api import check_permissions + +from user_management import PERMISSION_USER_VIEW, \ + PERMISSION_USER_EDIT, PERMISSION_USER_CREATE, \ + PERMISSION_USER_DELETE +from user_management.forms import UserForm + +def user_list(request): + check_permissions(request.user, 'user_management', [PERMISSION_USER_VIEW]) + + return object_list( + request, + queryset=User.objects.all(), + template_name='generic_list.html', + extra_context={ + 'title': _(u'users'), + 'hide_link': True, + 'extra_columns': [ + { + 'name': _(u'full name'), + 'attribute': 'get_full_name' + }, + { + 'name': _(u'active'), + 'attribute': 'is_active' + } + + ], + 'multi_select_as_buttons': True, + }, + ) + + +def user_edit(request, user_id): + check_permissions(request.user, 'user_management', [PERMISSION_USER_EDIT]) + user = get_object_or_404(User, pk=user_id) + + if request.method == 'POST': + form = UserForm(instance=user, data=request.POST) + if form.is_valid(): + form.save() + messages.success(request, _(u'User "%s" updated successfully.') % user) + return HttpResponseRedirect(reverse('user_list')) + else: + form = UserForm(instance=user) + + return render_to_response('generic_form.html', { + 'title': _(u'edit user: %s') % user, + 'form': form, + 'object': user, + }, + context_instance=RequestContext(request)) + + +def user_add(request): + check_permissions(request.user, 'user_management', [PERMISSION_USER_CREATE]) + + if request.method == 'POST': + form = UserForm(request.POST) + if form.is_valid(): + user = form.save() + messages.success(request, _(u'User "%s" created successfully.') % user) + return HttpResponseRedirect(reverse('user_list')) + else: + form = UserForm() + + return render_to_response('generic_form.html', { + 'title': _(u'create new user'), + 'form': form, + }, + context_instance=RequestContext(request)) + + +def user_delete(request, user_id=None, user_id_list=None): + check_permissions(request.user, 'users', [PERMISSION_USER_DELETE]) + post_action_redirect = None + + if user_id: + users = [get_object_or_404(User, pk=user_id)] + post_action_redirect = reverse('user_list') + elif user_id_list: + users = [get_object_or_404(User, pk=user_id) for user_id in user_id_list.split(',')] + else: + messages.error(request, _(u'Must provide at least one user.')) + return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) + + previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) + next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/'))) + + if request.method == 'POST': + for user in users: + try: + user.delete() + messages.success(request, _(u'User "%s" deleted successfully.') % user) + except Exception, e: + messages.error(request, _(u'Error deleting user "%(user)s": %(error)s') % { + 'user': user, 'error': e + }) + + return HttpResponseRedirect(next) + + context = { + 'object_name': _(u'user'), + 'delete_view': True, + 'previous': previous, + 'next': next, + } + if len(users) == 1: + context['object'] = users[0] + context['title'] = _(u'Are you sure you wish to delete the user: %s?') % ', '.join([unicode(d) for d in users]) + elif len(users) > 1: + context['title'] = _(u'Are you sure you wish to delete the users: %s?') % ', '.join([unicode(d) for d in users]) + + return render_to_response('generic_confirm.html', context, + context_instance=RequestContext(request)) + + +def user_multiple_delete(request): + return user_delete( + request, user_id_list=request.GET.get('id_list', []) + ) diff --git a/settings.py b/settings.py index ec707449a8..808abbce56 100644 --- a/settings.py +++ b/settings.py @@ -143,6 +143,7 @@ INSTALLED_APPS = ( 'taggit', 'tags', 'document_comments', + 'user_management', ) TEMPLATE_CONTEXT_PROCESSORS = ( diff --git a/urls.py b/urls.py index 34ce9be978..e99cbfa7e7 100644 --- a/urls.py +++ b/urls.py @@ -19,6 +19,7 @@ urlpatterns = patterns('', (r'^grappelli/', include('grappelli.urls')), (r'^sentry/', include('sentry.urls')), (r'^comments/', include('document_comments.urls')), + (r'^user_management/', include('user_management.urls')), )