diff --git a/authentik/stages/authenticator_webauthn/forms.py b/authentik/stages/authenticator_webauthn/forms.py
index 78368c190..881bf54d7 100644
--- a/authentik/stages/authenticator_webauthn/forms.py
+++ b/authentik/stages/authenticator_webauthn/forms.py
@@ -1,7 +1,10 @@
"""Webauthn stage forms"""
from django import forms
-from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage
+from authentik.stages.authenticator_webauthn.models import (
+ AuthenticateWebAuthnStage,
+ WebAuthnDevice,
+)
class AuthenticateWebAuthnStageForm(forms.ModelForm):
@@ -15,3 +18,16 @@ class AuthenticateWebAuthnStageForm(forms.ModelForm):
widgets = {
"name": forms.TextInput(),
}
+
+
+class DeviceEditForm(forms.ModelForm):
+ """Form to edit webauthn device"""
+
+ class Meta:
+
+ model = WebAuthnDevice
+ fields = ["name"]
+
+ widgets = {
+ "name": forms.TextInput(),
+ }
diff --git a/authentik/stages/authenticator_webauthn/models.py b/authentik/stages/authenticator_webauthn/models.py
index f84c0b799..cc63da205 100644
--- a/authentik/stages/authenticator_webauthn/models.py
+++ b/authentik/stages/authenticator_webauthn/models.py
@@ -79,3 +79,8 @@ class WebAuthnDevice(Device):
def __str__(self):
return self.name or str(self.user)
+
+ class Meta:
+
+ verbose_name = _("WebAuthn Device")
+ verbose_name_plural = _("WebAuthn Devices")
diff --git a/authentik/stages/authenticator_webauthn/templates/stages/authenticator_webauthn/user_settings.html b/authentik/stages/authenticator_webauthn/templates/stages/authenticator_webauthn/user_settings.html
index 89a26a8a3..38daec51a 100644
--- a/authentik/stages/authenticator_webauthn/templates/stages/authenticator_webauthn/user_settings.html
+++ b/authentik/stages/authenticator_webauthn/templates/stages/authenticator_webauthn/user_settings.html
@@ -17,6 +17,20 @@
Created {{ created_on }}
{% endblocktrans %}
+
+
+
+ {% trans 'Update' %}
+
+
+
+
+
+ {% trans 'Delete' %}
+
+
+
+
diff --git a/authentik/stages/authenticator_webauthn/urls.py b/authentik/stages/authenticator_webauthn/urls.py
index d163dcc39..bcd10e496 100644
--- a/authentik/stages/authenticator_webauthn/urls.py
+++ b/authentik/stages/authenticator_webauthn/urls.py
@@ -1,10 +1,16 @@
"""WebAuthn urls"""
from django.urls import path
-from authentik.stages.authenticator_webauthn.views import UserSettingsView
+from authentik.stages.authenticator_webauthn.views import (
+ DeviceDeleteView,
+ DeviceUpdateView,
+ UserSettingsView,
+)
urlpatterns = [
path(
"/settings/", UserSettingsView.as_view(), name="user-settings"
),
+ path("devices//delete/", DeviceDeleteView.as_view(), name="device-delete"),
+ 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 6881fb571..c8954f586 100644
--- a/authentik/stages/authenticator_webauthn/views.py
+++ b/authentik/stages/authenticator_webauthn/views.py
@@ -1,8 +1,13 @@
"""webauthn views"""
from django.contrib.auth.mixins import LoginRequiredMixin
+from django.contrib.messages.views import SuccessMessageMixin
+from django.http.response import Http404
from django.shortcuts import get_object_or_404
-from django.views.generic import TemplateView
+from django.utils.translation import gettext as _
+from django.views.generic import TemplateView, UpdateView
+from authentik.admin.views.utils import DeleteMessageView
+from authentik.stages.authenticator_webauthn.forms import DeviceEditForm
from authentik.stages.authenticator_webauthn.models import (
AuthenticateWebAuthnStage,
WebAuthnDevice,
@@ -22,3 +27,34 @@ class UserSettingsView(LoginRequiredMixin, TemplateView):
)
kwargs["stage"] = stage
return kwargs
+
+
+class DeviceUpdateView(SuccessMessageMixin, LoginRequiredMixin, UpdateView):
+ """Update device"""
+
+ model = WebAuthnDevice
+ form_class = DeviceEditForm
+ template_name = "generic/update.html"
+ success_url = "/"
+ success_message = _("Successfully updated Device")
+
+ def get_object(self) -> WebAuthnDevice:
+ device: WebAuthnDevice = super().get_object()
+ if device.user != self.request.user:
+ raise Http404
+ return device
+
+
+class DeviceDeleteView(LoginRequiredMixin, DeleteMessageView):
+ """Delete device"""
+
+ model = WebAuthnDevice
+ template_name = "generic/delete.html"
+ success_url = "/"
+ success_message = _("Successfully deleted Device")
+
+ def get_object(self) -> WebAuthnDevice:
+ device: WebAuthnDevice = super().get_object()
+ if device.user != self.request.user:
+ raise Http404
+ return device