From caf6580ccbfb1205cdfdfaea5d42a7ab8ab82c6c Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Mon, 26 Nov 2018 22:08:48 +0100 Subject: [PATCH] Admin: add rule admin --- .../templates/administration/rule/create.html | 11 +++ .../templates/administration/rule/list.html | 45 ++++++++++++ passbook/admin/urls.py | 5 ++ passbook/admin/views/rules.py | 72 +++++++++++++++++++ passbook/core/forms/rules.py | 20 ++++++ passbook/core/models.py | 18 +++-- 6 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 passbook/admin/templates/administration/rule/create.html create mode 100644 passbook/admin/templates/administration/rule/list.html create mode 100644 passbook/admin/views/rules.py create mode 100644 passbook/core/forms/rules.py diff --git a/passbook/admin/templates/administration/rule/create.html b/passbook/admin/templates/administration/rule/create.html new file mode 100644 index 000000000..eff352942 --- /dev/null +++ b/passbook/admin/templates/administration/rule/create.html @@ -0,0 +1,11 @@ +{% extends "generic/create.html" %} + +{% load i18n %} + +{% block title %} +{% blocktrans with type=request.GET.type %}Create {{ type }}{% endblocktrans %} +{% endblock %} + +{% block above_form %} +

{% blocktrans with type=request.GET.type %}Create {{ type }}{% endblocktrans %}

+{% endblock %} \ No newline at end of file diff --git a/passbook/admin/templates/administration/rule/list.html b/passbook/admin/templates/administration/rule/list.html new file mode 100644 index 000000000..9dd13e781 --- /dev/null +++ b/passbook/admin/templates/administration/rule/list.html @@ -0,0 +1,45 @@ +{% extends "administration/base.html" %} + +{% load i18n %} +{% load utils %} + +{% block title %} +{% title %} +{% endblock %} + +{% block content %} +
+ +
+ + + + + + + + + + + {% for rule in object_list %} + + + + + + + {% endfor %} + +
{% trans 'Name' %}{% trans 'Class' %}
{{ rule.name }}{{ rule|fieldtype }}{% trans 'Edit' %}{% trans 'Delete' %}
+
+{% endblock %} \ No newline at end of file diff --git a/passbook/admin/urls.py b/passbook/admin/urls.py index 5d623bd2d..5816869a8 100644 --- a/passbook/admin/urls.py +++ b/passbook/admin/urls.py @@ -18,5 +18,10 @@ urlpatterns = [ path('sources/create/', sources.SourceCreateView.as_view(), name='source-create'), path('sources//update/', sources.SourceUpdateView.as_view(), name='source-update'), path('sources//delete/', sources.SourceDeleteView.as_view(), name='source-delete'), + # Rules + path('rules/', rules.RuleListView.as_view(), name='rules'), + path('rules/create/', rules.RuleCreateView.as_view(), name='rule-create'), + path('rules//update/', rules.RuleUpdateView.as_view(), name='rule-update'), + path('rules//delete/', rules.RuleDeleteView.as_view(), name='rule-delete'), # path('api/v1/', include('passbook.admin.api.v1.urls')) ] diff --git a/passbook/admin/views/rules.py b/passbook/admin/views/rules.py new file mode 100644 index 000000000..e8e0c169a --- /dev/null +++ b/passbook/admin/views/rules.py @@ -0,0 +1,72 @@ +"""passbook Rule administration""" +from django.contrib.messages.views import SuccessMessageMixin +from django.http import Http404 +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.models import Rule +from passbook.lib.utils.reflection import path_to_class + + +class RuleListView(AdminRequiredMixin, ListView): + """Show list of all rules""" + + model = Rule + template_name = 'administration/rule/list.html' + + def get_context_data(self, **kwargs): + kwargs['types'] = { + x.__name__: x._meta.verbose_name for x in Rule.__subclasses__()} + return super().get_context_data(**kwargs) + + def get_queryset(self): + return super().get_queryset().order_by('order').select_subclasses() + + +class RuleCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView): + """Create new Rule""" + + template_name = 'administration/rule/create.html' + success_url = reverse_lazy('passbook_admin:rules') + success_message = _('Successfully created Rule') + + def get_form_class(self): + rule_type = self.request.GET.get('type') + model = next(x for x in Rule.__subclasses__() + if x.__name__ == rule_type) + if not model: + raise Http404 + return path_to_class(model.form) + + +class RuleUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView): + """Update rule""" + + model = Rule + template_name = 'generic/update.html' + success_url = reverse_lazy('passbook_admin:rules') + success_message = _('Successfully updated Rule') + + def get_form_class(self): + form_class_path = self.get_object().form + form_class = path_to_class(form_class_path) + return form_class + + def get_object(self, queryset=None): + obj = Rule.objects.get(pk=self.kwargs.get('pk')) + return obj.cast() + + +class RuleDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView): + """Delete rule""" + + model = Rule + + success_url = reverse_lazy('passbook_admin:rules') + success_message = _('Successfully updated Rule') + + def get_object(self, queryset=None): + obj = Rule.objects.get(pk=self.kwargs.get('pk')) + return obj.cast() diff --git a/passbook/core/forms/rules.py b/passbook/core/forms/rules.py new file mode 100644 index 000000000..f4debd952 --- /dev/null +++ b/passbook/core/forms/rules.py @@ -0,0 +1,20 @@ +"""passbook rule forms""" + +from django import forms + +from passbook.core.models import FieldMatcherRule + + +class FieldMatcherRuleForm(forms.ModelForm): + """FieldMatcherRule Form""" + + class Meta: + + model = FieldMatcherRule + fields = ['name', 'action', 'negate', 'order', + 'user_field', 'match_action', 'value', ] + widgets = { + 'name': forms.TextInput(), + 'user_field': forms.TextInput(), + 'value': forms.TextInput(), + } diff --git a/passbook/core/models.py b/passbook/core/models.py index ec3524a12..1fe0f8aac 100644 --- a/passbook/core/models.py +++ b/passbook/core/models.py @@ -5,6 +5,7 @@ from logging import getLogger import reversion from django.contrib.auth.models import AbstractUser from django.db import models +from django.utils.translation import gettext as _ from model_utils.managers import InheritanceManager from passbook.lib.models import CreatedUpdatedModel, UUIDModel @@ -128,17 +129,19 @@ class FieldMatcherRule(Rule): MATCH_REGEXP = 'regexp' MATCH_EXACT = 'exact' MATCHES = ( - (MATCH_STARTSWITH, MATCH_STARTSWITH), - (MATCH_ENDSWITH, MATCH_ENDSWITH), - (MATCH_ENDSWITH, MATCH_CONTAINS), - (MATCH_REGEXP, MATCH_REGEXP), - (MATCH_EXACT, MATCH_EXACT), + (MATCH_STARTSWITH, _('Starts with')), + (MATCH_ENDSWITH, _('Ends with')), + (MATCH_ENDSWITH, _('Contains')), + (MATCH_REGEXP, _('Regexp')), + (MATCH_EXACT, _('Exact')), ) user_field = models.TextField() match_action = models.CharField(max_length=50, choices=MATCHES) value = models.TextField() + form = 'passbook.core.forms.rules.FieldMatcherRuleForm' + def __str__(self): description = "%s, user.%s %s '%s'" % (self.name, self.user_field, self.match_action, self.value) @@ -167,3 +170,8 @@ class FieldMatcherRule(Rule): passes = not passes LOGGER.debug("User got '%r'", passes) return passes + + class Meta: + + verbose_name = _('Field matcher Rule') + verbose_name_plural = _('Field matcher Rules')