web/admin: migrate flows to web forms
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -24,10 +24,6 @@ export class AdminURLManager { | |||||||
|         return `/administration/outpost_service_connections/${rest}`; |         return `/administration/outpost_service_connections/${rest}`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static flows(rest: string): string { |  | ||||||
|         return `/administration/flows/${rest}`; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     static stages(rest: string): string { |     static stages(rest: string): string { | ||||||
|         return `/administration/stages/${rest}`; |         return `/administration/stages/${rest}`; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ export class ApplicationForm extends Form<Application> { | |||||||
|             ${Array.from(m).map(([group, providers]) => { |             ${Array.from(m).map(([group, providers]) => { | ||||||
|                 return html`<optgroup label=${group}> |                 return html`<optgroup label=${group}> | ||||||
|                     ${providers.map(p => { |                     ${providers.map(p => { | ||||||
|                         const selected = (this.application?.provider?.pk === p.pk) || (this.provider === p.pk) |                         const selected = (this.application?.provider?.pk === p.pk) || (this.provider === p.pk); | ||||||
|                         return html`<option ?selected=${selected} value=${ifDefined(p.pk)}>${p.name}</option>`; |                         return html`<option ?selected=${selected} value=${ifDefined(p.pk)}>${p.name}</option>`; | ||||||
|                     })} |                     })} | ||||||
|                 </optgroup>`; |                 </optgroup>`; | ||||||
|  | |||||||
							
								
								
									
										115
									
								
								web/src/pages/flows/FlowForm.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								web/src/pages/flows/FlowForm.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,115 @@ | |||||||
|  | import { Flow, FlowDesignationEnum, FlowsApi } 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"; | ||||||
|  |  | ||||||
|  | @customElement("ak-flow-form") | ||||||
|  | export class FlowForm extends Form<Flow> { | ||||||
|  |  | ||||||
|  |     @property({attribute: false}) | ||||||
|  |     flow?: Flow; | ||||||
|  |  | ||||||
|  |     getSuccessMessage(): string { | ||||||
|  |         if (this.flow) { | ||||||
|  |             return gettext("Successfully updated flow."); | ||||||
|  |         } else { | ||||||
|  |             return gettext("Successfully created flow."); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     send = (data: Flow): Promise<void | Flow> => { | ||||||
|  |         let writeOp: Promise<Flow>; | ||||||
|  |         if (this.flow) { | ||||||
|  |             writeOp = new FlowsApi(DEFAULT_CONFIG).flowsInstancesUpdate({ | ||||||
|  |                 slug: this.flow.slug, | ||||||
|  |                 data: data | ||||||
|  |             }); | ||||||
|  |         } else { | ||||||
|  |             writeOp = new FlowsApi(DEFAULT_CONFIG).flowsInstancesCreate({ | ||||||
|  |                 data: data | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         const background = this.getFormFile(); | ||||||
|  |         if (background) { | ||||||
|  |             return writeOp.then(flow => { | ||||||
|  |                 return new FlowsApi(DEFAULT_CONFIG).flowsInstancesSetBackground({ | ||||||
|  |                     slug: flow.slug, | ||||||
|  |                     file: background | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         return writeOp; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     renderDesignations(): TemplateResult { | ||||||
|  |         return html` | ||||||
|  |             <option value=${FlowDesignationEnum.Authentication} ?selected=${this.flow?.designation === FlowDesignationEnum.Authentication}> | ||||||
|  |                 ${gettext("Authentication")} | ||||||
|  |             </option> | ||||||
|  |             <option value=${FlowDesignationEnum.Authorization} ?selected=${this.flow?.designation === FlowDesignationEnum.Authorization}> | ||||||
|  |                 ${gettext("Authorization")} | ||||||
|  |             </option> | ||||||
|  |             <option value=${FlowDesignationEnum.Enrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Enrollment}> | ||||||
|  |                 ${gettext("Enrollment")} | ||||||
|  |             </option> | ||||||
|  |             <option value=${FlowDesignationEnum.Invalidation} ?selected=${this.flow?.designation === FlowDesignationEnum.Invalidation}> | ||||||
|  |                 ${gettext("Invalidation")} | ||||||
|  |             </option> | ||||||
|  |             <option value=${FlowDesignationEnum.Recovery} ?selected=${this.flow?.designation === FlowDesignationEnum.Recovery}> | ||||||
|  |                 ${gettext("Recovery")} | ||||||
|  |             </option> | ||||||
|  |             <option value=${FlowDesignationEnum.StageConfiguration} ?selected=${this.flow?.designation === FlowDesignationEnum.StageConfiguration}> | ||||||
|  |                 ${gettext("Stage Configuration")} | ||||||
|  |             </option> | ||||||
|  |             <option value=${FlowDesignationEnum.Unenrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Unenrollment}> | ||||||
|  |                 ${gettext("Unenrollment")} | ||||||
|  |             </option> | ||||||
|  |         `; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     renderForm(): TemplateResult { | ||||||
|  |         return html`<form class="pf-c-form pf-m-horizontal"> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Name")} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="name"> | ||||||
|  |                 <input type="text" value="${ifDefined(this.flow?.name)}" class="pf-c-form-control" required> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Title")} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="title"> | ||||||
|  |                 <input type="text" value="${ifDefined(this.flow?.title)}" class="pf-c-form-control" required> | ||||||
|  |                 <p class="pf-c-form__helper-text">${gettext("Shown as the Title in Flow pages.")}</p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Name")} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="slug"> | ||||||
|  |                 <input type="text" value="${ifDefined(this.flow?.slug)}" class="pf-c-form-control" required> | ||||||
|  |                 <p class="pf-c-form__helper-text">${gettext("Visible in the URL.")}</p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Designation")} | ||||||
|  |                 ?required=${true} | ||||||
|  |                 name="designation"> | ||||||
|  |                 <select class="pf-c-form-control"> | ||||||
|  |                     <option value="" ?selected=${this.flow?.designation === undefined}>---------</option> | ||||||
|  |                     ${this.renderDesignations()} | ||||||
|  |                 </select> | ||||||
|  |                 <p class="pf-c-form__helper-text">${gettext("Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.")}</p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Background")} | ||||||
|  |                 name="background"> | ||||||
|  |                 <input type="file" value="${ifDefined(this.flow?.background)}" class="pf-c-form-control"> | ||||||
|  |                 <p class="pf-c-form__helper-text">${gettext("Background shown during execution.")}</p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |         </form>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								web/src/pages/flows/FlowImportForm.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								web/src/pages/flows/FlowImportForm.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | import { Flow, FlowsApi } from "authentik-api"; | ||||||
|  | import { gettext } from "django"; | ||||||
|  | import { customElement } from "lit-element"; | ||||||
|  | import { html, TemplateResult } from "lit-html"; | ||||||
|  | import { DEFAULT_CONFIG } from "../../api/Config"; | ||||||
|  | import { Form } from "../../elements/forms/Form"; | ||||||
|  | import "../../elements/forms/HorizontalFormElement"; | ||||||
|  |  | ||||||
|  | @customElement("ak-flow-import-form") | ||||||
|  | export class FlowImportForm extends Form<Flow> { | ||||||
|  |  | ||||||
|  |     getSuccessMessage(): string { | ||||||
|  |         return gettext("Successfully imported flow."); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // eslint-disable-next-line | ||||||
|  |     send = (data: Flow): Promise<void> => { | ||||||
|  |         const file = this.getFormFile(); | ||||||
|  |         if (!file) { | ||||||
|  |             throw new Error("No form data"); | ||||||
|  |         } | ||||||
|  |         return new FlowsApi(DEFAULT_CONFIG).flowsInstancesImportFlow({ | ||||||
|  |             file: file | ||||||
|  |         }); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     renderForm(): TemplateResult { | ||||||
|  |         return html`<form class="pf-c-form pf-m-horizontal"> | ||||||
|  |             <ak-form-element-horizontal | ||||||
|  |                 label=${gettext("Flow")} | ||||||
|  |                 name="flow"> | ||||||
|  |                 <input type="file" value="" class="pf-c-form-control"> | ||||||
|  |                 <p class="pf-c-form__helper-text">${gettext("Background shown during execution.")}</p> | ||||||
|  |             </ak-form-element-horizontal> | ||||||
|  |         </form>`; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -6,11 +6,13 @@ 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 "./FlowForm"; | ||||||
|  | import "./FlowImportForm"; | ||||||
| import { TableColumn } from "../../elements/table/Table"; | import { TableColumn } from "../../elements/table/Table"; | ||||||
| import { PAGE_SIZE } from "../../constants"; | import { PAGE_SIZE } from "../../constants"; | ||||||
| import { Flow, FlowsApi } from "authentik-api"; | import { Flow, FlowsApi } from "authentik-api"; | ||||||
| import { DEFAULT_CONFIG } from "../../api/Config"; | import { DEFAULT_CONFIG } from "../../api/Config"; | ||||||
| import { AdminURLManager } from "../../api/legacy"; |  | ||||||
|  |  | ||||||
| @customElement("ak-flow-list") | @customElement("ak-flow-list") | ||||||
| export class FlowListPage extends TablePage<Flow> { | export class FlowListPage extends TablePage<Flow> { | ||||||
| @ -60,48 +62,76 @@ export class FlowListPage extends TablePage<Flow> { | |||||||
|             html`${Array.from(item.stages || []).length}`, |             html`${Array.from(item.stages || []).length}`, | ||||||
|             html`${Array.from(item.policies || []).length}`, |             html`${Array.from(item.policies || []).length}`, | ||||||
|             html` |             html` | ||||||
|             <ak-modal-button href="${AdminURLManager.flows(`${item.pk}/update/`)}"> |             <ak-forms-modal> | ||||||
|                 <ak-spinner-button slot="trigger" class="pf-m-secondary"> |                 <span slot="submit"> | ||||||
|  |                     ${gettext("Update")} | ||||||
|  |                 </span> | ||||||
|  |                 <span slot="header"> | ||||||
|  |                     ${gettext("Update Flow")} | ||||||
|  |                 </span> | ||||||
|  |                 <ak-flow-form slot="form" .flow=${item}> | ||||||
|  |                 </ak-flow-form> | ||||||
|  |                 <button slot="trigger" class="pf-c-button pf-m-secondary"> | ||||||
|                     ${gettext("Edit")} |                     ${gettext("Edit")} | ||||||
|                 </ak-spinner-button> |                 </button> | ||||||
|                 <div slot="modal"></div> |             </ak-forms-modal> | ||||||
|             </ak-modal-button> |  | ||||||
|             <ak-forms-delete |             <ak-forms-delete | ||||||
|                 .obj=${item} |                 .obj=${item} | ||||||
|                 objectLabel=${gettext("Flow")} |                 objectLabel=${gettext("Flow")} | ||||||
|                 .delete=${() => { |                 .delete=${() => { | ||||||
|                     return new FlowsApi(DEFAULT_CONFIG).flowsInstancesDelete({ |                     return new FlowsApi(DEFAULT_CONFIG).flowsInstancesDelete({ | ||||||
|                         slug: item.slug || "" |                         slug: item.slug | ||||||
|                     }); |                     }); | ||||||
|                 }}> |                 }}> | ||||||
|                 <button slot="trigger" class="pf-c-button pf-m-danger"> |                 <button slot="trigger" class="pf-c-button pf-m-danger"> | ||||||
|                     ${gettext("Delete")} |                     ${gettext("Delete")} | ||||||
|                 </button> |                 </button> | ||||||
|             </ak-forms-delete> |             </ak-forms-delete> | ||||||
|             <a class="pf-c-button pf-m-secondary ak-root-link" href="${AdminURLManager.flows(`${item.pk}/execute/?next=/%23${window.location.href}`)}"> |             <button | ||||||
|  |                 class="pf-c-button pf-m-secondary ak-root-link" | ||||||
|  |                 @click=${() => { | ||||||
|  |                     new FlowsApi(DEFAULT_CONFIG).flowsInstancesExecute({ | ||||||
|  |                         slug: item.slug | ||||||
|  |                     }).then(link => { | ||||||
|  |                         window.location.assign(`${link.link}?next=/%23${window.location.href}`); | ||||||
|  |                     }); | ||||||
|  |                 }}> | ||||||
|                 ${gettext("Execute")} |                 ${gettext("Execute")} | ||||||
|             </a> |             </button> | ||||||
|             <a class="pf-c-button pf-m-secondary ak-root-link" href="${`${DEFAULT_CONFIG.basePath}/flows/instances/${item.slug}/export/`}"> |             <a class="pf-c-button pf-m-secondary ak-root-link" href="${`${DEFAULT_CONFIG.basePath}/flows/instances/${item.slug}/export/`}"> | ||||||
|                 ${gettext("Export")} |                 ${gettext("Export")} | ||||||
|             </a> |             </a>`, | ||||||
|             `, |  | ||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     renderToolbar(): TemplateResult { |     renderToolbar(): TemplateResult { | ||||||
|         return html` |         return html` | ||||||
|         <ak-modal-button href=${AdminURLManager.flows("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 Flow")} | ||||||
|         <ak-modal-button href=${AdminURLManager.flows("import/")}> |             </span> | ||||||
|             <ak-spinner-button slot="trigger" class="pf-m-secondary"> |             <ak-flow-form slot="form"> | ||||||
|  |             </ak-flow-form> | ||||||
|  |             <button slot="trigger" class="pf-c-button pf-m-primary"> | ||||||
|  |                 ${gettext("Create")} | ||||||
|  |             </button> | ||||||
|  |         </ak-forms-modal> | ||||||
|  |         <ak-forms-modal> | ||||||
|  |             <span slot="submit"> | ||||||
|                 ${gettext("Import")} |                 ${gettext("Import")} | ||||||
|             </ak-spinner-button> |             </span> | ||||||
|             <div slot="modal"></div> |             <span slot="header"> | ||||||
|         </ak-modal-button> |                 ${gettext("Import Flow")} | ||||||
|  |             </span> | ||||||
|  |             <ak-flow-import-form slot="form"> | ||||||
|  |             </ak-flow-import-form> | ||||||
|  |             <button slot="trigger" class="pf-c-button pf-m-primary"> | ||||||
|  |                 ${gettext("Import")} | ||||||
|  |             </button> | ||||||
|  |         </ak-forms-modal> | ||||||
|         ${super.renderToolbar()} |         ${super.renderToolbar()} | ||||||
|         `; |         `; | ||||||
|     } |     } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer