flows: add invalidation designation, use as default logout action
This commit is contained in:
parent
9dec13c225
commit
e12780f78f
|
@ -40,7 +40,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-c-page__header-tools">
|
<div class="pf-c-page__header-tools">
|
||||||
<div class="pf-c-page__header-tools-group pf-m-icons">
|
<div class="pf-c-page__header-tools-group pf-m-icons">
|
||||||
<a href="{% url 'passbook_core:auth-logout' %}" class="pf-c-button pf-m-plain" type="button">
|
<a href="{% url 'passbook_flows:default-invalidation' %}" class="pf-c-button pf-m-plain" type="button">
|
||||||
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
|
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
"""passbook Core Account Test"""
|
|
||||||
import string
|
|
||||||
from random import SystemRandom
|
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
from django.urls import reverse
|
|
||||||
|
|
||||||
from passbook.core.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class TestAuthenticationViews(TestCase):
|
|
||||||
"""passbook Core Account Test"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super().setUp()
|
|
||||||
self.sign_up_data = {
|
|
||||||
"name": "Test",
|
|
||||||
"username": "beryjuorg",
|
|
||||||
"email": "unittest@passbook.beryju.org",
|
|
||||||
"password": "B3ryju0rg!",
|
|
||||||
"password_repeat": "B3ryju0rg!",
|
|
||||||
}
|
|
||||||
self.login_data = {
|
|
||||||
"uid_field": "unittest@example.com",
|
|
||||||
}
|
|
||||||
self.user = User.objects.create_superuser(
|
|
||||||
username="unittest user",
|
|
||||||
email="unittest@example.com",
|
|
||||||
password="".join(
|
|
||||||
SystemRandom().choice(string.ascii_uppercase + string.digits)
|
|
||||||
for _ in range(8)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_logout_view(self):
|
|
||||||
"""Test account.logout view"""
|
|
||||||
self.client.force_login(self.user)
|
|
||||||
response = self.client.get(reverse("passbook_core:auth-logout"))
|
|
||||||
self.assertEqual(response.status_code, 302)
|
|
||||||
|
|
||||||
def test_sign_up_view_auth(self):
|
|
||||||
"""Test account.sign_up view (Authenticated)"""
|
|
||||||
self.client.force_login(self.user)
|
|
||||||
response = self.client.get(reverse("passbook_core:auth-logout"))
|
|
||||||
self.assertEqual(response.status_code, 302)
|
|
|
@ -1,11 +1,9 @@
|
||||||
"""passbook URL Configuration"""
|
"""passbook URL Configuration"""
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from passbook.core.views import authentication, overview, user
|
from passbook.core.views import overview, user
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Authentication views
|
|
||||||
path("auth/logout/", authentication.LogoutView.as_view(), name="auth-logout"),
|
|
||||||
# User views
|
# User views
|
||||||
path("-/user/", user.UserSettingsView.as_view(), name="user-settings"),
|
path("-/user/", user.UserSettingsView.as_view(), name="user-settings"),
|
||||||
path("-/user/delete/", user.UserDeleteView.as_view(), name="user-delete"),
|
path("-/user/delete/", user.UserDeleteView.as_view(), name="user-delete"),
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
"""passbook core authentication views"""
|
|
||||||
from django.contrib import messages
|
|
||||||
from django.contrib.auth import logout
|
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
from django.shortcuts import redirect, reverse
|
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from django.views import View
|
|
||||||
from structlog import get_logger
|
|
||||||
|
|
||||||
LOGGER = get_logger()
|
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(LoginRequiredMixin, View):
|
|
||||||
"""Log current user out"""
|
|
||||||
|
|
||||||
def dispatch(self, request: HttpRequest) -> HttpResponse:
|
|
||||||
"""Log current user out"""
|
|
||||||
logout(request)
|
|
||||||
messages.success(request, _("You've successfully been logged out."))
|
|
||||||
return redirect(reverse("passbook_flows:default-auth"))
|
|
|
@ -8,7 +8,9 @@ from passbook.flows.models import FlowDesignation
|
||||||
from passbook.stages.identification.models import Templates, UserFields
|
from passbook.stages.identification.models import Templates, UserFields
|
||||||
|
|
||||||
|
|
||||||
def create_default_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
def create_default_authentication_flow(
|
||||||
|
apps: Apps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
):
|
||||||
Flow = apps.get_model("passbook_flows", "Flow")
|
Flow = apps.get_model("passbook_flows", "Flow")
|
||||||
FlowStageBinding = apps.get_model("passbook_flows", "FlowStageBinding")
|
FlowStageBinding = apps.get_model("passbook_flows", "FlowStageBinding")
|
||||||
PasswordStage = apps.get_model("passbook_stages_password", "PasswordStage")
|
PasswordStage = apps.get_model("passbook_stages_password", "PasswordStage")
|
||||||
|
@ -18,7 +20,11 @@ def create_default_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||||
)
|
)
|
||||||
db_alias = schema_editor.connection.alias
|
db_alias = schema_editor.connection.alias
|
||||||
|
|
||||||
if Flow.objects.using(db_alias).all().exists():
|
if (
|
||||||
|
Flow.objects.using(db_alias)
|
||||||
|
.filter(designation=FlowDesignation.AUTHENTICATION)
|
||||||
|
.exists()
|
||||||
|
):
|
||||||
# Only create default flow when none exist
|
# Only create default flow when none exist
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -53,13 +59,46 @@ def create_default_flow(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def create_default_invalidation_flow(
|
||||||
|
apps: Apps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
):
|
||||||
|
Flow = apps.get_model("passbook_flows", "Flow")
|
||||||
|
FlowStageBinding = apps.get_model("passbook_flows", "FlowStageBinding")
|
||||||
|
UserLogoutStage = apps.get_model("passbook_stages_user_logout", "UserLogoutStage")
|
||||||
|
db_alias = schema_editor.connection.alias
|
||||||
|
|
||||||
|
if (
|
||||||
|
Flow.objects.using(db_alias)
|
||||||
|
.filter(designation=FlowDesignation.INVALIDATION)
|
||||||
|
.exists()
|
||||||
|
):
|
||||||
|
# Only create default flow when none exist
|
||||||
|
return
|
||||||
|
|
||||||
|
if not UserLogoutStage.objects.using(db_alias).exists():
|
||||||
|
UserLogoutStage.objects.using(db_alias).create(name="authentication")
|
||||||
|
|
||||||
|
flow = Flow.objects.using(db_alias).create(
|
||||||
|
name="default-invalidation-flow",
|
||||||
|
slug="default-invalidation-flow",
|
||||||
|
designation=FlowDesignation.INVALIDATION,
|
||||||
|
)
|
||||||
|
FlowStageBinding.objects.using(db_alias).create(
|
||||||
|
flow=flow, stage=UserLogoutStage.objects.using(db_alias).first(), order=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("passbook_flows", "0001_initial"),
|
("passbook_flows", "0001_initial"),
|
||||||
("passbook_stages_user_login", "0001_initial"),
|
("passbook_stages_user_login", "0001_initial"),
|
||||||
|
("passbook_stages_user_logout", "0001_initial"),
|
||||||
("passbook_stages_password", "0001_initial"),
|
("passbook_stages_password", "0001_initial"),
|
||||||
("passbook_stages_identification", "0001_initial"),
|
("passbook_stages_identification", "0001_initial"),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [migrations.RunPython(create_default_flow)]
|
operations = [
|
||||||
|
migrations.RunPython(create_default_authentication_flow),
|
||||||
|
migrations.RunPython(create_default_invalidation_flow),
|
||||||
|
]
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.0.5 on 2020-05-10 23:10
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('passbook_flows', '0003_auto_20200509_1258'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='flow',
|
||||||
|
name='designation',
|
||||||
|
field=models.CharField(choices=[('authentication', 'Authentication'), ('enrollment', 'Enrollment'), ('recovery', 'Recovery'), ('password_change', 'Password Change'), ('invalidation', 'Invalidation')], max_length=100),
|
||||||
|
),
|
||||||
|
]
|
|
@ -18,6 +18,7 @@ class FlowDesignation(models.TextChoices):
|
||||||
ENROLLMENT = "enrollment"
|
ENROLLMENT = "enrollment"
|
||||||
RECOVERY = "recovery"
|
RECOVERY = "recovery"
|
||||||
PASSWORD_CHANGE = "password_change" # nosec # noqa
|
PASSWORD_CHANGE = "password_change" # nosec # noqa
|
||||||
|
INVALIDATION = "invalidation"
|
||||||
|
|
||||||
|
|
||||||
class Stage(UUIDModel):
|
class Stage(UUIDModel):
|
||||||
|
|
|
@ -15,6 +15,11 @@ urlpatterns = [
|
||||||
ToDefaultFlow.as_view(designation=FlowDesignation.AUTHENTICATION),
|
ToDefaultFlow.as_view(designation=FlowDesignation.AUTHENTICATION),
|
||||||
name="default-auth",
|
name="default-auth",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"-/default/invalidation/",
|
||||||
|
ToDefaultFlow.as_view(designation=FlowDesignation.INVALIDATION),
|
||||||
|
name="default-invalidation",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"-/default/recovery/",
|
"-/default/recovery/",
|
||||||
ToDefaultFlow.as_view(designation=FlowDesignation.RECOVERY),
|
ToDefaultFlow.as_view(designation=FlowDesignation.RECOVERY),
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
{% blocktrans with user=user %}
|
{% blocktrans with user=user %}
|
||||||
You are logged in as {{ user }}. Not you?
|
You are logged in as {{ user }}. Not you?
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
<a href="{% url 'passbook_core:auth-logout' %}">{% trans 'Logout' %}</a>
|
<a href="{% url 'passbook_flows:default-invalidation' %}">{% trans 'Logout' %}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-c-form__group pf-m-action">
|
<div class="pf-c-form__group pf-m-action">
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
{% blocktrans with user=user %}
|
{% blocktrans with user=user %}
|
||||||
You are logged in as {{ user }}. Not you?
|
You are logged in as {{ user }}. Not you?
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
<a href="{% url 'passbook_core:auth-logout' %}">{% trans 'Logout' %}</a>
|
<a href="{% url 'passbook_flows:default-invalidation' %}">{% trans 'Logout' %}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-c-form__group pf-m-action">
|
<div class="pf-c-form__group pf-m-action">
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
{% blocktrans with user=user %}
|
{% blocktrans with user=user %}
|
||||||
You are logged in as {{ user }}.
|
You are logged in as {{ user }}.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
<a href="{% url 'passbook_core:auth-logout' %}">{% trans 'Not you?' %}</a>
|
<a href="{% url 'passbook_flows:default-invalidation' %}">{% trans 'Not you?' %}</a>
|
||||||
</p>
|
</p>
|
||||||
<input class="btn btn-primary btn-block btn-lg" type="submit" value="{% trans 'Continue' %}" />
|
<input class="btn btn-primary btn-block btn-lg" type="submit" value="{% trans 'Continue' %}" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
{% blocktrans with user=user %}
|
{% blocktrans with user=user %}
|
||||||
You are logged in as {{ user }}.
|
You are logged in as {{ user }}.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
<a href="{% url 'passbook_core:auth-logout' %}">{% trans 'Not you?' %}</a>
|
<a href="{% url 'passbook_flows:default-invalidation' %}">{% trans 'Not you?' %}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-c-form__group pf-m-action">
|
<div class="pf-c-form__group pf-m-action">
|
||||||
|
|
|
@ -12,6 +12,9 @@ from passbook.root.monitoring import MetricsView
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
admin.autodiscover()
|
admin.autodiscover()
|
||||||
admin.site.login = RedirectView.as_view(pattern_name="passbook_flows:default-auth")
|
admin.site.login = RedirectView.as_view(pattern_name="passbook_flows:default-auth")
|
||||||
|
admin.site.logout = RedirectView.as_view(
|
||||||
|
pattern_name="passbook_flows:default-invalidate"
|
||||||
|
)
|
||||||
|
|
||||||
handler400 = error.BadRequestView.as_view()
|
handler400 = error.BadRequestView.as_view()
|
||||||
handler403 = error.ForbiddenView.as_view()
|
handler403 = error.ForbiddenView.as_view()
|
||||||
|
|
Reference in New Issue