web/admin: migrate invitations to web
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -10,7 +10,6 @@ from authentik.admin.views import ( | |||||||
|     sources, |     sources, | ||||||
|     stages, |     stages, | ||||||
|     stages_bindings, |     stages_bindings, | ||||||
|     stages_invitations, |  | ||||||
|     stages_prompts, |     stages_prompts, | ||||||
| ) | ) | ||||||
| from authentik.providers.saml.views.metadata import MetadataImportView | from authentik.providers.saml.views.metadata import MetadataImportView | ||||||
| @ -86,12 +85,6 @@ urlpatterns = [ | |||||||
|         stages_prompts.PromptUpdateView.as_view(), |         stages_prompts.PromptUpdateView.as_view(), | ||||||
|         name="stage-prompt-update", |         name="stage-prompt-update", | ||||||
|     ), |     ), | ||||||
|     # Stage Invitations |  | ||||||
|     path( |  | ||||||
|         "stages/invitations/create/", |  | ||||||
|         stages_invitations.InvitationCreateView.as_view(), |  | ||||||
|         name="stage-invitation-create", |  | ||||||
|     ), |  | ||||||
|     # Property Mappings |     # Property Mappings | ||||||
|     path( |     path( | ||||||
|         "property-mappings/create/", |         "property-mappings/create/", | ||||||
|  | |||||||
| @ -1,36 +0,0 @@ | |||||||
| """authentik Invitation administration""" |  | ||||||
| from django.contrib.auth.mixins import LoginRequiredMixin |  | ||||||
| from django.contrib.auth.mixins import ( |  | ||||||
|     PermissionRequiredMixin as DjangoPermissionRequiredMixin, |  | ||||||
| ) |  | ||||||
| from django.contrib.messages.views import SuccessMessageMixin |  | ||||||
| from django.http import HttpResponseRedirect |  | ||||||
| from django.urls import reverse_lazy |  | ||||||
| from django.utils.translation import gettext as _ |  | ||||||
|  |  | ||||||
| from authentik.lib.views import CreateAssignPermView |  | ||||||
| from authentik.stages.invitation.forms import InvitationForm |  | ||||||
| from authentik.stages.invitation.models import Invitation |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class InvitationCreateView( |  | ||||||
|     SuccessMessageMixin, |  | ||||||
|     LoginRequiredMixin, |  | ||||||
|     DjangoPermissionRequiredMixin, |  | ||||||
|     CreateAssignPermView, |  | ||||||
| ): |  | ||||||
|     """Create new Invitation""" |  | ||||||
|  |  | ||||||
|     model = Invitation |  | ||||||
|     form_class = InvitationForm |  | ||||||
|     permission_required = "authentik_stages_invitation.add_invitation" |  | ||||||
|  |  | ||||||
|     template_name = "generic/create.html" |  | ||||||
|     success_url = reverse_lazy("authentik_core:if-admin") |  | ||||||
|     success_message = _("Successfully created Invitation") |  | ||||||
|  |  | ||||||
|     def form_valid(self, form): |  | ||||||
|         obj = form.save(commit=False) |  | ||||||
|         obj.created_by = self.request.user |  | ||||||
|         obj.save() |  | ||||||
|         return HttpResponseRedirect(self.success_url) |  | ||||||
| @ -49,5 +49,4 @@ class InvitationViewSet(ModelViewSet): | |||||||
|     filterset_fields = ["created_by__username", "expires"] |     filterset_fields = ["created_by__username", "expires"] | ||||||
|  |  | ||||||
|     def perform_create(self, serializer: InvitationSerializer): |     def perform_create(self, serializer: InvitationSerializer): | ||||||
|         serializer.instance.created_by = self.request.user |         serializer.save(created_by=self.request.user) | ||||||
|         return super().perform_create(serializer) |  | ||||||
|  | |||||||
| @ -1,8 +1,7 @@ | |||||||
| """authentik flows invitation forms""" | """authentik flows invitation forms""" | ||||||
| from django import forms | from django import forms | ||||||
|  |  | ||||||
| from authentik.admin.fields import CodeMirrorWidget, YAMLField | from authentik.stages.invitation.models import InvitationStage | ||||||
| from authentik.stages.invitation.models import Invitation, InvitationStage |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class InvitationStageForm(forms.ModelForm): | class InvitationStageForm(forms.ModelForm): | ||||||
| @ -15,14 +14,3 @@ class InvitationStageForm(forms.ModelForm): | |||||||
|         widgets = { |         widgets = { | ||||||
|             "name": forms.TextInput(), |             "name": forms.TextInput(), | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
| class InvitationForm(forms.ModelForm): |  | ||||||
|     """InvitationForm""" |  | ||||||
|  |  | ||||||
|     class Meta: |  | ||||||
|  |  | ||||||
|         model = Invitation |  | ||||||
|         fields = ["expires", "fixed_data"] |  | ||||||
|         widgets = {"fixed_data": CodeMirrorWidget()} |  | ||||||
|         field_classes = {"fixed_data": YAMLField} |  | ||||||
|  | |||||||
| @ -28,10 +28,6 @@ export class AdminURLManager { | |||||||
|         return `/administration/stages_prompts/${rest}`; |         return `/administration/stages_prompts/${rest}`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static stageInvitations(rest: string): string { |  | ||||||
|         return `/administration/stages/invitations/${rest}`; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     static stageBindings(rest: string): string { |     static stageBindings(rest: string): string { | ||||||
|         return `/administration/stages/bindings/${rest}`; |         return `/administration/stages/bindings/${rest}`; | ||||||
|     } |     } | ||||||
| @ -52,10 +48,6 @@ export class UserURLManager { | |||||||
|         return `/-/user/tokens/${rest}`; |         return `/-/user/tokens/${rest}`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static authenticatorWebauthn(rest: string): string { |  | ||||||
|         return `/-/user/authenticator/webauthn/${rest}`; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| export class AppURLManager { | export class AppURLManager { | ||||||
|  | |||||||
| @ -84,6 +84,8 @@ export class Form<T> extends LitElement { | |||||||
|             const values = form._serializeElementValues(element); |             const values = form._serializeElementValues(element); | ||||||
|             if (element.tagName.toLowerCase() === "select" && "multiple" in element.attributes) { |             if (element.tagName.toLowerCase() === "select" && "multiple" in element.attributes) { | ||||||
|                 json[element.name] = values; |                 json[element.name] = values; | ||||||
|  |             } else if (element.tagName.toLowerCase() === "input" && element.type === "date") { | ||||||
|  |                 json[element.name] = element.valueAsDate; | ||||||
|             } else { |             } else { | ||||||
|                 for (let v = 0; v < values.length; v++) { |                 for (let v = 0; v < values.length; v++) { | ||||||
|                     form._addSerializedElement(json, element.name, values[v]); |                     form._addSerializedElement(json, element.name, values[v]); | ||||||
|  | |||||||
							
								
								
									
										57
									
								
								web/src/pages/stages/InvitationForm.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								web/src/pages/stages/InvitationForm.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | |||||||
|  | import { Invitation, StagesApi } 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 { ifDefined } from "lit-html/directives/if-defined"; | ||||||
|  | import "../../elements/forms/HorizontalFormElement"; | ||||||
|  | import "../../elements/CodeMirror"; | ||||||
|  | import YAML from "yaml"; | ||||||
|  |  | ||||||
|  | @customElement("ak-stage-invitation-form") | ||||||
|  | export class InvitationForm extends Form<Invitation> { | ||||||
|  |  | ||||||
|  |     @property({attribute: false}) | ||||||
|  |     invitation?: Invitation; | ||||||
|  |  | ||||||
|  |     getSuccessMessage(): string { | ||||||
|  |         if (this.invitation) { | ||||||
|  |             return gettext("Successfully updated invitation."); | ||||||
|  |         } else { | ||||||
|  |             return gettext("Successfully created invitation."); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     send = (data: Invitation): Promise<Invitation> => { | ||||||
|  |         if (this.invitation) { | ||||||
|  |             return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsUpdate({ | ||||||
|  |                 inviteUuid: this.invitation.pk || "", | ||||||
|  |                 data: data | ||||||
|  |             }); | ||||||
|  |         } else { | ||||||
|  |             return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsCreate({ | ||||||
|  |                 data: data | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     renderForm(): TemplateResult { | ||||||
|  |         return html`<form class="pf-c-form pf-m-horizontal"> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Expires")} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="expires"> | ||||||
|  |                 <input type="date" value="${ifDefined(this.invitation?.expires)}" class="pf-c-form-control" required> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Attributes")} | ||||||
|  |                 name="fixedData"> | ||||||
|  |                 <ak-codemirror mode="yaml" value="${YAML.stringify(this.invitation?.fixedData)}"> | ||||||
|  |                 </ak-codemirror> | ||||||
|  |                 <p class="pf-c-form__helper-text">${gettext("Optional data which is loaded into the flow's 'prompt_data' context variable.")}</p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |         </form>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -6,11 +6,12 @@ import { TablePage } from "../../elements/table/TablePage"; | |||||||
| import "../../elements/buttons/ModalButton"; | import "../../elements/buttons/ModalButton"; | ||||||
| import "../../elements/buttons/SpinnerButton"; | import "../../elements/buttons/SpinnerButton"; | ||||||
| import "../../elements/forms/DeleteForm"; | import "../../elements/forms/DeleteForm"; | ||||||
|  | import "../../elements/forms/ModalForm"; | ||||||
|  | import "./InvitationForm"; | ||||||
| import { TableColumn } from "../../elements/table/Table"; | import { TableColumn } from "../../elements/table/Table"; | ||||||
| import { PAGE_SIZE } from "../../constants"; | import { PAGE_SIZE } from "../../constants"; | ||||||
| import { Invitation, StagesApi } from "authentik-api"; | import { Invitation, StagesApi } from "authentik-api"; | ||||||
| import { DEFAULT_CONFIG } from "../../api/Config"; | import { DEFAULT_CONFIG } from "../../api/Config"; | ||||||
| import { AdminURLManager } from "../../api/legacy"; |  | ||||||
|  |  | ||||||
| @customElement("ak-stage-invitation-list") | @customElement("ak-stage-invitation-list") | ||||||
| export class InvitationListPage extends TablePage<Invitation> { | export class InvitationListPage extends TablePage<Invitation> { | ||||||
| @ -71,12 +72,19 @@ export class InvitationListPage extends TablePage<Invitation> { | |||||||
|  |  | ||||||
|     renderToolbar(): TemplateResult { |     renderToolbar(): TemplateResult { | ||||||
|         return html` |         return html` | ||||||
|         <ak-modal-button href=${AdminURLManager.stageInvitations("create/")}> |         <ak-forms-modal> | ||||||
|             <ak-spinner-button slot="trigger" class="pf-m-primary"> |             <span slot="submit"> | ||||||
|                 ${gettext("Create")} |                 ${gettext("Create")} | ||||||
|             </ak-spinner-button> |             </span> | ||||||
|             <div slot="modal"></div> |             <span slot="header"> | ||||||
|         </ak-modal-button> |                 ${gettext("Create Invitation")} | ||||||
|  |             </span> | ||||||
|  |             <ak-stage-invitation-form slot="form"> | ||||||
|  |             </ak-stage-invitation-form> | ||||||
|  |             <button slot="trigger" class="pf-c-button pf-m-primary"> | ||||||
|  |                 ${gettext("Create")} | ||||||
|  |             </button> | ||||||
|  |         </ak-forms-modal> | ||||||
|         ${super.renderToolbar()} |         ${super.renderToolbar()} | ||||||
|         `; |         `; | ||||||
|     } |     } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer