diff --git a/authentik/admin/templates/administration/property_mapping/test.html b/authentik/admin/templates/administration/property_mapping/test.html new file mode 100644 index 000000000..d52dcff56 --- /dev/null +++ b/authentik/admin/templates/administration/property_mapping/test.html @@ -0,0 +1,28 @@ +{% extends 'generic/form.html' %} + +{% load i18n %} + +{% block above_form %} +

{% blocktrans with property_mapping=property_mapping %}Test {{ property_mapping }}{% endblocktrans %}

+{% endblock %} + +{% block beneath_form %} +{% if result %} +
+
+ +
+
+
+ +
+
+
+{% endif %} +{% endblock %} + +{% block action %} +{% trans 'Test' %} +{% endblock %} diff --git a/authentik/admin/urls.py b/authentik/admin/urls.py index 680f30f5c..dc02b0073 100644 --- a/authentik/admin/urls.py +++ b/authentik/admin/urls.py @@ -238,11 +238,6 @@ urlpatterns = [ name="flow-delete", ), # Property Mappings - path( - "property-mappings/", - property_mappings.PropertyMappingListView.as_view(), - name="property-mappings", - ), path( "property-mappings/create/", property_mappings.PropertyMappingCreateView.as_view(), @@ -258,6 +253,11 @@ urlpatterns = [ property_mappings.PropertyMappingDeleteView.as_view(), name="property-mapping-delete", ), + path( + "property-mappings//test/", + property_mappings.PropertyMappingTestView.as_view(), + name="property-mapping-test", + ), # Users path("users/", users.UserListView.as_view(), name="users"), path("users/create/", users.UserCreateView.as_view(), name="user-create"), diff --git a/authentik/admin/views/property_mappings.py b/authentik/admin/views/property_mappings.py index 522b26622..53e18329e 100644 --- a/authentik/admin/views/property_mappings.py +++ b/authentik/admin/views/property_mappings.py @@ -1,4 +1,12 @@ """authentik PropertyMapping administration""" +from django.contrib.messages import views +from authentik.admin.forms.policies import PolicyTestForm +from django.http import HttpResponse +from json import dumps +from typing import Any +from django.db.models import QuerySet +from django.views.generic import FormView +from django.views.generic.detail import DetailView from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -20,22 +28,6 @@ from authentik.admin.views.utils import ( from authentik.core.models import PropertyMapping -class PropertyMappingListView( - LoginRequiredMixin, - PermissionListMixin, - UserPaginateListMixin, - SearchListMixin, - InheritanceListView, -): - """Show list of all property_mappings""" - - model = PropertyMapping - permission_required = "authentik_core.view_propertymapping" - template_name = "administration/property_mapping/list.html" - ordering = "name" - search_fields = ["name", "expression"] - - class PropertyMappingCreateView( SuccessMessageMixin, BackSuccessUrlMixin, @@ -81,3 +73,38 @@ class PropertyMappingDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("authentik_admin:property-mappings") success_message = _("Successfully deleted Property Mapping") + + +class PropertyMappingTestView(LoginRequiredMixin, DetailView, PermissionRequiredMixin, FormView): + """View to test property mappings""" + + model = PropertyMapping + form_class = PolicyTestForm + permission_required = "authentik_core.view_propertymapping" + template_name = "administration/property_mapping/test.html" + object = None + + def get_object(self, queryset=None) -> PropertyMapping: + return ( + PropertyMapping.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() + ) + + def get_context_data(self, **kwargs: Any) -> dict[str, Any]: + kwargs["property_mapping"] = self.get_object() + return super().get_context_data(**kwargs) + + def post(self, *args, **kwargs) -> HttpResponse: + self.object = self.get_object() + return super().post(*args, **kwargs) + + def form_valid(self, form: PolicyTestForm) -> HttpResponse: + mapping = self.get_object() + user = form.cleaned_data.get("user") + + context = self.get_context_data(form=form) + try: + result = mapping.evaluate(user, self.request, **form.cleaned_data.get("context", {})) + context["result"] = dumps(result, indent=4) + except Exception as exc: # pylint: disable=broad-except + context["result"] = str(exc) + return self.render_to_response(context) diff --git a/web/src/pages/property-mappings/PropertyMappingListPage.ts b/web/src/pages/property-mappings/PropertyMappingListPage.ts index 97cdbe2d4..d895f4594 100644 --- a/web/src/pages/property-mappings/PropertyMappingListPage.ts +++ b/web/src/pages/property-mappings/PropertyMappingListPage.ts @@ -54,13 +54,19 @@ export class PropertyMappingListPage extends TablePage { html` - Edit + ${gettext("Edit")} + +
+
  + + + ${gettext("Test")}
  - Delete + ${gettext("Delete")}