diff --git a/authentik/stages/authenticator_static/apps.py b/authentik/stages/authenticator_static/apps.py index e79ea32db..1edd2b873 100644 --- a/authentik/stages/authenticator_static/apps.py +++ b/authentik/stages/authenticator_static/apps.py @@ -1,4 +1,6 @@ """Authenticator Static stage""" +from importlib import import_module + from django.apps import AppConfig @@ -8,4 +10,6 @@ class AuthentikStageAuthenticatorStaticConfig(AppConfig): name = "authentik.stages.authenticator_static" label = "authentik_stages_authenticator_static" verbose_name = "authentik Stages.Authenticator.Static" - mountpoint = "-/user/authenticator/static/" + + def ready(self): + import_module("authentik.stages.authenticator_static.signals") diff --git a/authentik/stages/authenticator_static/models.py b/authentik/stages/authenticator_static/models.py index 4f8a5d47e..d0497b65a 100644 --- a/authentik/stages/authenticator_static/models.py +++ b/authentik/stages/authenticator_static/models.py @@ -3,12 +3,11 @@ from typing import Optional, Type 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 @@ -42,15 +41,11 @@ class AuthenticatorStaticStage(ConfigurableStage, Stage): return AuthenticatorStaticStageForm @property - def ui_user_settings(self) -> Optional[Challenge]: - return Challenge( + def ui_user_settings(self) -> Optional[UserSettingSerializer]: + return UserSettingSerializer( data={ - "type": ChallengeTypes.shell.value, "title": str(self._meta.verbose_name), - "component": reverse( - "authentik_stages_authenticator_static:user-settings", - kwargs={"stage_uuid": self.stage_uuid}, - ), + "component": "ak-user-settings-authenticator-static", } ) diff --git a/authentik/stages/authenticator_static/signals.py b/authentik/stages/authenticator_static/signals.py new file mode 100644 index 000000000..f8aefba12 --- /dev/null +++ b/authentik/stages/authenticator_static/signals.py @@ -0,0 +1,17 @@ +"""totp authenticator signals""" +from django.db.models.signals import pre_delete +from django.dispatch import receiver +from django_otp.plugins.otp_static.models import StaticDevice + +from authentik.events.models import Event + + +@receiver(pre_delete, sender=StaticDevice) +# pylint: disable=unused-argument +def pre_delete_event(sender, instance: StaticDevice, **_): + # Create event with email notification + event = Event.new( + "static_authenticator_disable", message="User disabled Static OTP Tokens." + ) + event.set_user(instance.user) + event.save() diff --git a/authentik/stages/authenticator_static/templates/stages/authenticator_static/user_settings.html b/authentik/stages/authenticator_static/templates/stages/authenticator_static/user_settings.html deleted file mode 100644 index 81a40e04c..000000000 --- a/authentik/stages/authenticator_static/templates/stages/authenticator_static/user_settings.html +++ /dev/null @@ -1,31 +0,0 @@ -{% load i18n %} - -
- {% blocktrans with state=state|yesno:"Enabled,Disabled" %} - Status: {{ state }} - {% endblocktrans %} - {% if state %} - - {% else %} - - {% endif %} -
-- {% blocktrans with state=state|yesno:"Enabled,Disabled" %} - Status: {{ state }} - {% endblocktrans %} - {% if state %} - - {% else %} - - {% endif %} -
-- {% if not state %} - {% if stage.configure_flow %} - {% trans "Enable Time-based OTP" %} - {% endif %} - {% else %} - {% trans "Disable Time-based OTP" %} - {% endif %} -
-+ ${gettext("Status: Enabled")} + +
++ ${gettext("Status: Disabled")} + +
++ ${gettext("Status: Enabled")} + +
++ ${gettext("Status: Disabled")} + +
+