web/admin: migrate property mapping test to web
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -1,12 +0,0 @@ | |||||||
| """authentik administration forms""" |  | ||||||
| from django import forms |  | ||||||
|  |  | ||||||
| from authentik.admin.fields import CodeMirrorWidget, YAMLField |  | ||||||
| from authentik.core.models import User |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class PolicyTestForm(forms.Form): |  | ||||||
|     """Form to test policies against user""" |  | ||||||
|  |  | ||||||
|     user = forms.ModelChoiceField(queryset=User.objects.all()) |  | ||||||
|     context = YAMLField(widget=CodeMirrorWidget(), required=False, initial=dict) |  | ||||||
| @ -1,46 +0,0 @@ | |||||||
| {% extends 'generic/form.html' %} |  | ||||||
|  |  | ||||||
| {% load i18n %} |  | ||||||
|  |  | ||||||
| {% block above_form %} |  | ||||||
| <h1>{% blocktrans with policy=policy %}Test {{ policy }}{% endblocktrans %}</h1> |  | ||||||
| {% endblock %} |  | ||||||
|  |  | ||||||
| {% block beneath_form %} |  | ||||||
| {% if result %} |  | ||||||
| <div class="pf-c-form__group "> |  | ||||||
|     <div class="pf-c-form__group-label"> |  | ||||||
|         <label class="pf-c-form__label" for="context-1"> |  | ||||||
|             <span class="pf-c-form__label-text">{% trans 'Passing' %}</span> |  | ||||||
|         </label> |  | ||||||
|     </div> |  | ||||||
|     <div class="pf-c-form__group-label"> |  | ||||||
|         <div class="c-form__horizontal-group"> |  | ||||||
|             <span class="pf-c-form__label-text">{{ result.passing|yesno:"Yes,No" }}</span> |  | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
| </div> |  | ||||||
| <div class="pf-c-form__group "> |  | ||||||
|     <div class="pf-c-form__group-label"> |  | ||||||
|         <label class="pf-c-form__label" for="context-1"> |  | ||||||
|             <span class="pf-c-form__label-text">{% trans 'Messages' %}</span> |  | ||||||
|         </label> |  | ||||||
|     </div> |  | ||||||
|     <div class="pf-c-form__group-label"> |  | ||||||
|         <div class="c-form__horizontal-group"> |  | ||||||
|             <ul> |  | ||||||
|                 {% for m in result.messages %} |  | ||||||
|                 <li><span class="pf-c-form__label-text">{{ m }}</span></li> |  | ||||||
|                 {% empty %} |  | ||||||
|                 <li><span class="pf-c-form__label-text">-</span></li> |  | ||||||
|                 {% endfor %} |  | ||||||
|             </ul> |  | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
| </div> |  | ||||||
| {% endif %} |  | ||||||
| {% endblock %} |  | ||||||
|  |  | ||||||
| {% block action %} |  | ||||||
| {% trans 'Test' %} |  | ||||||
| {% endblock %} |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| {% extends 'generic/form.html' %} |  | ||||||
|  |  | ||||||
| {% load i18n %} |  | ||||||
|  |  | ||||||
| {% block above_form %} |  | ||||||
| <h1>{% blocktrans with property_mapping=property_mapping %}Test {{ property_mapping }}{% endblocktrans %}</h1> |  | ||||||
| {% endblock %} |  | ||||||
|  |  | ||||||
| {% block beneath_form %} |  | ||||||
| {% if result %} |  | ||||||
| <div class="pf-c-form__group "> |  | ||||||
|     <div class="pf-c-form__group-label"> |  | ||||||
|         <label class="pf-c-form__label" for="context-1"> |  | ||||||
|             <span class="pf-c-form__label-text">{% trans 'Result' %}</span> |  | ||||||
|         </label> |  | ||||||
|     </div> |  | ||||||
|     <div class="pf-c-form__group-control"> |  | ||||||
|         <div class="c-form__horizontal-group"> |  | ||||||
|             <ak-codemirror mode="javascript"><textarea class="pf-c-form-control">{{ result }}</textarea></ak-codemirror> |  | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
| </div> |  | ||||||
| {% endif %} |  | ||||||
| {% endblock %} |  | ||||||
|  |  | ||||||
| {% block action %} |  | ||||||
| {% trans 'Test' %} |  | ||||||
| {% endblock %} |  | ||||||
| @ -30,11 +30,6 @@ urlpatterns = [ | |||||||
|         policies.PolicyUpdateView.as_view(), |         policies.PolicyUpdateView.as_view(), | ||||||
|         name="policy-update", |         name="policy-update", | ||||||
|     ), |     ), | ||||||
|     path( |  | ||||||
|         "policies/<uuid:pk>/test/", |  | ||||||
|         policies.PolicyTestView.as_view(), |  | ||||||
|         name="policy-test", |  | ||||||
|     ), |  | ||||||
|     # Policy bindings |     # Policy bindings | ||||||
|     path( |     path( | ||||||
|         "policies/bindings/create/", |         "policies/bindings/create/", | ||||||
| @ -108,11 +103,6 @@ urlpatterns = [ | |||||||
|         property_mappings.PropertyMappingUpdateView.as_view(), |         property_mappings.PropertyMappingUpdateView.as_view(), | ||||||
|         name="property-mapping-update", |         name="property-mapping-update", | ||||||
|     ), |     ), | ||||||
|     path( |  | ||||||
|         "property-mappings/<uuid:pk>/test/", |  | ||||||
|         property_mappings.PropertyMappingTestView.as_view(), |  | ||||||
|         name="property-mapping-test", |  | ||||||
|     ), |  | ||||||
|     # Outpost Service Connections |     # Outpost Service Connections | ||||||
|     path( |     path( | ||||||
|         "outpost_service_connections/create/", |         "outpost_service_connections/create/", | ||||||
|  | |||||||
| @ -1,22 +1,15 @@ | |||||||
| """authentik Policy administration""" | """authentik Policy administration""" | ||||||
| from typing import Any |  | ||||||
|  |  | ||||||
| from django.contrib.auth.mixins import LoginRequiredMixin | from django.contrib.auth.mixins import LoginRequiredMixin | ||||||
| from django.contrib.auth.mixins import ( | from django.contrib.auth.mixins import ( | ||||||
|     PermissionRequiredMixin as DjangoPermissionRequiredMixin, |     PermissionRequiredMixin as DjangoPermissionRequiredMixin, | ||||||
| ) | ) | ||||||
| from django.contrib.messages.views import SuccessMessageMixin | from django.contrib.messages.views import SuccessMessageMixin | ||||||
| from django.http import HttpResponse |  | ||||||
| from django.urls import reverse_lazy | from django.urls import reverse_lazy | ||||||
| from django.utils.translation import gettext as _ | from django.utils.translation import gettext as _ | ||||||
| from django.views.generic import FormView |  | ||||||
| from django.views.generic.detail import DetailView |  | ||||||
| from guardian.mixins import PermissionRequiredMixin | from guardian.mixins import PermissionRequiredMixin | ||||||
|  |  | ||||||
| from authentik.admin.forms.policies import PolicyTestForm |  | ||||||
| from authentik.admin.views.utils import InheritanceCreateView, InheritanceUpdateView | from authentik.admin.views.utils import InheritanceCreateView, InheritanceUpdateView | ||||||
| from authentik.policies.models import Policy, PolicyBinding | from authentik.policies.models import Policy | ||||||
| from authentik.policies.process import PolicyProcess, PolicyRequest |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class PolicyCreateView( | class PolicyCreateView( | ||||||
| @ -49,41 +42,3 @@ class PolicyUpdateView( | |||||||
|     template_name = "generic/update.html" |     template_name = "generic/update.html" | ||||||
|     success_url = reverse_lazy("authentik_core:if-admin") |     success_url = reverse_lazy("authentik_core:if-admin") | ||||||
|     success_message = _("Successfully updated Policy") |     success_message = _("Successfully updated Policy") | ||||||
|  |  | ||||||
|  |  | ||||||
| class PolicyTestView(LoginRequiredMixin, DetailView, PermissionRequiredMixin, FormView): |  | ||||||
|     """View to test policy(s)""" |  | ||||||
|  |  | ||||||
|     model = Policy |  | ||||||
|     form_class = PolicyTestForm |  | ||||||
|     permission_required = "authentik_policies.view_policy" |  | ||||||
|     template_name = "administration/policy/test.html" |  | ||||||
|     object = None |  | ||||||
|  |  | ||||||
|     def get_object(self, queryset=None) -> Policy: |  | ||||||
|         return ( |  | ||||||
|             Policy.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def get_context_data(self, **kwargs: Any) -> dict[str, Any]: |  | ||||||
|         kwargs["policy"] = 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: |  | ||||||
|         policy = self.get_object() |  | ||||||
|         user = form.cleaned_data.get("user") |  | ||||||
|  |  | ||||||
|         p_request = PolicyRequest(user) |  | ||||||
|         p_request.debug = True |  | ||||||
|         p_request.set_http_request(self.request) |  | ||||||
|         p_request.context = form.cleaned_data.get("context", {}) |  | ||||||
|  |  | ||||||
|         proc = PolicyProcess(PolicyBinding(policy=policy), p_request, None) |  | ||||||
|         result = proc.execute() |  | ||||||
|         context = self.get_context_data(form=form) |  | ||||||
|         context["result"] = result |  | ||||||
|         return self.render_to_response(context) |  | ||||||
|  | |||||||
| @ -1,19 +1,12 @@ | |||||||
| """authentik PropertyMapping administration""" | """authentik PropertyMapping administration""" | ||||||
| from json import dumps |  | ||||||
| from typing import Any |  | ||||||
|  |  | ||||||
| from django.contrib.auth.mixins import LoginRequiredMixin | from django.contrib.auth.mixins import LoginRequiredMixin | ||||||
| from django.contrib.auth.mixins import ( | from django.contrib.auth.mixins import ( | ||||||
|     PermissionRequiredMixin as DjangoPermissionRequiredMixin, |     PermissionRequiredMixin as DjangoPermissionRequiredMixin, | ||||||
| ) | ) | ||||||
| from django.contrib.messages.views import SuccessMessageMixin | from django.contrib.messages.views import SuccessMessageMixin | ||||||
| from django.http import HttpResponse |  | ||||||
| from django.utils.translation import gettext as _ | from django.utils.translation import gettext as _ | ||||||
| from django.views.generic import FormView |  | ||||||
| from django.views.generic.detail import DetailView |  | ||||||
| from guardian.mixins import PermissionRequiredMixin | from guardian.mixins import PermissionRequiredMixin | ||||||
|  |  | ||||||
| from authentik.admin.forms.policies import PolicyTestForm |  | ||||||
| from authentik.admin.views.utils import InheritanceCreateView, InheritanceUpdateView | from authentik.admin.views.utils import InheritanceCreateView, InheritanceUpdateView | ||||||
| from authentik.core.models import PropertyMapping | from authentik.core.models import PropertyMapping | ||||||
|  |  | ||||||
| @ -46,44 +39,3 @@ class PropertyMappingUpdateView( | |||||||
|     success_url = "/" |     success_url = "/" | ||||||
|     template_name = "generic/update.html" |     template_name = "generic/update.html" | ||||||
|     success_message = _("Successfully updated Property Mapping") |     success_message = _("Successfully updated 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) |  | ||||||
|  | |||||||
| @ -7,6 +7,8 @@ import "../../elements/buttons/ModalButton"; | |||||||
| import "../../elements/buttons/Dropdown"; | import "../../elements/buttons/Dropdown"; | ||||||
| import "../../elements/buttons/SpinnerButton"; | import "../../elements/buttons/SpinnerButton"; | ||||||
| import "../../elements/forms/DeleteForm"; | import "../../elements/forms/DeleteForm"; | ||||||
|  | import "../../elements/forms/ModalForm"; | ||||||
|  | import "./PropertyMappingTestForm"; | ||||||
| import { TableColumn } from "../../elements/table/Table"; | import { TableColumn } from "../../elements/table/Table"; | ||||||
| import { until } from "lit-html/directives/until"; | import { until } from "lit-html/directives/until"; | ||||||
| import { PAGE_SIZE } from "../../constants"; | import { PAGE_SIZE } from "../../constants"; | ||||||
| @ -64,12 +66,19 @@ export class PropertyMappingListPage extends TablePage<PropertyMapping> { | |||||||
|                 </ak-spinner-button> |                 </ak-spinner-button> | ||||||
|                 <div slot="modal"></div> |                 <div slot="modal"></div> | ||||||
|             </ak-modal-button> |             </ak-modal-button> | ||||||
|             <ak-modal-button href="${AdminURLManager.propertyMappings(`${item.pk}/test/`)}"> |             <ak-forms-modal .closeAfterSuccessfulSubmit=${false}> | ||||||
|                 <ak-spinner-button slot="trigger" class="pf-m-secondary"> |                 <span slot="submit"> | ||||||
|                     ${gettext("Test")} |                     ${gettext("Test")} | ||||||
|                 </ak-spinner-button> |                 </span> | ||||||
|                 <div slot="modal"></div> |                 <span slot="header"> | ||||||
|             </ak-modal-button> |                     ${gettext("Test Property Mapping")} | ||||||
|  |                 </span> | ||||||
|  |                 <ak-property-mapping-test-form slot="form" .mapping=${item}> | ||||||
|  |                 </ak-property-mapping-test-form> | ||||||
|  |                 <button slot="trigger" class="pf-c-button pf-m-secondary"> | ||||||
|  |                     ${gettext("Test")} | ||||||
|  |                 </button> | ||||||
|  |             </ak-forms-modal> | ||||||
|             <ak-forms-delete |             <ak-forms-delete | ||||||
|                 .obj=${item} |                 .obj=${item} | ||||||
|                 objectLabel=${gettext("Property Mapping")} |                 objectLabel=${gettext("Property Mapping")} | ||||||
|  | |||||||
							
								
								
									
										74
									
								
								web/src/pages/property-mappings/PropertyMappingTestForm.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								web/src/pages/property-mappings/PropertyMappingTestForm.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | import { CoreApi, PropertyMapping, PropertymappingsApi, PropertyMappingTestResult } 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 { until } from "lit-html/directives/until"; | ||||||
|  | import { ifDefined } from "lit-html/directives/if-defined"; | ||||||
|  | import "../../elements/forms/HorizontalFormElement"; | ||||||
|  | import "../../elements/CodeMirror"; | ||||||
|  | import { PolicyTest } from "authentik-api/src"; | ||||||
|  |  | ||||||
|  | @customElement("ak-property-mapping-test-form") | ||||||
|  | export class PolicyTestForm extends Form<PolicyTest> { | ||||||
|  |  | ||||||
|  |     @property({attribute: false}) | ||||||
|  |     mapping?: PropertyMapping; | ||||||
|  |  | ||||||
|  |     @property({ attribute: false}) | ||||||
|  |     result?: PropertyMappingTestResult; | ||||||
|  |  | ||||||
|  |     getSuccessMessage(): string { | ||||||
|  |         return gettext("Successfully sent test-request."); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     send = (data: PolicyTest): Promise<PropertyMappingTestResult> => { | ||||||
|  |         return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsAllTest({ | ||||||
|  |             pmUuid: this.mapping?.pk || "", | ||||||
|  |             data: data | ||||||
|  |         }).then(result => this.result = result); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     renderResult(): TemplateResult { | ||||||
|  |         return html`<ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Result")}> | ||||||
|  |             ${this.result?.successful ? | ||||||
|  |                 html`<ak-codemirror mode="javascript" ?readOnly=${true} value="${this.result?.result}"> | ||||||
|  |                 </ak-codemirror>`: | ||||||
|  |                 html` | ||||||
|  |                     <div class="pf-c-form__group-label"> | ||||||
|  |                         <div class="c-form__horizontal-group"> | ||||||
|  |                             <span class="pf-c-form__label-text">${this.result?.result}</span> | ||||||
|  |                         </div> | ||||||
|  |                     </div>`} | ||||||
|  |         </ak-form-element-horizontal>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     renderForm(): TemplateResult { | ||||||
|  |         return html`<form class="pf-c-form pf-m-horizontal"> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("User")} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="user"> | ||||||
|  |                 <select class="pf-c-form-control"> | ||||||
|  |                     ${until(new CoreApi(DEFAULT_CONFIG).coreUsersList({ | ||||||
|  |                         ordering: "username", | ||||||
|  |                     }).then(users => { | ||||||
|  |                         return users.results.map(user => { | ||||||
|  |                             return html`<option value=${ifDefined(user.pk)}>${user.username}</option>`; | ||||||
|  |                         }); | ||||||
|  |                     }), html``)} | ||||||
|  |                 </select> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Context")} | ||||||
|  |                 name="context"> | ||||||
|  |                 <ak-codemirror mode="yaml"> | ||||||
|  |                 </ak-codemirror> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             ${this.result ? this.renderResult(): html``} | ||||||
|  |         </form>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer