diff --git a/authentik/stages/authenticator_webauthn/models.py b/authentik/stages/authenticator_webauthn/models.py index 9b89e2acf..fdae8dd28 100644 --- a/authentik/stages/authenticator_webauthn/models.py +++ b/authentik/stages/authenticator_webauthn/models.py @@ -1,5 +1,4 @@ """WebAuthn stage""" -from authentik.core.types import UserSettingSerializer from typing import Optional, Type from django.contrib.auth import get_user_model @@ -11,6 +10,7 @@ from django.views import View from django_otp.models import Device from rest_framework.serializers import BaseSerializer +from authentik.core.types import UserSettingSerializer from authentik.flows.models import ConfigurableStage, Stage diff --git a/authentik/stages/authenticator_webauthn/urls.py b/authentik/stages/authenticator_webauthn/urls.py index 23c864c58..7c6148891 100644 --- a/authentik/stages/authenticator_webauthn/urls.py +++ b/authentik/stages/authenticator_webauthn/urls.py @@ -1,9 +1,7 @@ """WebAuthn urls""" from django.urls import path -from authentik.stages.authenticator_webauthn.views import ( - DeviceUpdateView, -) +from authentik.stages.authenticator_webauthn.views import DeviceUpdateView urlpatterns = [ path("devices//update/", DeviceUpdateView.as_view(), name="device-update"), diff --git a/authentik/stages/authenticator_webauthn/views.py b/authentik/stages/authenticator_webauthn/views.py index bfd7def9c..b4db56221 100644 --- a/authentik/stages/authenticator_webauthn/views.py +++ b/authentik/stages/authenticator_webauthn/views.py @@ -6,9 +6,8 @@ from django.utils.translation import gettext as _ from django.views.generic import UpdateView from authentik.stages.authenticator_webauthn.forms import DeviceEditForm -from authentik.stages.authenticator_webauthn.models import ( - WebAuthnDevice, -) +from authentik.stages.authenticator_webauthn.models import WebAuthnDevice + class DeviceUpdateView(SuccessMessageMixin, LoginRequiredMixin, UpdateView): """Update device""" diff --git a/authentik/stages/password/apps.py b/authentik/stages/password/apps.py index 2e933bc59..2ff268260 100644 --- a/authentik/stages/password/apps.py +++ b/authentik/stages/password/apps.py @@ -8,4 +8,3 @@ class AuthentikStagePasswordConfig(AppConfig): name = "authentik.stages.password" label = "authentik_stages_password" verbose_name = "authentik Stages.Password" - mountpoint = "-/user/password/" diff --git a/authentik/stages/password/models.py b/authentik/stages/password/models.py index 830cc17a1..a4c8619fc 100644 --- a/authentik/stages/password/models.py +++ b/authentik/stages/password/models.py @@ -4,12 +4,11 @@ from typing import Optional, Type from django.contrib.postgres.fields import ArrayField from django.db import models from django.forms import ModelForm -from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.views import View from rest_framework.serializers import BaseSerializer -from authentik.flows.challenge import Challenge, ChallengeTypes +from authentik.core.types import UserSettingSerializer from authentik.flows.models import ConfigurableStage, Stage @@ -49,17 +48,13 @@ class PasswordStage(ConfigurableStage, Stage): return PasswordStageForm @property - def ui_user_settings(self) -> Optional[Challenge]: + def ui_user_settings(self) -> Optional[UserSettingSerializer]: if not self.configure_flow: return None - return Challenge( + return UserSettingSerializer( data={ - "type": ChallengeTypes.shell.value, "title": str(self._meta.verbose_name), - "component": reverse( - "authentik_stages_password:user-settings", - kwargs={"stage_uuid": self.pk}, - ), + "component": "ak-user-settings-password", } ) diff --git a/authentik/stages/password/templates/stages/password/user-settings-card.html b/authentik/stages/password/templates/stages/password/user-settings-card.html deleted file mode 100644 index aa8782b26..000000000 --- a/authentik/stages/password/templates/stages/password/user-settings-card.html +++ /dev/null @@ -1,13 +0,0 @@ -{% load i18n %} -{% load authentik_utils %} - -
-
- {% trans 'Reset your password' %} -
- -
diff --git a/authentik/stages/password/urls.py b/authentik/stages/password/urls.py deleted file mode 100644 index f6c254e90..000000000 --- a/authentik/stages/password/urls.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Password stage urls""" -from django.urls import path - -from authentik.stages.password.views import UserSettingsCardView - -urlpatterns = [ - path( - "/change-card/", - UserSettingsCardView.as_view(), - name="user-settings", - ), -] diff --git a/authentik/stages/password/views.py b/authentik/stages/password/views.py deleted file mode 100644 index b374a87e1..000000000 --- a/authentik/stages/password/views.py +++ /dev/null @@ -1,20 +0,0 @@ -"""password stage user settings card""" -from typing import Any - -from django.contrib.auth.mixins import LoginRequiredMixin -from django.shortcuts import get_object_or_404 -from django.views.generic import TemplateView - -from authentik.stages.password.models import PasswordStage - - -class UserSettingsCardView(LoginRequiredMixin, TemplateView): - """Card shown on user settings page to allow user to change their password""" - - template_name = "stages/password/user-settings-card.html" - - def get_context_data(self, **kwargs: Any) -> dict[str, Any]: - stage = get_object_or_404(PasswordStage, pk=self.kwargs["stage_uuid"]) - kwargs = super().get_context_data(**kwargs) - kwargs["stage"] = stage - return kwargs diff --git a/web/src/pages/users/UserSettingsPage.ts b/web/src/pages/users/UserSettingsPage.ts index 2649f2225..4c2180a2d 100644 --- a/web/src/pages/users/UserSettingsPage.ts +++ b/web/src/pages/users/UserSettingsPage.ts @@ -21,6 +21,7 @@ import "../../elements/Tabs"; import "../tokens/UserTokenList"; import "../generic/SiteShell"; import "./settings/AuthenticatorWebAuthnDevices"; +import "./settings/Password"; @customElement("ak-user-settings") export class UserSettingsPage extends LitElement { @@ -34,6 +35,9 @@ export class UserSettingsPage extends LitElement { case "ak-user-settings-authenticator-webauthn": return html` `; + case "ak-user-settings-password": + return html` + `; default: return html`
diff --git a/web/src/pages/users/settings/Password.ts b/web/src/pages/users/settings/Password.ts new file mode 100644 index 000000000..ddc4f7517 --- /dev/null +++ b/web/src/pages/users/settings/Password.ts @@ -0,0 +1,35 @@ +import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; +import PFCard from "@patternfly/patternfly/components/Card/card.css"; +import PFButton from "@patternfly/patternfly/components/Button/button.css"; +import AKGlobal from "../../../authentik.css"; +import { gettext } from "django"; +import { FlowURLManager } from "../../../api/legacy"; + +@customElement("ak-user-settings-password") +export class UserSettingsPassword extends LitElement { + + @property() + stageId!: string; + + static get styles(): CSSResult[] { + return [PFBase, PFCard, PFButton, AKGlobal]; + } + + render(): TemplateResult { + // For this stage we don't need to check for a configureFlow, + // as the stage won't return any UI Elements if no configureFlow is set. + return html`
+
+ ${gettext('Change your password')} +
+ +
`; + } + +}