web/admin: fix switches (#19493)

* web/admin: fix switches

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update all forms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Apply suggestions from code review

Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Jens L. <jens@beryju.org>

* fix lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
This commit is contained in:
Jens L.
2026-01-15 21:31:46 +01:00
committed by GitHub
parent 0f11ad6df0
commit cbff6b1eeb
7 changed files with 162 additions and 316 deletions
@@ -70,23 +70,12 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
${msg("Set custom attributes using YAML or JSON.")}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="verifySsl">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.verifySsl ?? true}
/>
<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("Verify Kubernetes API SSL Certificate")}</span
>
</label>
</ak-form-element-horizontal>`;
<ak-switch-input
name="verifySsl"
label=${msg("Verify Kubernetes API SSL Certificate")}
?checked=${this.instance?.verifySsl ?? true}
>
</ak-switch-input>`;
}
}
@@ -1,4 +1,5 @@
import "#elements/forms/FormGroup";
import "#components/ak-switch-input";
import "#elements/forms/HorizontalFormElement";
import { DEFAULT_CONFIG } from "#common/api/config";
@@ -228,26 +229,14 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.executionLogging ?? 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("Execution logging")}</span>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="executionLogging"
label=${msg("Execution logging")}
?checked=${this.instance?.executionLogging ?? false}
help=${msg(
"When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.",
)}
></ak-switch-input>
<ak-form-element-horizontal
label=${msg("Password field")}
required
@@ -264,73 +253,45 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="checkStaticRules">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.checkStaticRules ?? true}
@change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showStatic = el.checked;
}}
/>
<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("Check static rules")}</span>
</label>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="checkHaveIBeenPwned">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.checkHaveIBeenPwned ?? true}
@change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showHIBP = el.checked;
}}
/>
<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("Check haveibeenpwned.com")}</span>
</label>
<p class="pf-c-form__helper-text">
<ak-switch-input
name="checkStaticRules"
label=${msg("Check static rules")}
?checked=${this.instance?.checkStaticRules ?? true}
@change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showStatic = el.checked;
}}
></ak-switch-input>
<ak-switch-input
name="checkHaveIBeenPwned"
label=${msg("Check haveibeenpwned.com")}
?checked=${this.instance?.checkHaveIBeenPwned ?? true}
@change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showHIBP = el.checked;
}}
.bighelp=${html`<p class="pf-c-form__helper-text">
${msg("For more info see:")}
<a href="https://haveibeenpwned.com/API/v3#SearchingPwnedPasswordsByRange"
>haveibeenpwned.com</a
>
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="checkZxcvbn">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.checkZxcvbn ?? true}
@change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showZxcvbn = el.checked;
}}
/>
<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("Check zxcvbn")}</span>
</label>
<p class="pf-c-form__helper-text">
</p>`}
>
</ak-switch-input>
<ak-switch-input
name="checkZxcvbn"
label=${msg("Check zxcvbn")}
?checked=${this.instance?.checkZxcvbn ?? true}
@change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showZxcvbn = el.checked;
}}
.bighelp=${html`<p class="pf-c-form__helper-text">
${msg("Password strength estimator created by Dropbox, see:")}
<a href="https://github.com/dropbox/zxcvbn#readme">dropbox/zxcvbn</a>
</p>
</ak-form-element-horizontal>
</p>`}
>
</ak-switch-input>
${this.showStatic ? this.renderStaticRules() : nothing}
${this.showHIBP ? this.renderHIBP() : nothing}
${this.showZxcvbn ? this.renderZxcvbn() : nothing}`;
@@ -3,6 +3,7 @@ import "#elements/forms/FormGroup";
import "#elements/forms/HorizontalFormElement";
import "#elements/forms/Radio";
import "#elements/forms/SearchSelect/index";
import "#components/ak-switch-input";
import { DEFAULT_CONFIG } from "#common/api/config";
@@ -93,36 +94,18 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
?revealed=${!this.instance}
></ak-secret-text-input>
<ak-form-element-horizontal name="useTls">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.useTls ?? true}
/>
<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("Use TLS")}</span>
</label>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="useSsl">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.useSsl ?? 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("Use SSL")}</span>
</label>
</ak-form-element-horizontal>
<ak-switch-input
name="useTls"
label=${msg("Use TLS")}
?checked=${this.instance?.useTls ?? true}
>
</ak-switch-input>
<ak-switch-input
name="useSsl"
label=${msg("Use SSL")}
?checked=${this.instance?.useSsl ?? false}
>
</ak-switch-input>
<ak-form-element-horizontal label=${msg("Timeout")} required name="timeout">
<input
type="number"
@@ -176,30 +159,18 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="useGlobalSettings">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.useGlobalSettings ?? true}
@change=${(ev: Event) => {
const target = ev.target as HTMLInputElement;
this.showConnectionSettings = !target.checked;
}}
/>
<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("Use global connection settings")}</span>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When enabled, global email connection settings will be used and connection settings below will be ignored.",
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="useGlobalSettings"
?checked=${this.instance?.useGlobalSettings ?? true}
@change=${(ev: Event) => {
const target = ev.target as HTMLInputElement;
this.showConnectionSettings = !target.checked;
}}
label=${msg("Use global connection settings")}
help=${msg(
"When enabled, global email connection settings will be used and connection settings below will be ignored.",
)}
></ak-switch-input>
${this.renderConnectionSettings()}
<ak-form-group open label="${msg("Stage-specific settings")}">
<div class="pf-c-form">
+33 -76
View File
@@ -2,6 +2,7 @@ import "#components/ak-secret-text-input";
import "#elements/forms/FormGroup";
import "#elements/forms/HorizontalFormElement";
import "#elements/utils/TimeDeltaHelp";
import "#components/ak-switch-input";
import { DEFAULT_CONFIG } from "#common/api/config";
@@ -81,36 +82,18 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
name="password"
?revealed=${!this.instance}
></ak-secret-text-input>
<ak-form-element-horizontal name="useTls">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.useTls ?? true}
/>
<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("Use TLS")}</span>
</label>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="useSsl">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.useSsl ?? 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("Use SSL")}</span>
</label>
</ak-form-element-horizontal>
<ak-switch-input
name="useTls"
label=${msg("Use TLS")}
?checked=${this.instance?.useTls ?? true}
>
</ak-switch-input>
<ak-switch-input
name="useSsl"
label=${msg("Use SSL")}
?checked=${this.instance?.useSsl ?? false}
>
</ak-switch-input>
<ak-form-element-horizontal label=${msg("Timeout")} required name="timeout">
<input
type="number"
@@ -151,52 +134,26 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
</ak-form-element-horizontal>
<ak-form-group open label="${msg("Stage-specific settings")}">
<div class="pf-c-form">
<ak-form-element-horizontal name="activateUserOnSuccess">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.activateUserOnSuccess ?? true}
/>
<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("Activate pending user on success")}</span
>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When a user returns from the email successfully, their account will be activated.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="useGlobalSettings">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.useGlobalSettings ?? true}
@change=${(ev: Event) => {
const target = ev.target as HTMLInputElement;
this.showConnectionSettings = !target.checked;
}}
/>
<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("Use global settings")}</span>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When enabled, global Email connection settings will be used and connection settings below will be ignored.",
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="activateUserOnSuccess"
?checked=${this.instance?.activateUserOnSuccess ?? true}
label=${msg("Activate pending user on success")}
help=${msg(
"When a user returns from the email successfully, their account will be activated.",
)}
></ak-switch-input>
<ak-switch-input
name="useGlobalSettings"
?checked=${this.instance?.useGlobalSettings ?? true}
@change=${(ev: Event) => {
const target = ev.target as HTMLInputElement;
this.showConnectionSettings = !target.checked;
}}
label=${msg("Use global connection settings")}
help=${msg(
"When enabled, global email connection settings will be used and connection settings below will be ignored.",
)}
></ak-switch-input>
<ak-form-element-horizontal
label=${msg("Token expiration")}
required
+29 -67
View File
@@ -1,6 +1,7 @@
import "#elements/CodeMirror";
import "#elements/forms/HorizontalFormElement";
import "#flow/stages/prompt/PromptStage";
import "#components/ak-switch-input";
import { DEFAULT_CONFIG } from "#common/api/config";
import { parseAPIResponseError, pluckErrorDetail } from "#common/errors/network";
@@ -263,50 +264,24 @@ export class PromptForm extends ModelForm<Prompt, string> {
${this.renderTypes()}
</select>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="required">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.required ?? false}
@change=${() => {
this._shouldRefresh = true;
}}
/>
<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("Required")}</span>
</label>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="placeholderExpression">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.placeholderExpression ?? false}
@change=${() => {
this._shouldRefresh = true;
}}
/>
<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("Interpret placeholder as expression")}</span
>
</label>
<p class="pf-c-form__helper-text">
${msg(
`When checked, the placeholder will be evaluated in the same way a property mapping is.
If the evaluation fails, the placeholder itself is returned.`,
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="required"
?checked=${this.instance?.required ?? false}
@change=${() => {
this._shouldRefresh = true;
}}
label=${msg("Required")}
></ak-switch-input>
<ak-switch-input
name="placeholderExpression"
?checked=${this.instance?.placeholderExpression ?? false}
@change=${() => {
this._shouldRefresh = true;
}}
label=${msg("Interpret placeholder as expression")}
help=${msg(`When checked, the placeholder will be evaluated in the same way a property mapping is.
If the evaluation fails, the placeholder itself is returned.`)}
></ak-switch-input>
<ak-form-element-horizontal label=${msg("Placeholder")} name="placeholder">
<ak-codemirror
mode="python"
@@ -324,29 +299,16 @@ export class PromptForm extends ModelForm<Prompt, string> {
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="initialValueExpression">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${this.instance?.initialValueExpression ?? 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("Interpret initial value as expression")}</span
>
</label>
<p class="pf-c-form__helper-text">
${msg(
`When checked, the initial value will be evaluated in the same way a property mapping is.
If the evaluation fails, the initial value itself is returned.`,
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="initialValueExpression"
?checked=${this.instance?.initialValueExpression ?? false}
@change=${() => {
this._shouldRefresh = true;
}}
label=${msg("Interpret initial value as expression")}
help=${msg(`When checked, the initial value will be evaluated in the same way a property mapping is.
If the evaluation fails, the initial value itself is returned.`)}
></ak-switch-input>
<ak-form-element-horizontal label=${msg("Initial value")} name="initialValue">
<ak-codemirror mode="python" value="${ifDefined(this.instance?.initialValue)}">
</ak-codemirror>
+19 -5
View File
@@ -4,7 +4,7 @@ import { AKElement } from "#elements/Base";
import { IDGenerator } from "@goauthentik/core/id";
import { html, nothing } from "lit";
import { html, nothing, TemplateResult } from "lit";
import { customElement, property, query } from "lit/decorators.js";
@customElement("ak-switch-input")
@@ -35,14 +35,30 @@ export class AkSwitchInput extends AKElement {
@property({ type: String })
help = "";
/**
* For more complex help instructions, provide a template result.
*/
@property({ type: Object })
public bighelp!: TemplateResult | TemplateResult[];
@query("input.pf-c-switch__input[type=checkbox]")
checkbox!: HTMLInputElement;
#fieldID: string = IDGenerator.randomID();
protected renderHelp() {
const helpText = this.help.trim();
return [
helpText
? html`<p id="${this.#fieldID}-help" class="pf-c-form__helper-text">${helpText}</p>`
: nothing,
this.bighelp ? this.bighelp : nothing,
];
}
render() {
const doCheck = this.checked ? this.checked : undefined;
const helpText = this.help.trim();
return html` <ak-form-element-horizontal name=${this.name} ?required=${this.required}>
<div slot="label" class="pf-c-form__group-label"></div>
@@ -62,9 +78,7 @@ export class AkSwitchInput extends AKElement {
</span>
<span class="pf-c-switch__label" id="${this.#fieldID}-label">${this.label}</span>
</label>
${helpText
? html`<p id="${this.#fieldID}-help" class="pf-c-form__helper-text">${helpText}</p>`
: nothing}
${this.renderHelp()}
</ak-form-element-horizontal>`;
}
}
+8 -16
View File
@@ -2,6 +2,7 @@ import "#elements/events/LogViewer";
import "#admin/common/ak-flow-search/ak-flow-search-no-default";
import "#elements/forms/HorizontalFormElement";
import "#elements/forms/SearchSelect/index";
import "#components/ak-switch-input";
import { DEFAULT_CONFIG } from "#common/api/config";
@@ -127,22 +128,13 @@ export class SyncObjectForm extends Form<SyncObjectRequest> {
${this.model === SyncObjectModelEnum.AuthentikCoreModelsGroup
? this.renderSelectGroup()
: nothing}
<ak-form-element-horizontal name="overrideDryRun">
<label class="pf-c-switch">
<input class="pf-c-switch__input" type="checkbox" />
<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("Override dry-run mode")}</span>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When enabled, this sync will still execute mutating requests regardless of the dry-run mode in the provider.",
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="overrideDryRun"
label=${msg("Override dry-run mode")}
help=${msg(
"When enabled, this sync will still execute mutating requests regardless of the dry-run mode in the provider.",
)}
></ak-switch-input>
${this.result ? this.renderResult() : nothing}`;
}
}