From 2d7e8f1b507890d7d29b816205ba8cb3b10d8d88 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Fri, 8 Mar 2019 15:49:45 +0100 Subject: [PATCH] add group administration --- .../admin/templates/administration/base.html | 69 ++++++++------- .../templates/administration/group/list.html | 45 ++++++++++ .../templates/administration/groups/list.html | 83 ------------------- passbook/admin/urls.py | 5 ++ passbook/admin/views/groups.py | 51 +++++++++++- passbook/core/forms/groups.py | 30 +++++++ .../migrations/0017_auto_20190308_1417.py | 25 ++++++ passbook/core/models.py | 4 +- passbook/core/settings.py | 1 + 9 files changed, 195 insertions(+), 118 deletions(-) create mode 100644 passbook/admin/templates/administration/group/list.html delete mode 100644 passbook/admin/templates/administration/groups/list.html create mode 100644 passbook/core/forms/groups.py create mode 100644 passbook/core/migrations/0017_auto_20190308_1417.py diff --git a/passbook/admin/templates/administration/base.html b/passbook/admin/templates/administration/base.html index fadc37d70..d33970b78 100644 --- a/passbook/admin/templates/administration/base.html +++ b/passbook/admin/templates/administration/base.html @@ -5,35 +5,44 @@ {% block nav_secondary %} {% endblock %} diff --git a/passbook/admin/templates/administration/group/list.html b/passbook/admin/templates/administration/group/list.html new file mode 100644 index 000000000..4a87521b0 --- /dev/null +++ b/passbook/admin/templates/administration/group/list.html @@ -0,0 +1,45 @@ +{% extends "administration/base.html" %} + +{% load i18n %} +{% load utils %} + +{% block title %} +{% title %} +{% endblock %} + +{% block content %} +
+

{% trans "Groups" %}

+ {% trans "Group users together and give them permissions based on the membership." %} +
+ + {% trans 'Create...' %} + +
+ + + + + + + + + + + {% for group in object_list %} + + + + + + + {% endfor %} + +
{% trans 'Name' %}{% trans 'Parent' %}{% trans 'Members' %}
{{ group.name }}{{ group.parent }}{{ group.user_set.all|length }} + {% trans 'Edit' %} + {% trans 'Delete' %} +
+
+{% endblock %} diff --git a/passbook/admin/templates/administration/groups/list.html b/passbook/admin/templates/administration/groups/list.html deleted file mode 100644 index b8df11dc8..000000000 --- a/passbook/admin/templates/administration/groups/list.html +++ /dev/null @@ -1,83 +0,0 @@ -{% extends "administration/base.html" %} - -{% load i18n %} -{% load static %} -{% load utils %} - -{% block head %} -{{ block.super }} - -{% endblock %} - -{% block scripts %} -{{ block.super }} - - -{% endblock %} - -{% block title %} -{% title %} -{% endblock %} - -{% block content %} -
-
-
-
-
-

{% trans "Invitations" %}

- - {% trans 'Create...' %} - -
- - - - - - - - - - {% for invitation in object_list %} - - - - - - {% endfor %} - -
{% trans 'Expiry' %}{% trans 'Link' %}
{{ invitation.expires|default:"Never" }} -
{{ invitation.link }}
-
- {% - trans 'Delete' %} -
-
-{% endblock %} diff --git a/passbook/admin/urls.py b/passbook/admin/urls.py index e2d3a6236..deb4472bd 100644 --- a/passbook/admin/urls.py +++ b/passbook/admin/urls.py @@ -58,6 +58,11 @@ urlpatterns = [ users.UserDeleteView.as_view(), name='user-delete'), path('users//reset/', users.UserPasswordResetView.as_view(), name='user-password-reset'), + # Groups + path('group/', groups.GroupListView.as_view(), name='group'), + path('group/create/', groups.GroupCreateView.as_view(), name='group-create'), + path('group//update/', groups.GroupUpdateView.as_view(), name='group-update'), + path('group//delete/', groups.GroupDeleteView.as_view(), name='group-delete'), # Audit Log path('audit/', audit.AuditEntryListView.as_view(), name='audit-log'), # Groups diff --git a/passbook/admin/views/groups.py b/passbook/admin/views/groups.py index 629ed4aa0..1e120669d 100644 --- a/passbook/admin/views/groups.py +++ b/passbook/admin/views/groups.py @@ -1,12 +1,57 @@ """passbook Group administration""" -from django.views.generic import ListView +from django.contrib import messages +from django.contrib.messages.views import SuccessMessageMixin +from django.urls import reverse_lazy +from django.utils.translation import ugettext as _ +from django.views.generic import CreateView, DeleteView, ListView, UpdateView from passbook.admin.mixins import AdminRequiredMixin +from passbook.core.forms.groups import GroupForm from passbook.core.models import Group class GroupListView(AdminRequiredMixin, ListView): - """Show list of all invitations""" + """Show list of all groups""" model = Group - template_name = 'administration/groups/list.html' + ordering = 'name' + template_name = 'administration/group/list.html' + + +class GroupCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView): + """Create new Group""" + + form_class = GroupForm + + template_name = 'generic/create.html' + success_url = reverse_lazy('passbook_admin:groups') + success_message = _('Successfully created Group') + + def get_context_data(self, **kwargs): + kwargs['type'] = 'Group' + return super().get_context_data(**kwargs) + + +class GroupUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView): + """Update group""" + + model = Group + form_class = GroupForm + + template_name = 'generic/update.html' + success_url = reverse_lazy('passbook_admin:groups') + success_message = _('Successfully updated Group') + + +class GroupDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView): + """Delete group""" + + model = Group + + template_name = 'generic/delete.html' + success_url = reverse_lazy('passbook_admin:groups') + success_message = _('Successfully deleted Group') + + def delete(self, request, *args, **kwargs): + messages.success(self.request, self.success_message) + return super().delete(request, *args, **kwargs) diff --git a/passbook/core/forms/groups.py b/passbook/core/forms/groups.py new file mode 100644 index 000000000..76b10b667 --- /dev/null +++ b/passbook/core/forms/groups.py @@ -0,0 +1,30 @@ +"""passbook Core Group forms""" +from django import forms + +from passbook.core.models import Group, User + + +class GroupForm(forms.ModelForm): + """Group Form""" + + members = forms.ModelMultipleChoiceField(User.objects.all(), required=False) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if self.instance.pk: + self.initial['members'] = self.instance.user_set.values_list('pk', flat=True) + + def save(self, *args, **kwargs): + instance = super().save(*args, **kwargs) + if instance.pk: + instance.user_set.clear() + instance.user_set.add(*self.cleaned_data['users']) + return instance + + class Meta: + + model = Group + fields = ['name', 'parent', 'members', 'tags'] + widgets = { + 'name': forms.TextInput(), + } diff --git a/passbook/core/migrations/0017_auto_20190308_1417.py b/passbook/core/migrations/0017_auto_20190308_1417.py new file mode 100644 index 000000000..d32d6fa48 --- /dev/null +++ b/passbook/core/migrations/0017_auto_20190308_1417.py @@ -0,0 +1,25 @@ +# Generated by Django 2.1.7 on 2019-03-08 14:17 + +import django.contrib.postgres.fields.hstore +from django.contrib.postgres.operations import HStoreExtension +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('passbook_core', '0016_auto_20190227_1355'), + ] + + operations = [ + migrations.RemoveField( + model_name='group', + name='extra_data', + ), + HStoreExtension(), + migrations.AddField( + model_name='group', + name='tags', + field=django.contrib.postgres.fields.hstore.HStoreField(default=dict), + ), + ] diff --git a/passbook/core/models.py b/passbook/core/models.py index 2f6d526d8..25608b67a 100644 --- a/passbook/core/models.py +++ b/passbook/core/models.py @@ -8,7 +8,7 @@ from typing import Tuple, Union from uuid import uuid4 from django.contrib.auth.models import AbstractUser -from django.contrib.postgres.fields import ArrayField +from django.contrib.postgres.fields import ArrayField, HStoreField from django.db import models from django.urls import reverse_lazy from django.utils.timezone import now @@ -31,7 +31,7 @@ class Group(UUIDModel): name = models.CharField(_('name'), max_length=80) parent = models.ForeignKey('Group', blank=True, null=True, on_delete=models.SET_NULL, related_name='children') - extra_data = models.TextField(blank=True) + tags = HStoreField(default=dict) def __str__(self): return "Group %s" % self.name diff --git a/passbook/core/settings.py b/passbook/core/settings.py index 580c54f6f..495dd9282 100644 --- a/passbook/core/settings.py +++ b/passbook/core/settings.py @@ -60,6 +60,7 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.postgres', 'rest_framework', 'drf_yasg', 'raven.contrib.django.raven_compat',