Files
authentik/web/src/admin/tenants/TenantForm.ts
Ken Sternberg b181c551a5 web: expressing success (#7830)
* web: expressing success

Ever see an idiom that just, I dunno, *annoyed* you?

Automated tools for the win.

* web: repetition, repetition, repetition!  [throws chair]

* web: giving the de-duplication treatment to policy mappings.

* Created a BaseStageForm with success message and canonical primary key type for for Providers, Sources, and Stages.
2023-12-13 16:13:28 +01:00

283 lines
13 KiB
TypeScript

import "@goauthentik/admin/common/ak-crypto-certificate-search";
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect";
import { DefaultTenant } from "@goauthentik/elements/sidebar/SidebarBrand";
import YAML from "yaml";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { CoreApi, FlowsInstancesListDesignationEnum, Tenant } from "@goauthentik/api";
@customElement("ak-tenant-form")
export class TenantForm extends ModelForm<Tenant, string> {
loadInstance(pk: string): Promise<Tenant> {
return new CoreApi(DEFAULT_CONFIG).coreTenantsRetrieve({
tenantUuid: pk,
});
}
getSuccessMessage(): string {
return this.instance
? msg("Successfully updated tenant.")
: msg("Successfully created tenant.");
}
async send(data: Tenant): Promise<Tenant> {
if (this.instance?.tenantUuid) {
return new CoreApi(DEFAULT_CONFIG).coreTenantsUpdate({
tenantUuid: this.instance.tenantUuid,
tenantRequest: data,
});
} else {
return new CoreApi(DEFAULT_CONFIG).coreTenantsCreate({
tenantRequest: data,
});
}
}
renderForm(): TemplateResult {
return html` <ak-form-element-horizontal
label=${msg("Domain")}
?required=${true}
name="domain"
>
<input
type="text"
value="${first(this.instance?.domain, window.location.host)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${msg(
"Matching is done based on domain suffix, so if you enter domain.tld, foo.domain.tld will still match.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="_default">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${first(this.instance?._default, false)}
/>
<span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon">
<i class="fas fa-check" aria-hidden="true"></i>
</span>
</span>
<span class="pf-c-switch__label">${msg("Default")}</span>
</label>
<p class="pf-c-form__helper-text">
${msg("Use this tenant for each domain that doesn't have a dedicated tenant.")}
</p>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}>
<span slot="header"> ${msg("Branding settings")} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${msg("Title")}
?required=${true}
name="brandingTitle"
>
<input
type="text"
value="${first(
this.instance?.brandingTitle,
DefaultTenant.brandingTitle,
)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${msg("Branding shown in page title and several other places.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Logo")}
?required=${true}
name="brandingLogo"
>
<input
type="text"
value="${first(
this.instance?.brandingLogo,
DefaultTenant.brandingLogo,
)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${msg("Icon shown in sidebar/header and flow executor.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Favicon")}
?required=${true}
name="brandingFavicon"
>
<input
type="text"
value="${first(
this.instance?.brandingFavicon,
DefaultTenant.brandingFavicon,
)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${msg("Icon shown in the browser tab.")}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
<ak-form-group>
<span slot="header"> ${msg("Default flows")} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${msg("Authentication flow")}
name="flowAuthentication"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${this.instance?.flowAuthentication}
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg(
"Flow used to authenticate users. If left empty, the first applicable flow sorted by the slug is used.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Invalidation flow")}
name="flowInvalidation"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${this.instance?.flowInvalidation}
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg(
"Flow used to logout. If left empty, the first applicable flow sorted by the slug is used.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Recovery flow")} name="flowRecovery">
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Recovery}
.currentFlow=${this.instance?.flowRecovery}
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg(
"Recovery flow. If left empty, the first applicable flow sorted by the slug is used.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Unenrollment flow")}
name="flowUnenrollment"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Unenrollment}
.currentFlow=${this.instance?.flowUnenrollment}
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg(
"If set, users are able to unenroll themselves using this flow. If no flow is set, option is not shown.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("User settings flow")}
name="flowUserSettings"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.StageConfiguration}
.currentFlow=${this.instance?.flowUserSettings}
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg("If set, users are able to configure details of their profile.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Device code flow")}
name="flowDeviceCode"
>
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.StageConfiguration}
.currentFlow=${this.instance?.flowDeviceCode}
></ak-flow-search>
<p class="pf-c-form__helper-text">
${msg(
"If set, the OAuth Device Code profile can be used, and the selected flow will be used to enter the code.",
)}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
<ak-form-group>
<span slot="header"> ${msg("Other global settings")} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${msg("Web Certificate")}
name="webCertificate"
>
<ak-crypto-certificate-search
.certificate=${this.instance?.webCertificate}
></ak-crypto-certificate-search>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Event retention")}
?required=${true}
name="eventRetention"
>
<input
type="text"
value="${first(this.instance?.eventRetention, "days=365")}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${msg("Duration after which events will be deleted from the database.")}
</p>
<p class="pf-c-form__helper-text">
${msg(
'When using an external logging solution for archiving, this can be set to "minutes=5".',
)}
</p>
<p class="pf-c-form__helper-text">
${msg(
"This setting only affects new Events, as the expiration is saved per-event.",
)}
</p>
<p class="pf-c-form__helper-text">
${msg('Format: "weeks=3;days=2;hours=3,seconds=2".')}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Attributes")} name="attributes">
<ak-codemirror
mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(first(this.instance?.attributes, {}))}"
>
</ak-codemirror>
<p class="pf-c-form__helper-text">
${msg(
"Set custom attributes using YAML or JSON. Any attributes set here will be inherited by users, if the request is handled by this tenant.",
)}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>`;
}
}