admin: add flows
This commit is contained in:
parent
872ecd93a6
commit
08c0eb2ec6
|
@ -6,8 +6,8 @@ from defusedxml import defuse_stdlib
|
||||||
|
|
||||||
defuse_stdlib()
|
defuse_stdlib()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'passbook.root.settings')
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "passbook.root.settings")
|
||||||
try:
|
try:
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
|
|
|
@ -52,6 +52,12 @@
|
||||||
{% trans 'Property Mappings' %}
|
{% trans 'Property Mappings' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="pf-c-nav__item">
|
||||||
|
<a href="{% url 'passbook_admin:flows' %}"
|
||||||
|
class="pf-c-nav__link {% is_active 'passbook_admin:flows' 'passbook_admin:flow-create' 'passbook_admin:flow-update' 'passbook_admin:flow-delete' %}">
|
||||||
|
{% trans 'Flows' %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li class="pf-c-nav__item">
|
<li class="pf-c-nav__item">
|
||||||
<a href="{% url 'passbook_admin:factors' %}"
|
<a href="{% url 'passbook_admin:factors' %}"
|
||||||
class="pf-c-nav__link {% is_active 'passbook_admin:factors' 'passbook_admin:factor-create' 'passbook_admin:factor-update' 'passbook_admin:factor-delete' %}">
|
class="pf-c-nav__link {% is_active 'passbook_admin:factors' 'passbook_admin:factor-create' 'passbook_admin:factor-update' 'passbook_admin:factor-delete' %}">
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
{% extends "administration/base.html" %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
{% load utils %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section class="pf-c-page__main-section pf-m-light">
|
||||||
|
<div class="pf-c-content">
|
||||||
|
<h1>
|
||||||
|
<i class="pf-icon pf-icon-process-automation"></i>
|
||||||
|
{% trans 'Flows' %}
|
||||||
|
</h1>
|
||||||
|
<p>{% trans "Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them." %}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||||
|
<div class="pf-c-card">
|
||||||
|
<div class="pf-c-toolbar" id="page-layout-table-simple-toolbar-top">
|
||||||
|
<div class="pf-c-toolbar__action-group">
|
||||||
|
<a href="{% url 'passbook_admin:flow-create' %}?back={{ request.get_full_path }}" class="pf-c-button pf-m-primary" type="button">{% trans 'Create' %}</a>
|
||||||
|
</div>
|
||||||
|
{% include 'partials/pagination.html' %}
|
||||||
|
</div>
|
||||||
|
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
|
||||||
|
<thead>
|
||||||
|
<tr role="row">
|
||||||
|
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
|
||||||
|
<th role="columnheader" scope="col">{% trans 'Designation' %}</th>
|
||||||
|
<th role="columnheader" scope="col">{% trans 'Factors' %}</th>
|
||||||
|
<th role="columnheader" scope="col">{% trans 'Policies' %}</th>
|
||||||
|
<th role="cell"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody role="rowgroup">
|
||||||
|
{% for flow in object_list %}
|
||||||
|
<tr role="row">
|
||||||
|
<th role="columnheader">
|
||||||
|
<div>
|
||||||
|
<div>{{ flow.name }}</div>
|
||||||
|
<small>{{ flow.slug }}</small>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
<td role="cell">
|
||||||
|
<span>
|
||||||
|
{{ flow.designation }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td role="cell">
|
||||||
|
<span>
|
||||||
|
{{ flow.factors.all|length }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td role="cell">
|
||||||
|
<span>
|
||||||
|
{{ flow.policies.all|length }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a class="pf-c-button pf-m-secondary" href="{% url 'passbook_admin:flow-update' pk=flow.pk %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>
|
||||||
|
<a class="pf-c-button pf-m-danger" href="{% url 'passbook_admin:flow-delete' pk=flow.pk %}?back={{ request.get_full_path }}">{% trans 'Delete' %}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="pf-c-toolbar" id="page-layout-table-simple-toolbar-bottom">
|
||||||
|
{% include 'partials/pagination.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
|
@ -7,6 +7,7 @@ from passbook.admin.views import (
|
||||||
certificate_key_pair,
|
certificate_key_pair,
|
||||||
debug,
|
debug,
|
||||||
factors,
|
factors,
|
||||||
|
flows,
|
||||||
groups,
|
groups,
|
||||||
invitations,
|
invitations,
|
||||||
overview,
|
overview,
|
||||||
|
@ -97,6 +98,15 @@ urlpatterns = [
|
||||||
factors.FactorDeleteView.as_view(),
|
factors.FactorDeleteView.as_view(),
|
||||||
name="factor-delete",
|
name="factor-delete",
|
||||||
),
|
),
|
||||||
|
# Flows
|
||||||
|
path("flows/", flows.FlowListView.as_view(), name="flows"),
|
||||||
|
path("flows/create/", flows.FlowCreateView.as_view(), name="flow-create",),
|
||||||
|
path(
|
||||||
|
"flows/<uuid:pk>/update/", flows.FlowUpdateView.as_view(), name="flow-update",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"flows/<uuid:pk>/delete/", flows.FlowDeleteView.as_view(), name="flow-delete",
|
||||||
|
),
|
||||||
# Factors
|
# Factors
|
||||||
path(
|
path(
|
||||||
"property-mappings/",
|
"property-mappings/",
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
"""passbook Flow administration"""
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.contrib.auth.mixins import (
|
||||||
|
PermissionRequiredMixin as DjangoPermissionRequiredMixin,
|
||||||
|
)
|
||||||
|
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 DeleteView, ListView, UpdateView
|
||||||
|
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
|
||||||
|
|
||||||
|
from passbook.flows.forms import FlowForm
|
||||||
|
from passbook.flows.models import Flow
|
||||||
|
from passbook.lib.views import CreateAssignPermView
|
||||||
|
|
||||||
|
|
||||||
|
class FlowListView(LoginRequiredMixin, PermissionListMixin, ListView):
|
||||||
|
"""Show list of all flows"""
|
||||||
|
|
||||||
|
model = Flow
|
||||||
|
permission_required = "passbook_flows.view_flow"
|
||||||
|
ordering = "name"
|
||||||
|
paginate_by = 40
|
||||||
|
template_name = "administration/flow/list.html"
|
||||||
|
|
||||||
|
|
||||||
|
class FlowCreateView(
|
||||||
|
SuccessMessageMixin,
|
||||||
|
LoginRequiredMixin,
|
||||||
|
DjangoPermissionRequiredMixin,
|
||||||
|
CreateAssignPermView,
|
||||||
|
):
|
||||||
|
"""Create new Flow"""
|
||||||
|
|
||||||
|
model = Flow
|
||||||
|
form_class = FlowForm
|
||||||
|
permission_required = "passbook_flows.add_flow"
|
||||||
|
|
||||||
|
template_name = "generic/create.html"
|
||||||
|
success_url = reverse_lazy("passbook_admin:flows")
|
||||||
|
success_message = _("Successfully created Flow")
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs["type"] = "Flow"
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class FlowUpdateView(
|
||||||
|
SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView
|
||||||
|
):
|
||||||
|
"""Update flow"""
|
||||||
|
|
||||||
|
model = Flow
|
||||||
|
form_class = FlowForm
|
||||||
|
permission_required = "passbook_flows.change_flow"
|
||||||
|
|
||||||
|
template_name = "generic/update.html"
|
||||||
|
success_url = reverse_lazy("passbook_admin:flows")
|
||||||
|
success_message = _("Successfully updated Flow")
|
||||||
|
|
||||||
|
|
||||||
|
class FlowDeleteView(
|
||||||
|
SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView
|
||||||
|
):
|
||||||
|
"""Delete flow"""
|
||||||
|
|
||||||
|
model = Flow
|
||||||
|
permission_required = "passbook_flows.delete_flow"
|
||||||
|
|
||||||
|
template_name = "generic/delete.html"
|
||||||
|
success_url = reverse_lazy("passbook_admin:flows")
|
||||||
|
success_message = _("Successfully deleted Flow")
|
||||||
|
|
||||||
|
def delete(self, request, *args, **kwargs):
|
||||||
|
messages.success(self.request, self.success_message)
|
||||||
|
return super().delete(request, *args, **kwargs)
|
|
@ -11,14 +11,7 @@ class FlowSerializer(ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
model = Flow
|
model = Flow
|
||||||
fields = [
|
fields = ["pk", "name", "slug", "designation", "factors", "policies"]
|
||||||
"pk",
|
|
||||||
"name",
|
|
||||||
"slug",
|
|
||||||
"designation",
|
|
||||||
"factors",
|
|
||||||
"policies"
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class FlowViewSet(ModelViewSet):
|
class FlowViewSet(ModelViewSet):
|
||||||
|
@ -34,14 +27,7 @@ class FlowFactorBindingSerializer(ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
model = FlowFactorBinding
|
model = FlowFactorBinding
|
||||||
fields = [
|
fields = ["pk", "flow", "factor", "re_evaluate_policies", "order", "policies"]
|
||||||
"pk",
|
|
||||||
"flow",
|
|
||||||
"factor",
|
|
||||||
"re_evaluate_policies",
|
|
||||||
"order",
|
|
||||||
"policies"
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class FlowFactorBindingViewSet(ModelViewSet):
|
class FlowFactorBindingViewSet(ModelViewSet):
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.0.3 on 2020-05-08 16:42
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("passbook_core", "0011_auto_20200222_1822"),
|
||||||
|
("passbook_flows", "0004_default_flows"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="flow",
|
||||||
|
name="factors",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
through="passbook_flows.FlowFactorBinding",
|
||||||
|
to="passbook_core.Factor",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -36,7 +36,7 @@ class Flow(PolicyBindingModel, UUIDModel):
|
||||||
|
|
||||||
designation = models.CharField(max_length=100, choices=FlowDesignation.as_choices())
|
designation = models.CharField(max_length=100, choices=FlowDesignation.as_choices())
|
||||||
|
|
||||||
factors = models.ManyToManyField(Factor, through="FlowFactorBinding")
|
factors = models.ManyToManyField(Factor, through="FlowFactorBinding", blank=True)
|
||||||
|
|
||||||
pbm = models.OneToOneField(
|
pbm = models.OneToOneField(
|
||||||
PolicyBindingModel, parent_link=True, on_delete=models.CASCADE, related_name="+"
|
PolicyBindingModel, parent_link=True, on_delete=models.CASCADE, related_name="+"
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Generated by Django 3.0.3 on 2020-05-08 16:42
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("passbook_core", "0011_auto_20200222_1822"),
|
||||||
|
("passbook_policies", "0002_auto_20200508_1230"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="policybindingmodel",
|
||||||
|
name="policies",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
related_name="_policybindingmodel_policies_+",
|
||||||
|
through="passbook_policies.PolicyBinding",
|
||||||
|
to="passbook_core.Policy",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -9,7 +9,9 @@ from passbook.lib.models import UUIDModel
|
||||||
class PolicyBindingModel(models.Model):
|
class PolicyBindingModel(models.Model):
|
||||||
"""Base Model for objects which have Policies applied to them"""
|
"""Base Model for objects which have Policies applied to them"""
|
||||||
|
|
||||||
policies = models.ManyToManyField(Policy, through="PolicyBinding", related_name="+")
|
policies = models.ManyToManyField(
|
||||||
|
Policy, through="PolicyBinding", related_name="+", blank=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
|
|
Reference in New Issue