From f7aabe8ca97f80f7fd178817438938492e402c2a Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Sat, 3 Apr 2021 00:02:24 +0200 Subject: [PATCH] stages/user_delete: migrate to web Signed-off-by: Jens Langhammer --- authentik/stages/captcha/models.py | 1 - authentik/stages/user_delete/forms.py | 20 ------- authentik/stages/user_delete/models.py | 7 +-- authentik/stages/user_delete/stage.py | 10 +--- authentik/stages/user_login/tests.py | 8 --- authentik/stages/user_logout/tests.py | 6 -- authentik/stages/user_write/models.py | 1 - authentik/stages/user_write/tests.py | 6 -- .../stages/user_delete/UserDeleteStageForm.ts | 56 +++++++++++++++++++ 9 files changed, 60 insertions(+), 55 deletions(-) delete mode 100644 authentik/stages/user_delete/forms.py create mode 100644 web/src/pages/stages/user_delete/UserDeleteStageForm.ts diff --git a/authentik/stages/captcha/models.py b/authentik/stages/captcha/models.py index 61db9f375..17d4a721e 100644 --- a/authentik/stages/captcha/models.py +++ b/authentik/stages/captcha/models.py @@ -2,7 +2,6 @@ from typing import Type from django.db import models -from django.forms import ModelForm from django.utils.translation import gettext_lazy as _ from django.views import View from rest_framework.serializers import BaseSerializer diff --git a/authentik/stages/user_delete/forms.py b/authentik/stages/user_delete/forms.py deleted file mode 100644 index daf2e6fe0..000000000 --- a/authentik/stages/user_delete/forms.py +++ /dev/null @@ -1,20 +0,0 @@ -"""authentik flows delete forms""" -from django import forms - -from authentik.stages.user_delete.models import UserDeleteStage - - -class UserDeleteStageForm(forms.ModelForm): - """Form to delete/edit UserDeleteStage instances""" - - class Meta: - - model = UserDeleteStage - fields = ["name"] - widgets = { - "name": forms.TextInput(), - } - - -class UserDeleteForm(forms.Form): - """Confirmation form to ensure user knows they are deleting their profile""" diff --git a/authentik/stages/user_delete/models.py b/authentik/stages/user_delete/models.py index 7e791e8c0..f8a6cf72f 100644 --- a/authentik/stages/user_delete/models.py +++ b/authentik/stages/user_delete/models.py @@ -1,7 +1,6 @@ """delete stage models""" from typing import Type -from django.forms import ModelForm from django.utils.translation import gettext_lazy as _ from django.views import View from rest_framework.serializers import BaseSerializer @@ -26,10 +25,8 @@ class UserDeleteStage(Stage): return UserDeleteStageView @property - def form(self) -> Type[ModelForm]: - from authentik.stages.user_delete.forms import UserDeleteStageForm - - return UserDeleteStageForm + def component(self) -> str: + return "ak-stage-user-delete-form" class Meta: diff --git a/authentik/stages/user_delete/stage.py b/authentik/stages/user_delete/stage.py index 03c34afd6..15945dbe2 100644 --- a/authentik/stages/user_delete/stage.py +++ b/authentik/stages/user_delete/stage.py @@ -2,31 +2,25 @@ from django.contrib import messages from django.http import HttpRequest, HttpResponse from django.utils.translation import gettext as _ -from django.views.generic import FormView from structlog.stdlib import get_logger from authentik.core.models import User from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.stage import StageView -from authentik.stages.user_delete.forms import UserDeleteForm LOGGER = get_logger() -class UserDeleteStageView(FormView, StageView): +class UserDeleteStageView(StageView): """Finalise unenrollment flow by deleting the user object.""" - form_class = UserDeleteForm - def get(self, request: HttpRequest) -> HttpResponse: + """Delete currently pending user""" if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: message = _("No Pending User.") messages.error(request, message) LOGGER.debug(message) return self.executor.stage_invalid() - return super().get(request) - - def form_valid(self, form: UserDeleteForm) -> HttpResponse: user: User = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] user.delete() LOGGER.debug("Deleted user", user=user) diff --git a/authentik/stages/user_login/tests.py b/authentik/stages/user_login/tests.py index d05e6dc07..b2e636802 100644 --- a/authentik/stages/user_login/tests.py +++ b/authentik/stages/user_login/tests.py @@ -13,7 +13,6 @@ from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK from authentik.flows.views import SESSION_KEY_PLAN from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND -from authentik.stages.user_login.forms import UserLoginStageForm from authentik.stages.user_login.models import UserLoginStage @@ -112,10 +111,3 @@ class TestUserLoginStage(TestCase): "type": ChallengeTypes.NATIVE.value, }, ) - - def test_form(self): - """Test Form""" - data = {"name": "test", "session_duration": "seconds=0"} - self.assertEqual(UserLoginStageForm(data).is_valid(), True) - data = {"name": "test", "session_duration": "123"} - self.assertEqual(UserLoginStageForm(data).is_valid(), False) diff --git a/authentik/stages/user_logout/tests.py b/authentik/stages/user_logout/tests.py index 4923dff93..4eb464f6a 100644 --- a/authentik/stages/user_logout/tests.py +++ b/authentik/stages/user_logout/tests.py @@ -9,7 +9,6 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.views import SESSION_KEY_PLAN from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND -from authentik.stages.user_logout.forms import UserLogoutStageForm from authentik.stages.user_logout.models import UserLogoutStage @@ -51,8 +50,3 @@ class TestUserLogoutStage(TestCase): force_str(response.content), {"to": reverse("authentik_core:root-redirect"), "type": "redirect"}, ) - - def test_form(self): - """Test Form""" - data = {"name": "test"} - self.assertEqual(UserLogoutStageForm(data).is_valid(), True) diff --git a/authentik/stages/user_write/models.py b/authentik/stages/user_write/models.py index 49c2650e5..eb37a89f6 100644 --- a/authentik/stages/user_write/models.py +++ b/authentik/stages/user_write/models.py @@ -1,7 +1,6 @@ """write stage models""" from typing import Type -from django.forms import ModelForm from django.utils.translation import gettext_lazy as _ from django.views import View from rest_framework.serializers import BaseSerializer diff --git a/authentik/stages/user_write/tests.py b/authentik/stages/user_write/tests.py index bd83b2e72..00cce0ac8 100644 --- a/authentik/stages/user_write/tests.py +++ b/authentik/stages/user_write/tests.py @@ -15,7 +15,6 @@ from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK from authentik.flows.views import SESSION_KEY_PLAN from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT -from authentik.stages.user_write.forms import UserWriteStageForm from authentik.stages.user_write.models import UserWriteStage @@ -135,8 +134,3 @@ class TestUserWriteStage(TestCase): "type": ChallengeTypes.NATIVE.value, }, ) - - def test_form(self): - """Test Form""" - data = {"name": "test"} - self.assertEqual(UserWriteStageForm(data).is_valid(), True) diff --git a/web/src/pages/stages/user_delete/UserDeleteStageForm.ts b/web/src/pages/stages/user_delete/UserDeleteStageForm.ts new file mode 100644 index 000000000..32f6edc82 --- /dev/null +++ b/web/src/pages/stages/user_delete/UserDeleteStageForm.ts @@ -0,0 +1,56 @@ +import { UserDeleteStage, StagesApi } from "authentik-api"; +import { gettext } from "django"; +import { customElement, property } from "lit-element"; +import { html, TemplateResult } from "lit-html"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import { Form } from "../../../elements/forms/Form"; +import { ifDefined } from "lit-html/directives/if-defined"; +import "../../../elements/forms/HorizontalFormElement"; + +@customElement("ak-stage-user-delete-form") +export class UserLogoutStageForm extends Form { + + set stageUUID(value: string) { + new StagesApi(DEFAULT_CONFIG).stagesUserDeleteRead({ + stageUuid: value, + }).then(stage => { + this.stage = stage; + }); + } + + @property({attribute: false}) + stage?: UserDeleteStage; + + getSuccessMessage(): string { + if (this.stage) { + return gettext("Successfully updated stage."); + } else { + return gettext("Successfully created stage."); + } + } + + send = (data: UserDeleteStage): Promise => { + if (this.stage) { + return new StagesApi(DEFAULT_CONFIG).stagesUserDeleteUpdate({ + stageUuid: this.stage.pk || "", + data: data + }); + } else { + return new StagesApi(DEFAULT_CONFIG).stagesUserDeleteCreate({ + data: data + }); + } + }; + + renderForm(): TemplateResult { + return html`
+ + + +
`; + } + +}