diff --git a/passbook/admin/forms/rule.py b/passbook/admin/forms/policies.py
similarity index 67%
rename from passbook/admin/forms/rule.py
rename to passbook/admin/forms/policies.py
index a633a83e8..9bca84a98 100644
--- a/passbook/admin/forms/rule.py
+++ b/passbook/admin/forms/policies.py
@@ -4,7 +4,7 @@ from django import forms
from passbook.core.models import User
-class RuleTestForm(forms.Form):
- """Form to test rule against user"""
+class PolicyTestForm(forms.Form):
+ """Form to test policies against user"""
user = forms.ModelChoiceField(queryset=User.objects.all())
diff --git a/passbook/admin/templates/administration/base.html b/passbook/admin/templates/administration/base.html
index 4dac1922f..7ed02b095 100644
--- a/passbook/admin/templates/administration/base.html
+++ b/passbook/admin/templates/administration/base.html
@@ -20,8 +20,8 @@
{% trans 'Factors' %}
-
- {% trans 'Rules' %}
+
+ {% trans 'Policies' %}
{% trans 'Invitations' %}
diff --git a/passbook/admin/templates/administration/overview.html b/passbook/admin/templates/administration/overview.html
index 6ebcaa759..8d0a9e9a8 100644
--- a/passbook/admin/templates/administration/overview.html
+++ b/passbook/admin/templates/administration/overview.html
@@ -31,11 +31,11 @@
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/passbook/admin/templates/administration/rule/list.html b/passbook/admin/templates/administration/policy/list.html
similarity index 66%
rename from passbook/admin/templates/administration/rule/list.html
rename to passbook/admin/templates/administration/policy/list.html
index d0a324ffe..51218e286 100644
--- a/passbook/admin/templates/administration/rule/list.html
+++ b/passbook/admin/templates/administration/policy/list.html
@@ -9,7 +9,7 @@
{% block content %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/passbook/admin/templates/administration/policy/test.html b/passbook/admin/templates/administration/policy/test.html
new file mode 100644
index 000000000..6a5ddcbb1
--- /dev/null
+++ b/passbook/admin/templates/administration/policy/test.html
@@ -0,0 +1,7 @@
+{% extends 'generic/form.html' %}
+
+{% load i18n %}
+
+{% block above_form %}
+{% blocktrans with policy=policy %}Test policy {{ policy }}{% endblocktrans %}
+{% endblock %}
diff --git a/passbook/admin/templates/administration/rule/test.html b/passbook/admin/templates/administration/rule/test.html
deleted file mode 100644
index 5d8a9f4f6..000000000
--- a/passbook/admin/templates/administration/rule/test.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% extends 'generic/form.html' %}
-
-{% load i18n %}
-
-{% block above_form %}
-{% blocktrans with rule=rule %}Test rule {{ rule }}{% endblocktrans %}
-{% endblock %}
\ No newline at end of file
diff --git a/passbook/admin/urls.py b/passbook/admin/urls.py
index 941d99cf2..77b48e419 100644
--- a/passbook/admin/urls.py
+++ b/passbook/admin/urls.py
@@ -3,7 +3,7 @@ from django.urls import include, path
from rest_framework_swagger.views import get_swagger_view
from passbook.admin.views import (applications, audit, factors, groups,
- invitations, overview, providers, rules,
+ invitations, overview, policy, providers,
sources, users)
schema_view = get_swagger_view(title='passbook Admin Internal API')
@@ -25,12 +25,12 @@ 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('rules//test/', rules.RuleTestView.as_view(), name='rule-test'),
+ # Policies
+ path('policies/', policy.PolicyListView.as_view(), name='policies'),
+ path('policies/create/', policy.PolicyCreateView.as_view(), name='policy-create'),
+ path('policies//update/', policy.PolicyUpdateView.as_view(), name='policy-update'),
+ path('policies//delete/', policy.PolicyDeleteView.as_view(), name='policy-delete'),
+ path('policies//test/', policy.PolicyTestView.as_view(), name='policy-test'),
# Providers
path('providers/', providers.ProviderListView.as_view(), name='providers'),
path('providers/create/',
diff --git a/passbook/admin/views/overview.py b/passbook/admin/views/overview.py
index 49a402736..504b863b1 100644
--- a/passbook/admin/views/overview.py
+++ b/passbook/admin/views/overview.py
@@ -2,7 +2,7 @@
from django.views.generic import TemplateView
from passbook.admin.mixins import AdminRequiredMixin
-from passbook.core.models import Application, Provider, Rule, User
+from passbook.core.models import Application, Policy, Provider, User
class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
@@ -12,7 +12,7 @@ class AdministrationOverviewView(AdminRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
kwargs['application_count'] = len(Application.objects.all())
- kwargs['rule_count'] = len(Rule.objects.all())
+ kwargs['policy_count'] = len(Policy.objects.all())
kwargs['user_count'] = len(User.objects.all())
kwargs['provider_count'] = len(Provider.objects.all())
return super().get_context_data(**kwargs)
diff --git a/passbook/admin/views/policy.py b/passbook/admin/views/policy.py
new file mode 100644
index 000000000..1bf29dac4
--- /dev/null
+++ b/passbook/admin/views/policy.py
@@ -0,0 +1,104 @@
+"""passbook Policy administration"""
+from django.contrib import messages
+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, FormView, ListView,
+ UpdateView)
+from django.views.generic.detail import DetailView
+
+from passbook.admin.forms.policies import PolicyTestForm
+from passbook.admin.mixins import AdminRequiredMixin
+from passbook.core.models import Policy
+from passbook.lib.utils.reflection import path_to_class
+
+
+class PolicyListView(AdminRequiredMixin, ListView):
+ """Show list of all policys"""
+
+ model = Policy
+ template_name = 'administration/policy/list.html'
+
+ def get_context_data(self, **kwargs):
+ kwargs['types'] = {
+ x.__name__: x._meta.verbose_name for x in Policy.__subclasses__()}
+ return super().get_context_data(**kwargs)
+
+ def get_queryset(self):
+ return super().get_queryset().order_by('order').select_subclasses()
+
+
+class PolicyCreateView(SuccessMessageMixin, AdminRequiredMixin, CreateView):
+ """Create new Policy"""
+
+ template_name = 'generic/create_inheritance.html'
+ success_url = reverse_lazy('passbook_admin:policys')
+ success_message = _('Successfully created Policy')
+
+ def get_form_class(self):
+ policy_type = self.request.GET.get('type')
+ model = next(x for x in Policy.__subclasses__()
+ if x.__name__ == policy_type)
+ if not model:
+ raise Http404
+ return path_to_class(model.form)
+
+
+class PolicyUpdateView(SuccessMessageMixin, AdminRequiredMixin, UpdateView):
+ """Update policy"""
+
+ model = Policy
+ template_name = 'generic/update.html'
+ success_url = reverse_lazy('passbook_admin:policys')
+ success_message = _('Successfully updated Policy')
+
+ 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):
+ return Policy.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
+
+
+class PolicyDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
+ """Delete policy"""
+
+ model = Policy
+ template_name = 'generic/delete.html'
+ success_url = reverse_lazy('passbook_admin:policys')
+ success_message = _('Successfully updated Policy')
+
+ def get_object(self, queryset=None):
+ return Policy.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
+
+
+class PolicyTestView(AdminRequiredMixin, DetailView, FormView):
+ """View to test policy(s)"""
+
+ model = Policy
+ form_class = PolicyTestForm
+ template_name = 'administration/policy/test.html'
+ object = None
+
+ def get_object(self, queryset=None):
+ return Policy.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
+
+ def get_context_data(self, **kwargs):
+ kwargs['policy'] = self.get_object()
+ return super().get_context_data(**kwargs)
+
+ def post(self, *args, **kwargs):
+ self.object = self.get_object()
+ return super().post(*args, **kwargs)
+
+ def form_valid(self, form):
+ policy = self.get_object()
+ user = form.cleaned_data.get('user')
+ result = policy.passes(user)
+ if result:
+ messages.success(self.request, _('User successfully passed policy.'))
+ else:
+ messages.error(self.request, _("User didn't pass policy."))
+ return self.render_to_response(self.get_context_data(form=form, result=result))
diff --git a/passbook/admin/views/rules.py b/passbook/admin/views/rules.py
deleted file mode 100644
index c4aa85510..000000000
--- a/passbook/admin/views/rules.py
+++ /dev/null
@@ -1,104 +0,0 @@
-"""passbook Rule administration"""
-from django.contrib import messages
-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, FormView, ListView,
- UpdateView)
-from django.views.generic.detail import DetailView
-
-from passbook.admin.forms.rule import RuleTestForm
-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 = 'generic/create_inheritance.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):
- return Rule.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
-
-
-class RuleDeleteView(SuccessMessageMixin, AdminRequiredMixin, DeleteView):
- """Delete rule"""
-
- model = Rule
- template_name = 'generic/delete.html'
- success_url = reverse_lazy('passbook_admin:rules')
- success_message = _('Successfully updated Rule')
-
- def get_object(self, queryset=None):
- return Rule.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
-
-
-class RuleTestView(AdminRequiredMixin, DetailView, FormView):
- """View to test rule(s)"""
-
- model = Rule
- form_class = RuleTestForm
- template_name = 'administration/rule/test.html'
- object = None
-
- def get_object(self, queryset=None):
- return Rule.objects.filter(pk=self.kwargs.get('pk')).select_subclasses().first()
-
- def get_context_data(self, **kwargs):
- kwargs['rule'] = self.get_object()
- return super().get_context_data(**kwargs)
-
- def post(self, *args, **kwargs):
- self.object = self.get_object()
- return super().post(*args, **kwargs)
-
- def form_valid(self, form):
- rule = self.get_object()
- user = form.cleaned_data.get('user')
- result = rule.passes(user)
- if result:
- messages.success(self.request, _('User successfully passed rule.'))
- else:
- messages.error(self.request, _("User didn't pass rule."))
- return self.render_to_response(self.get_context_data(form=form, result=result))
diff --git a/passbook/audit/migrations/0001_initial.py b/passbook/audit/migrations/0001_initial.py
index d6b25b693..568b3d7d7 100644
--- a/passbook/audit/migrations/0001_initial.py
+++ b/passbook/audit/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.3 on 2018-11-25 10:39
+# Generated by Django 2.1.7 on 2019-02-16 09:13
import uuid
@@ -20,13 +20,32 @@ class Migration(migrations.Migration):
name='AuditEntry',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
- ('action', models.TextField()),
+ ('action', models.TextField(choices=[('login', 'login'), ('login_failed', 'login_failed'), ('logout', 'logout'), ('authorize_application', 'authorize_application'), ('suspicious_request', 'suspicious_request'), ('sign_up', 'sign_up'), ('password_reset', 'password_reset'), ('invitation_created', 'invitation_created'), ('invitation_used', 'invitation_used')])),
('date', models.DateTimeField(auto_now_add=True)),
('app', models.TextField()),
+ ('_context', models.TextField()),
+ ('request_ip', models.GenericIPAddressField()),
+ ('created', models.DateTimeField(auto_now_add=True)),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
],
options={
- 'abstract': False,
+ 'verbose_name': 'Audit Entry',
+ 'verbose_name_plural': 'Audit Entries',
},
),
+ migrations.CreateModel(
+ name='LoginAttempt',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('created', models.DateField(auto_now_add=True)),
+ ('last_updated', models.DateTimeField(auto_now=True)),
+ ('target_uid', models.CharField(max_length=254)),
+ ('request_ip', models.GenericIPAddressField()),
+ ('attempts', models.IntegerField(default=1)),
+ ],
+ ),
+ migrations.AlterUniqueTogether(
+ name='loginattempt',
+ unique_together={('target_uid', 'request_ip', 'created')},
+ ),
]
diff --git a/passbook/audit/migrations/0002_auto_20181210_1039.py b/passbook/audit/migrations/0002_auto_20181210_1039.py
deleted file mode 100644
index 67f88bbb6..000000000
--- a/passbook/audit/migrations/0002_auto_20181210_1039.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Generated by Django 2.1.4 on 2018-12-10 10:39
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_audit', '0001_initial'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='auditentry',
- name='context',
- field=models.TextField(default=''),
- preserve_default=False,
- ),
- migrations.AddField(
- model_name='auditentry',
- name='request_ip',
- field=models.GenericIPAddressField(default=''),
- preserve_default=False,
- ),
- migrations.AlterField(
- model_name='auditentry',
- name='action',
- field=models.TextField(choices=[('login', 'login'), ('login_failed', 'login_failed'), ('logout', 'logout'), ('authorize_application', 'authorize_application'), ('suspicious_request', 'suspicious_request'), ('sign_up', 'sign_up'), ('password_reset', 'password_reset')]),
- ),
- ]
diff --git a/passbook/audit/migrations/0003_auto_20181210_1213.py b/passbook/audit/migrations/0003_auto_20181210_1213.py
deleted file mode 100644
index 16d7c103a..000000000
--- a/passbook/audit/migrations/0003_auto_20181210_1213.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Generated by Django 2.1.4 on 2018-12-10 12:13
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_audit', '0002_auto_20181210_1039'),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name='auditentry',
- options={'verbose_name': 'Audit Entry', 'verbose_name_plural': 'Audit Entries'},
- ),
- migrations.RenameField(
- model_name='auditentry',
- old_name='context',
- new_name='_context',
- ),
- migrations.AlterField(
- model_name='auditentry',
- name='action',
- field=models.TextField(choices=[('login', 'login'), ('login_failed', 'login_failed'), ('logout', 'logout'), ('authorize_application', 'authorize_application'), ('suspicious_request', 'suspicious_request'), ('sign_up', 'sign_up'), ('password_reset', 'password_reset'), ('invitation_used', 'invitation_used')]),
- ),
- ]
diff --git a/passbook/audit/migrations/0004_auto_20181210_1348.py b/passbook/audit/migrations/0004_auto_20181210_1348.py
deleted file mode 100644
index b1e151fc3..000000000
--- a/passbook/audit/migrations/0004_auto_20181210_1348.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 2.1.4 on 2018-12-10 13:48
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_audit', '0003_auto_20181210_1213'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='auditentry',
- name='action',
- field=models.TextField(choices=[('login', 'login'), ('login_failed', 'login_failed'), ('logout', 'logout'), ('authorize_application', 'authorize_application'), ('suspicious_request', 'suspicious_request'), ('sign_up', 'sign_up'), ('password_reset', 'password_reset'), ('invitation_created', 'invitation_created'), ('invitation_used', 'invitation_used')]),
- ),
- ]
diff --git a/passbook/audit/migrations/0005_auditentry_created.py b/passbook/audit/migrations/0005_auditentry_created.py
deleted file mode 100644
index 5ee9c9118..000000000
--- a/passbook/audit/migrations/0005_auditentry_created.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Generated by Django 2.1.4 on 2018-12-11 15:00
-
-import django.utils.timezone
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_audit', '0004_auto_20181210_1348'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='auditentry',
- name='created',
- field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
- preserve_default=False,
- ),
- ]
diff --git a/passbook/audit/migrations/0006_auto_20181218_1252.py b/passbook/audit/migrations/0006_auto_20181218_1252.py
deleted file mode 100644
index 5317e3f6e..000000000
--- a/passbook/audit/migrations/0006_auto_20181218_1252.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 2.1.4 on 2018-12-18 12:52
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_audit', '0005_auditentry_created'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='LoginAttempt',
- fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('created', models.DateField(auto_now_add=True)),
- ('last_updated', models.DateTimeField(auto_now=True)),
- ('target_uid', models.CharField(max_length=254)),
- ('request_ip', models.GenericIPAddressField()),
- ('attempts', models.IntegerField(default=1)),
- ],
- ),
- migrations.AlterUniqueTogether(
- name='loginattempt',
- unique_together={('target_uid', 'request_ip', 'created')},
- ),
- ]
diff --git a/passbook/core/apps.py b/passbook/core/apps.py
index 8548b9da2..ae651b1b8 100644
--- a/passbook/core/apps.py
+++ b/passbook/core/apps.py
@@ -16,7 +16,7 @@ class PassbookCoreConfig(AppConfig):
verbose_name = 'passbook Core'
def ready(self):
- import_module('passbook.core.rules')
+ import_module('passbook.core.policies')
factors_to_load = CONFIG.y('passbook.factors', [])
for factors_to_load in factors_to_load:
try:
diff --git a/passbook/core/auth/view.py b/passbook/core/auth/view.py
index 8ef594e9e..e591b33cc 100644
--- a/passbook/core/auth/view.py
+++ b/passbook/core/auth/view.py
@@ -49,7 +49,7 @@ class AuthenticationView(UserPassesTestMixin, View):
self.pending_factors = request.session[AuthenticationView.SESSION_PENDING_FACTORS]
else:
# Get an initial list of factors which are currently enabled
- # and apply to the current user. We check rules here and block the request
+ # and apply to the current user. We check policies here and block the request
_all_factors = Factor.objects.filter(enabled=True)
self.pending_factors = []
for factor in _all_factors:
diff --git a/passbook/core/forms/applications.py b/passbook/core/forms/applications.py
index 4a7d50712..642de6471 100644
--- a/passbook/core/forms/applications.py
+++ b/passbook/core/forms/applications.py
@@ -13,7 +13,7 @@ class ApplicationForm(forms.ModelForm):
model = Application
fields = ['name', 'slug', 'launch_url', 'icon_url',
- 'rules', 'provider', 'skip_authorization']
+ 'policies', 'provider', 'skip_authorization']
widgets = {
'name': forms.TextInput(),
'launch_url': forms.TextInput(),
diff --git a/passbook/core/forms/factor.py b/passbook/core/forms/factor.py
index 326fe795f..9ad91c1fd 100644
--- a/passbook/core/forms/factor.py
+++ b/passbook/core/forms/factor.py
@@ -17,7 +17,7 @@ class FactorForm(forms.ModelForm):
class Meta:
model = Factor
- fields = ['name', 'slug', 'order', 'rules', 'type', 'enabled']
+ fields = ['name', 'slug', 'order', 'policies', 'type', 'enabled']
widgets = {
'type': forms.Select(choices=get_factors()),
'name': forms.TextInput(),
diff --git a/passbook/core/forms/rules.py b/passbook/core/forms/policies.py
similarity index 70%
rename from passbook/core/forms/rules.py
rename to passbook/core/forms/policies.py
index 0e83a23f4..c80a3bbc9 100644
--- a/passbook/core/forms/rules.py
+++ b/passbook/core/forms/policies.py
@@ -1,18 +1,18 @@
-"""passbook rule forms"""
+"""passbook Policy forms"""
from django import forms
from django.utils.translation import gettext as _
-from passbook.core.models import DebugRule, FieldMatcherRule, WebhookRule
+from passbook.core.models import DebugPolicy, FieldMatcherPolicy, WebhookPolicy
GENERAL_FIELDS = ['name', 'action', 'negate', 'order', ]
-class FieldMatcherRuleForm(forms.ModelForm):
- """FieldMatcherRule Form"""
+class FieldMatcherPolicyForm(forms.ModelForm):
+ """FieldMatcherPolicy Form"""
class Meta:
- model = FieldMatcherRule
+ model = FieldMatcherPolicy
fields = GENERAL_FIELDS + ['user_field', 'match_action', 'value', ]
widgets = {
'name': forms.TextInput(),
@@ -20,12 +20,12 @@ class FieldMatcherRuleForm(forms.ModelForm):
}
-class WebhookRuleForm(forms.ModelForm):
- """WebhookRuleForm Form"""
+class WebhookPolicyForm(forms.ModelForm):
+ """WebhookPolicyForm Form"""
class Meta:
- model = WebhookRule
+ model = WebhookPolicy
fields = GENERAL_FIELDS + ['url', 'method', 'json_body', 'json_headers',
'result_jsonpath', 'result_json_value', ]
widgets = {
@@ -37,12 +37,12 @@ class WebhookRuleForm(forms.ModelForm):
}
-class DebugRuleForm(forms.ModelForm):
- """DebugRuleForm Form"""
+class DebugPolicyForm(forms.ModelForm):
+ """DebugPolicyForm Form"""
class Meta:
- model = DebugRule
+ model = DebugPolicy
fields = GENERAL_FIELDS + ['result', 'wait_min', 'wait_max']
widgets = {
'name': forms.TextInput(),
diff --git a/passbook/core/migrations/0001_initial.py b/passbook/core/migrations/0001_initial.py
index c3afb6961..94e90987e 100644
--- a/passbook/core/migrations/0001_initial.py
+++ b/passbook/core/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.5 on 2019-02-08 10:42
+# Generated by Django 2.1.7 on 2019-02-16 09:10
import uuid
@@ -68,13 +68,7 @@ class Migration(migrations.Migration):
},
),
migrations.CreateModel(
- name='Provider',
- fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ],
- ),
- migrations.CreateModel(
- name='Rule',
+ name='Policy',
fields=[
('created', models.DateField(auto_now_add=True)),
('last_updated', models.DateTimeField(auto_now=True)),
@@ -89,7 +83,7 @@ class Migration(migrations.Migration):
},
),
migrations.CreateModel(
- name='RuleModel',
+ name='PolicyModel',
fields=[
('created', models.DateField(auto_now_add=True)),
('last_updated', models.DateTimeField(auto_now=True)),
@@ -99,6 +93,12 @@ class Migration(migrations.Migration):
'abstract': False,
},
),
+ migrations.CreateModel(
+ name='Provider',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ],
+ ),
migrations.CreateModel(
name='UserSourceConnection',
fields=[
@@ -111,51 +111,82 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Application',
fields=[
- ('rulemodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.RuleModel')),
+ ('policymodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PolicyModel')),
('name', models.TextField()),
('slug', models.SlugField()),
('launch_url', models.URLField(blank=True, null=True)),
('icon_url', models.TextField(blank=True, null=True)),
('skip_authorization', models.BooleanField(default=False)),
- ('provider', models.OneToOneField(default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='passbook_core.Provider')),
+ ('provider', models.OneToOneField(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='passbook_core.Provider')),
],
options={
'abstract': False,
},
- bases=('passbook_core.rulemodel',),
+ bases=('passbook_core.policymodel',),
),
migrations.CreateModel(
- name='DebugRule',
+ name='DebugPolicy',
fields=[
- ('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Rule')),
+ ('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('result', models.BooleanField(default=False)),
('wait_min', models.IntegerField(default=5)),
('wait_max', models.IntegerField(default=30)),
],
options={
- 'verbose_name': 'Debug Rule',
- 'verbose_name_plural': 'Debug Rules',
+ 'verbose_name': 'Debug Policy',
+ 'verbose_name_plural': 'Debug Policys',
},
- bases=('passbook_core.rule',),
+ bases=('passbook_core.policy',),
),
migrations.CreateModel(
- name='FieldMatcherRule',
+ name='Factor',
fields=[
- ('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Rule')),
- ('user_field', models.TextField(choices=[('username', 'username'), ('first_name', 'first_name'), ('last_name', 'last_name'), ('email', 'email'), ('is_staff', 'is_staff'), ('is_active', 'is_active'), ('data_joined', 'data_joined')])),
+ ('policymodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PolicyModel')),
+ ('name', models.TextField()),
+ ('slug', models.SlugField(unique=True)),
+ ('order', models.IntegerField()),
+ ('type', models.TextField(unique=True)),
+ ('enabled', models.BooleanField(default=True)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ bases=('passbook_core.policymodel',),
+ ),
+ migrations.CreateModel(
+ name='FieldMatcherPolicy',
+ fields=[
+ ('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
+ ('user_field', models.TextField(choices=[('username', 'Username'), ('first_name', 'First Name'), ('last_name', 'Last Name'), ('email', 'E-Mail'), ('is_staff', 'Is staff'), ('is_active', 'Is active'), ('data_joined', 'Date joined')])),
('match_action', models.CharField(choices=[('startswith', 'Starts with'), ('endswith', 'Ends with'), ('endswith', 'Contains'), ('regexp', 'Regexp'), ('exact', 'Exact')], max_length=50)),
('value', models.TextField()),
],
options={
- 'verbose_name': 'Field matcher Rule',
- 'verbose_name_plural': 'Field matcher Rules',
+ 'verbose_name': 'Field matcher Policy',
+ 'verbose_name_plural': 'Field matcher Policys',
},
- bases=('passbook_core.rule',),
+ bases=('passbook_core.policy',),
+ ),
+ migrations.CreateModel(
+ name='PasswordPolicyPolicy',
+ fields=[
+ ('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
+ ('amount_uppercase', models.IntegerField(default=0)),
+ ('amount_lowercase', models.IntegerField(default=0)),
+ ('amount_symbols', models.IntegerField(default=0)),
+ ('length_min', models.IntegerField(default=0)),
+ ('symbol_charset', models.TextField(default='!\\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ ')),
+ ],
+ options={
+ 'verbose_name': 'Password Policy Policy',
+ 'verbose_name_plural': 'Password Policy Policys',
+ },
+ bases=('passbook_core.policy',),
),
migrations.CreateModel(
name='Source',
fields=[
- ('rulemodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.RuleModel')),
+ ('policymodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.PolicyModel')),
('name', models.TextField()),
('slug', models.SlugField()),
('enabled', models.BooleanField(default=True)),
@@ -163,12 +194,12 @@ class Migration(migrations.Migration):
options={
'abstract': False,
},
- bases=('passbook_core.rulemodel',),
+ bases=('passbook_core.policymodel',),
),
migrations.CreateModel(
- name='WebhookRule',
+ name='WebhookPolicy',
fields=[
- ('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Rule')),
+ ('policy_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Policy')),
('url', models.URLField()),
('method', models.CharField(choices=[('GET', 'GET'), ('POST', 'POST'), ('PATCH', 'PATCH'), ('DELETE', 'DELETE'), ('PUT', 'PUT')], max_length=10)),
('json_body', models.TextField()),
@@ -177,15 +208,15 @@ class Migration(migrations.Migration):
('result_json_value', models.TextField()),
],
options={
- 'verbose_name': 'Webhook Rule',
- 'verbose_name_plural': 'Webhook Rules',
+ 'verbose_name': 'Webhook Policy',
+ 'verbose_name_plural': 'Webhook Policys',
},
- bases=('passbook_core.rule',),
+ bases=('passbook_core.policy',),
),
migrations.AddField(
- model_name='rulemodel',
- name='rules',
- field=models.ManyToManyField(blank=True, to='passbook_core.Rule'),
+ model_name='policymodel',
+ name='policies',
+ field=models.ManyToManyField(blank=True, to='passbook_core.Policy'),
),
migrations.AddField(
model_name='user',
diff --git a/passbook/core/migrations/0002_auto_20190208_1514.py b/passbook/core/migrations/0002_auto_20190208_1514.py
deleted file mode 100644
index 1280d5a46..000000000
--- a/passbook/core/migrations/0002_auto_20190208_1514.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Generated by Django 2.1.5 on 2019-02-08 15:14
-
-import django.db.models.deletion
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_core', '0001_initial'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='PasswordPolicyRule',
- fields=[
- ('rule_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.Rule')),
- ('amount_uppercase', models.IntegerField(default=0)),
- ('amount_lowercase', models.IntegerField(default=0)),
- ('amount_symbols', models.IntegerField(default=0)),
- ('length_min', models.IntegerField(default=0)),
- ('symbol_charset', models.TextField(default='!\\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ ')),
- ],
- options={
- 'verbose_name': 'Password Policy Rule',
- 'verbose_name_plural': 'Password Policy Rules',
- },
- bases=('passbook_core.rule',),
- ),
- migrations.AlterField(
- model_name='fieldmatcherrule',
- name='user_field',
- field=models.TextField(choices=[('username', 'Username'), ('first_name', 'First Name'), ('last_name', 'Last Name'), ('email', 'E-Mail'), ('is_staff', 'Is staff'), ('is_active', 'Is active'), ('data_joined', 'Date joined')]),
- ),
- ]
diff --git a/passbook/core/migrations/0003_factor.py b/passbook/core/migrations/0003_factor.py
deleted file mode 100644
index b9da82781..000000000
--- a/passbook/core/migrations/0003_factor.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 2.1.7 on 2019-02-14 15:41
-
-import django.db.models.deletion
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_core', '0002_auto_20190208_1514'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Factor',
- fields=[
- ('rulemodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='passbook_core.RuleModel')),
- ('name', models.TextField()),
- ('slug', models.SlugField(unique=True)),
- ('order', models.IntegerField()),
- ('type', models.TextField()),
- ],
- options={
- 'abstract': False,
- },
- bases=('passbook_core.rulemodel',),
- ),
- ]
diff --git a/passbook/core/migrations/0004_auto_20190215_1534.py b/passbook/core/migrations/0004_auto_20190215_1534.py
deleted file mode 100644
index d31c8de23..000000000
--- a/passbook/core/migrations/0004_auto_20190215_1534.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Generated by Django 2.1.7 on 2019-02-15 15:34
-
-import django.db.models.deletion
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_core', '0003_factor'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='factor',
- name='enabled',
- field=models.BooleanField(default=True),
- ),
- migrations.AlterField(
- model_name='application',
- name='provider',
- field=models.OneToOneField(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='passbook_core.Provider'),
- ),
- ]
diff --git a/passbook/core/migrations/0005_auto_20190216_0853.py b/passbook/core/migrations/0005_auto_20190216_0853.py
deleted file mode 100644
index 15fd936bd..000000000
--- a/passbook/core/migrations/0005_auto_20190216_0853.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 2.1.7 on 2019-02-16 08:53
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_core', '0004_auto_20190215_1534'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='factor',
- name='type',
- field=models.TextField(unique=True),
- ),
- ]
diff --git a/passbook/core/models.py b/passbook/core/models.py
index 78c6dbbee..82ed89976 100644
--- a/passbook/core/models.py
+++ b/passbook/core/models.py
@@ -49,19 +49,19 @@ class Provider(models.Model):
return getattr(self, 'name')
return super().__str__()
-class RuleModel(UUIDModel, CreatedUpdatedModel):
- """Base model which can have rules applied to it"""
+class PolicyModel(UUIDModel, CreatedUpdatedModel):
+ """Base model which can have policies applied to it"""
- rules = models.ManyToManyField('Rule', blank=True)
+ policies = models.ManyToManyField('Policy', blank=True)
def passes(self, user: User) -> bool:
"""Return true if user passes, otherwise False or raise Exception"""
- for rule in self.rules:
- if not rule.passes(user):
+ for policy in self.policies:
+ if not policy.passes(user):
return False
return True
-class Factor(RuleModel):
+class Factor(PolicyModel):
"""Authentication factor, multiple instances of the same Factor can be used"""
name = models.TextField()
@@ -73,7 +73,7 @@ class Factor(RuleModel):
def __str__(self):
return "Factor %s" % self.slug
-class Application(RuleModel):
+class Application(PolicyModel):
"""Every Application which uses passbook for authentication/identification/authorization
needs an Application record. Other authentication types can subclass this Model to
add custom fields and other properties"""
@@ -90,13 +90,13 @@ class Application(RuleModel):
def user_is_authorized(self, user: User) -> bool:
"""Check if user is authorized to use this application"""
- from passbook.core.rules import RuleEngine
- return RuleEngine(self.rules.all()).for_user(user).result
+ from passbook.core.policies import PolicyEngine
+ return PolicyEngine(self.policies.all()).for_user(user).result
def __str__(self):
return self.name
-class Source(RuleModel):
+class Source(PolicyModel):
"""Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server"""
name = models.TextField()
@@ -129,8 +129,8 @@ class UserSourceConnection(CreatedUpdatedModel):
unique_together = (('user', 'source'),)
-class Rule(UUIDModel, CreatedUpdatedModel):
- """Rules which specify if a user is authorized to use an Application. Can be overridden by
+class Policy(UUIDModel, CreatedUpdatedModel):
+ """Policys which specify if a user is authorized to use an Application. Can be overridden by
other types to add other fields, more logic, etc."""
ACTION_ALLOW = 'allow'
@@ -153,11 +153,11 @@ class Rule(UUIDModel, CreatedUpdatedModel):
return "%s action %s" % (self.name, self.action)
def passes(self, user: User) -> bool:
- """Check if user instance passes this rule"""
+ """Check if user instance passes this policy"""
raise NotImplementedError()
-class FieldMatcherRule(Rule):
- """Rule which checks if a field of the User model matches/doesn't match a
+class FieldMatcherPolicy(Policy):
+ """Policy which checks if a field of the User model matches/doesn't match a
certain pattern"""
MATCH_STARTSWITH = 'startswith'
@@ -188,7 +188,7 @@ class FieldMatcherRule(Rule):
match_action = models.CharField(max_length=50, choices=MATCHES)
value = models.TextField()
- form = 'passbook.core.forms.rules.FieldMatcherRuleForm'
+ form = 'passbook.core.forms.policies.FieldMatcherPolicyForm'
def __str__(self):
description = "%s, user.%s %s '%s'" % (self.name, self.user_field,
@@ -205,13 +205,13 @@ class FieldMatcherRule(Rule):
LOGGER.debug("Checked '%s' %s with '%s'...",
user_field_value, self.match_action, self.value)
passes = False
- if self.match_action == FieldMatcherRule.MATCH_STARTSWITH:
+ if self.match_action == FieldMatcherPolicy.MATCH_STARTSWITH:
passes = user_field_value.startswith(self.value)
- if self.match_action == FieldMatcherRule.MATCH_ENDSWITH:
+ if self.match_action == FieldMatcherPolicy.MATCH_ENDSWITH:
passes = user_field_value.endswith(self.value)
- if self.match_action == FieldMatcherRule.MATCH_CONTAINS:
+ if self.match_action == FieldMatcherPolicy.MATCH_CONTAINS:
passes = self.value in user_field_value
- if self.match_action == FieldMatcherRule.MATCH_REGEXP:
+ if self.match_action == FieldMatcherPolicy.MATCH_REGEXP:
pattern = re.compile(self.value)
passes = bool(pattern.match(user_field_value))
if self.negate:
@@ -221,11 +221,11 @@ class FieldMatcherRule(Rule):
class Meta:
- verbose_name = _('Field matcher Rule')
- verbose_name_plural = _('Field matcher Rules')
+ verbose_name = _('Field matcher Policy')
+ verbose_name_plural = _('Field matcher Policys')
-class PasswordPolicyRule(Rule):
- """Rule to make sure passwords have certain properties"""
+class PasswordPolicyPolicy(Policy):
+ """Policy to make sure passwords have certain properties"""
amount_uppercase = models.IntegerField(default=0)
amount_lowercase = models.IntegerField(default=0)
@@ -233,7 +233,7 @@ class PasswordPolicyRule(Rule):
length_min = models.IntegerField(default=0)
symbol_charset = models.TextField(default=r"!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ")
- form = 'passbook.core.forms.rules.PasswordPolicyRuleForm'
+ form = 'passbook.core.forms.policies.PasswordPolicyPolicyForm'
def passes(self, user: User) -> bool:
# Only check if password is being set
@@ -254,12 +254,12 @@ class PasswordPolicyRule(Rule):
class Meta:
- verbose_name = _('Password Policy Rule')
- verbose_name_plural = _('Password Policy Rules')
+ verbose_name = _('Password Policy Policy')
+ verbose_name_plural = _('Password Policy Policys')
-class WebhookRule(Rule):
- """Rule that asks webhook"""
+class WebhookPolicy(Policy):
+ """Policy that asks webhook"""
METHOD_GET = 'GET'
METHOD_POST = 'POST'
@@ -282,7 +282,7 @@ class WebhookRule(Rule):
result_jsonpath = models.TextField()
result_json_value = models.TextField()
- form = 'passbook.core.forms.rules.WebhookRuleForm'
+ form = 'passbook.core.forms.policies.WebhookPolicyForm'
def passes(self, user: User):
"""Call webhook asynchronously and report back"""
@@ -290,30 +290,30 @@ class WebhookRule(Rule):
class Meta:
- verbose_name = _('Webhook Rule')
- verbose_name_plural = _('Webhook Rules')
+ verbose_name = _('Webhook Policy')
+ verbose_name_plural = _('Webhook Policys')
-class DebugRule(Rule):
- """Rule used for debugging the RuleEngine. Returns a fixed result,
+class DebugPolicy(Policy):
+ """Policy used for debugging the PolicyEngine. Returns a fixed result,
but takes a random time to process."""
result = models.BooleanField(default=False)
wait_min = models.IntegerField(default=5)
wait_max = models.IntegerField(default=30)
- form = 'passbook.core.forms.rules.DebugRuleForm'
+ form = 'passbook.core.forms.policies.DebugPolicyForm'
def passes(self, user: User):
"""Wait random time then return result"""
wait = SystemRandom().randrange(self.wait_min, self.wait_max)
- LOGGER.debug("Rule '%s' waiting for %ds", self.name, wait)
+ LOGGER.debug("Policy '%s' waiting for %ds", self.name, wait)
sleep(wait)
return self.result
class Meta:
- verbose_name = _('Debug Rule')
- verbose_name_plural = _('Debug Rules')
+ verbose_name = _('Debug Policy')
+ verbose_name_plural = _('Debug Policys')
class Invitation(UUIDModel):
"""Single-use invitation link"""
diff --git a/passbook/core/policies.py b/passbook/core/policies.py
new file mode 100644
index 000000000..b501ea97f
--- /dev/null
+++ b/passbook/core/policies.py
@@ -0,0 +1,48 @@
+"""passbook core policy engine"""
+from logging import getLogger
+
+from celery import group
+
+from passbook.core.celery import CELERY_APP
+from passbook.core.models import Policy, User
+
+LOGGER = getLogger(__name__)
+
+@CELERY_APP.task()
+def _policy_engine_task(user_pk, policy_pk, **kwargs):
+ """Task wrapper to run policy checking"""
+ policy_obj = Policy.objects.filter(pk=policy_pk).select_subclasses().first()
+ user_obj = User.objects.get(pk=user_pk)
+ for key, value in kwargs.items():
+ setattr(user_obj, key, value)
+ LOGGER.debug("Running policy `%s`#%s for user %s...", policy_obj.name,
+ policy_obj.pk.hex, user_obj)
+ return policy_obj.passes(user_obj)
+
+class PolicyEngine:
+ """Orchestrate policy checking, launch tasks and return result"""
+
+ policies = None
+ _group = None
+
+ def __init__(self, policies):
+ self.policies = policies
+
+ def for_user(self, user):
+ """Check policies for user"""
+ signatures = []
+ kwargs = {
+ '__password__': getattr(user, '__password__')
+ }
+ for policy in self.policies:
+ signatures.append(_policy_engine_task.s(user.pk, policy.pk.hex, **kwargs))
+ self._group = group(signatures)()
+ return self
+
+ @property
+ def result(self):
+ """Get policy-checking result"""
+ for policy_result in self._group.get():
+ if policy_result is False:
+ return False
+ return True
diff --git a/passbook/core/rules.py b/passbook/core/rules.py
deleted file mode 100644
index 29376fc09..000000000
--- a/passbook/core/rules.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""passbook core rule engine"""
-from logging import getLogger
-
-from celery import group
-
-from passbook.core.celery import CELERY_APP
-from passbook.core.models import Rule, User
-
-LOGGER = getLogger(__name__)
-
-@CELERY_APP.task()
-def _rule_engine_task(user_pk, rule_pk, **kwargs):
- """Task wrapper to run rule checking"""
- rule_obj = Rule.objects.filter(pk=rule_pk).select_subclasses().first()
- user_obj = User.objects.get(pk=user_pk)
- for key, value in kwargs.items():
- setattr(user_obj, key, value)
- LOGGER.debug("Running rule `%s`#%s for user %s...", rule_obj.name, rule_obj.pk.hex, user_obj)
- return rule_obj.passes(user_obj)
-
-class RuleEngine:
- """Orchestrate rule checking, launch tasks and return result"""
-
- rules = None
- _group = None
-
- def __init__(self, rules):
- self.rules = rules
-
- def for_user(self, user):
- """Check rules for user"""
- signatures = []
- kwargs = {
- '__password__': getattr(user, '__password__')
- }
- for rule in self.rules:
- signatures.append(_rule_engine_task.s(user.pk, rule.pk.hex, **kwargs))
- self._group = group(signatures)()
- return self
-
- @property
- def result(self):
- """Get rule-checking result"""
- for rule_result in self._group.get():
- if rule_result is False:
- return False
- return True
diff --git a/passbook/ldap/forms.py b/passbook/ldap/forms.py
index c963ae024..fbe6e55c3 100644
--- a/passbook/ldap/forms.py
+++ b/passbook/ldap/forms.py
@@ -14,7 +14,7 @@ class LDAPSourceForm(forms.ModelForm):
model = LDAPSource
fields = SOURCE_FORM_FIELDS + ['server_uri', 'bind_cn', 'bind_password',
'type', 'domain', 'base_dn', 'create_user',
- 'reset_password', 'rules']
+ 'reset_password', 'policies']
widgets = {
'name': forms.TextInput(),
'server_uri': forms.TextInput(),
diff --git a/passbook/ldap/migrations/0001_initial.py b/passbook/ldap/migrations/0001_initial.py
index 22b8e928d..4d432c79a 100644
--- a/passbook/ldap/migrations/0001_initial.py
+++ b/passbook/ldap/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.4 on 2018-12-10 09:16
+# Generated by Django 2.1.7 on 2019-02-16 09:13
import django.db.models.deletion
from django.db import migrations, models
diff --git a/passbook/oauth_client/migrations/0001_initial.py b/passbook/oauth_client/migrations/0001_initial.py
index 7894cad5f..5642bec33 100644
--- a/passbook/oauth_client/migrations/0001_initial.py
+++ b/passbook/oauth_client/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.4 on 2018-12-10 09:16
+# Generated by Django 2.1.7 on 2019-02-16 09:13
import django.db.models.deletion
from django.db import migrations, models
@@ -26,8 +26,8 @@ class Migration(migrations.Migration):
('consumer_secret', models.TextField()),
],
options={
- 'verbose_name': 'OAuth Source',
- 'verbose_name_plural': 'OAuth Sources',
+ 'verbose_name': 'Generic OAuth Source',
+ 'verbose_name_plural': 'Generic OAuth Sources',
},
bases=('passbook_core.source',),
),
diff --git a/passbook/oauth_client/migrations/0002_auto_20181218_1019.py b/passbook/oauth_client/migrations/0002_auto_20181218_1019.py
deleted file mode 100644
index e276234b4..000000000
--- a/passbook/oauth_client/migrations/0002_auto_20181218_1019.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Generated by Django 2.1.4 on 2018-12-18 10:19
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_oauth_client', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name='oauthsource',
- options={'verbose_name': 'Generic OAuth Source', 'verbose_name_plural': 'Generic OAuth Sources'},
- ),
- ]
diff --git a/passbook/oauth_provider/migrations/0001_initial.py b/passbook/oauth_provider/migrations/0001_initial.py
index 783c536a3..b25fedbca 100644
--- a/passbook/oauth_provider/migrations/0001_initial.py
+++ b/passbook/oauth_provider/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.3 on 2018-11-25 10:39
+# Generated by Django 2.1.7 on 2019-02-16 09:13
import django.db.models.deletion
import oauth2_provider.generators
@@ -15,8 +15,8 @@ class Migration(migrations.Migration):
]
dependencies = [
- ('passbook_core', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('passbook_core', '0001_initial'),
]
operations = [
@@ -36,7 +36,8 @@ class Migration(migrations.Migration):
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='passbook_oauth_provider_oauth2provider', to=settings.AUTH_USER_MODEL)),
],
options={
- 'abstract': False,
+ 'verbose_name': 'OAuth2 Provider',
+ 'verbose_name_plural': 'OAuth2 Providers',
},
bases=('passbook_core.provider', models.Model),
),
diff --git a/passbook/oauth_provider/migrations/0002_auto_20181126_1514.py b/passbook/oauth_provider/migrations/0002_auto_20181126_1514.py
deleted file mode 100644
index ec85f7878..000000000
--- a/passbook/oauth_provider/migrations/0002_auto_20181126_1514.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Generated by Django 2.1.3 on 2018-11-26 15:14
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('passbook_oauth_provider', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name='oauth2provider',
- options={'verbose_name': 'OAuth2 Provider', 'verbose_name_plural': 'OAuth2 Providers'},
- ),
- ]
diff --git a/passbook/oauth_provider/views/oauth2.py b/passbook/oauth_provider/views/oauth2.py
index 99d2e271e..f30d14e12 100644
--- a/passbook/oauth_provider/views/oauth2.py
+++ b/passbook/oauth_provider/views/oauth2.py
@@ -29,7 +29,7 @@ class OAuthPermissionDenied(PermissionDeniedView):
class PassbookAuthorizationView(AccessMixin, AuthorizationView):
- """Custom OAuth2 Authorization View which checks rules, etc"""
+ """Custom OAuth2 Authorization View which checks policies, etc"""
_application = None
diff --git a/passbook/saml_idp/migrations/0001_initial.py b/passbook/saml_idp/migrations/0001_initial.py
index 91878da0e..4a210df76 100644
--- a/passbook/saml_idp/migrations/0001_initial.py
+++ b/passbook/saml_idp/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.4 on 2018-12-10 09:16
+# Generated by Django 2.1.7 on 2019-02-16 09:13
import django.db.models.deletion
from django.db import migrations, models