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 %}
+
+
+
+
+
+
+
+
+
+ {% trans 'Name' %} |
+ {% trans 'Class' %} |
+ |
+ |
+
+
+
+ {% for rule in object_list %}
+
+ {{ rule.name }} |
+ {{ rule|fieldtype }} |
+ {% trans 'Edit' %} |
+ {% trans 'Delete' %} |
+
+ {% endfor %}
+
+
+
+{% 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')