web/admin: fix read-only provider selection for application form (cherry-pick #18768 to version-2025.12) (#18803)

Co-authored-by: Dominic R <dominic@sdko.org>
fix read-only provider selection for application form (#18768)
This commit is contained in:
authentik-automation[bot]
2025-12-16 18:10:49 +01:00
committed by GitHub
parent 409652e874
commit e73edc2fce
4 changed files with 54 additions and 4 deletions
@@ -99,6 +99,9 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Applicatio
const alertMsg = msg(
"Using this form will only create an Application. In order to authenticate with the application, you will have to manually pair it with a Provider.",
);
const providerFromInstance = this.instance?.provider;
const providerValue = providerFromInstance ?? this.provider;
const providerPrefilled = !this.instance && this.provider !== undefined;
return html`
${this.instance ? nothing : html`<ak-alert level="pf-m-info">${alertMsg}</ak-alert>`}
@@ -134,9 +137,10 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Applicatio
<ak-provider-search-input
name="provider"
label=${msg("Provider")}
value=${ifPresent(this.instance?.provider)}
.value=${providerValue}
.readOnly=${providerPrefilled}
?blankable=${!providerPrefilled}
help=${msg("Select a provider that this application should use.")}
blankable
></ak-provider-search-input>
<ak-backchannel-providers-input
name="backchannelProviders"
@@ -13,6 +13,7 @@ import { Provider, ProvidersAllListRequest, ProvidersApi } from "@goauthentik/ap
import { html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
const renderElement = (item: Provider) => item.name;
const renderValue = (item: Provider | undefined) => item?.pk;
@@ -53,6 +54,9 @@ export class AkProviderInput extends AKElement {
@property({ type: Number })
value?: number;
@property({ type: Boolean, attribute: "readonly" })
readOnly = false;
@property({ type: Boolean })
required = false;
@@ -76,6 +80,8 @@ export class AkProviderInput extends AKElement {
};
render() {
const readOnlyValue = this.readOnly && typeof this.value === "number";
return html` <ak-form-element-horizontal name=${this.name}>
${AKLabel(
{
@@ -86,7 +92,9 @@ export class AkProviderInput extends AKElement {
},
this.label,
)}
${readOnlyValue
? html`<input type="hidden" name=${this.name} value=${this.value ?? ""} />`
: nothing}
<ak-search-select
.fieldID=${this.fieldID}
.selected=${this.#selected}
@@ -94,7 +102,9 @@ export class AkProviderInput extends AKElement {
.renderElement=${renderElement}
.value=${renderValue}
.groupBy=${doGroupBy}
?blankable=${!!this.blankable}
?blankable=${readOnlyValue ? false : !!this.blankable}
?readonly=${this.readOnly}
name=${ifDefined(readOnlyValue ? undefined : this.name)}
>
</ak-search-select>
${this.help ? html`<p class="pf-c-form__helper-text">${this.help}</p>` : nothing}
@@ -23,6 +23,7 @@ type Group<T> = [string, T[]];
export interface ISearchSelectBase<T> {
blankable?: boolean;
readOnly?: boolean;
query?: string;
objects?: T[];
selectedObject: T | null;
@@ -93,6 +94,14 @@ export abstract class SearchSelectBase<T>
@property({ type: Boolean })
public creatable?: boolean;
/**
* Prevent user interaction while still rendering the current value.
* @property
* @attr
*/
@property({ type: Boolean, attribute: "readonly" })
public readOnly = false;
/**
* An initial string to filter the search contents,
* and the value of the input which further serves to restrict the search.
@@ -254,6 +263,8 @@ export abstract class SearchSelectBase<T>
}
#searchListener = (event: InputEvent) => {
if (this.readOnly) return;
const value = (event.target as SearchSelectView).rawValue;
if (!value) {
@@ -277,6 +288,8 @@ export abstract class SearchSelectBase<T>
};
private onSelect(event: InputEvent) {
if (this.readOnly) return;
const value = (event.target as SearchSelectView).value;
if (!value) {
@@ -381,6 +394,7 @@ export abstract class SearchSelectBase<T>
.options=${options}
value=${ifPresent(value)}
?blankable=${this.blankable}
?readonly=${this.readOnly}
label=${ifPresent(this.label)}
name=${ifPresent(this.name)}
placeholder=${ifPresent(this.placeholder)}
@@ -24,6 +24,7 @@ export interface ISearchSelectView {
value?: string;
open: boolean;
blankable: boolean;
readOnly: boolean;
caseSensitive: boolean;
name?: string;
placeholder: string;
@@ -126,6 +127,14 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
@property({ type: Boolean })
public blankable = false;
/**
* Prevents user interaction while showing the current value.
*
* @attr
*/
@property({ type: Boolean, attribute: "readonly" })
public readOnly = false;
/**
* If not managed, make the matcher case-sensitive during interaction. If managed,
* the manager must handle this.
@@ -248,6 +257,8 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
//#region Event Listeners
#clickListener = (_ev: Event) => {
if (this.readOnly) return;
this.open = !this.open;
this.#inputRef.value?.focus();
};
@@ -263,6 +274,8 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
}
#searchKeyupListener = (event: KeyboardEvent) => {
if (this.readOnly) return;
if (event.key === "Escape") {
event.stopPropagation();
event.preventDefault();
@@ -277,6 +290,8 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
};
#searchKeydownListener = (event: KeyboardEvent) => {
if (this.readOnly) return;
if (!this.open) return;
switch (event.key) {
@@ -339,6 +354,8 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
}
#inputListener = (_ev: InputEvent) => {
if (this.readOnly) return;
if (!this.managed) {
this.findValueForInput();
this.requestUpdate();
@@ -356,6 +373,8 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
};
#listKeydownListener = (event: KeyboardEvent) => {
if (this.readOnly) return;
if (event.key === "Tab" && event.shiftKey) {
event.preventDefault();
@@ -364,6 +383,8 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
};
#changeListener = (event: InputEvent) => {
if (this.readOnly) return;
if (!event.target) {
return;
}
@@ -441,6 +462,7 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
@keyup=${this.#searchKeyupListener}
@keydown=${this.#searchKeydownListener}
value=${this.displayValue}
?readonly=${this.readOnly}
/>
</div>
</div>