web/admin: fix misc dual select on different forms (#11203)
* fix prompt stage Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix identification stage Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix OAuth JWKS sources Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix oauth provider default scopes Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix outpost form Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix webauthn Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix transport form Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> # Conflicts: # web/src/admin/applications/wizard/methods/oauth/ak-application-wizard-authentication-by-oauth.ts # web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts
This commit is contained in:
2
Makefile
2
Makefile
@ -205,7 +205,7 @@ gen: gen-build gen-client-ts
|
||||
web-build: web-install ## Build the Authentik UI
|
||||
cd web && npm run build
|
||||
|
||||
web: web-lint-fix web-lint web-check-compile web-test ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
|
||||
web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
|
||||
|
||||
web-install: ## Install the necessary libraries to build the Authentik UI
|
||||
cd web && npm ci
|
||||
|
@ -11,7 +11,10 @@ import {
|
||||
redirectUriHelp,
|
||||
subjectModeOptions,
|
||||
} from "@goauthentik/admin/providers/oauth2/OAuth2ProviderForm";
|
||||
import { oauth2SourcesProvider } from "@goauthentik/admin/providers/oauth2/OAuth2Sources.js";
|
||||
import {
|
||||
makeSourceSelector,
|
||||
oauth2SourcesProvider,
|
||||
} from "@goauthentik/admin/providers/oauth2/OAuth2Sources.js";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
|
||||
import "@goauthentik/components/ak-number-input";
|
||||
@ -263,12 +266,12 @@ export class ApplicationWizardAuthenticationByOauth extends BaseProviderPanel {
|
||||
name="jwksSources"
|
||||
.errorMessages=${errors?.jwksSources ?? []}
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selected=${provider?.jwksSources}
|
||||
.selector=${makeSourceSelector(provider?.jwksSources)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.",
|
||||
|
@ -1,5 +1,8 @@
|
||||
import "@goauthentik/admin/applications/wizard/ak-wizard-title";
|
||||
import { oauth2SourcesProvider } from "@goauthentik/admin/providers/oauth2/OAuth2Sources.js";
|
||||
import {
|
||||
makeSourceSelector,
|
||||
oauth2SourcesProvider,
|
||||
} from "@goauthentik/admin/providers/oauth2/OAuth2Sources.js";
|
||||
import {
|
||||
makeProxyPropertyMappingsSelector,
|
||||
proxyPropertyMappingsProvider,
|
||||
@ -11,7 +14,6 @@ import "@goauthentik/components/ak-text-input";
|
||||
import "@goauthentik/components/ak-textarea-input";
|
||||
import "@goauthentik/components/ak-toggle-group";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
@ -228,12 +230,12 @@ export class AkTypeProxyApplicationWizardPage extends BaseProviderPanel {
|
||||
name="jwksSources"
|
||||
.errorMessages=${errors?.jwksSources ?? []}
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selected=${this.instance?.jwksSources}
|
||||
.selector=${makeSourceSelector(this.instance?.jwksSources)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.",
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { severityToLabel } from "@goauthentik/common/labels";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||
import "@goauthentik/elements/forms/Radio";
|
||||
@ -16,6 +18,7 @@ import {
|
||||
EventsApi,
|
||||
Group,
|
||||
NotificationRule,
|
||||
NotificationTransport,
|
||||
PaginatedNotificationTransportList,
|
||||
SeverityEnum,
|
||||
} from "@goauthentik/api";
|
||||
@ -34,6 +37,13 @@ async function eventTransportsProvider(page = 1, search = "") {
|
||||
};
|
||||
}
|
||||
|
||||
export function makeTransportSelector(instanceTransports: string[] | undefined) {
|
||||
const localTransports = instanceTransports ? new Set(instanceTransports) : undefined;
|
||||
|
||||
return localTransports
|
||||
? ([pk, _]: DualSelectPair) => localTransports.has(pk)
|
||||
: ([_0, _1, _2, stage]: DualSelectPair<NotificationTransport>) => stage !== undefined;
|
||||
}
|
||||
@customElement("ak-event-rule-form")
|
||||
export class RuleForm extends ModelForm<NotificationRule, string> {
|
||||
eventTransports?: PaginatedNotificationTransportList;
|
||||
@ -114,12 +124,12 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
|
||||
?required=${true}
|
||||
name="transports"
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${eventTransportsProvider}
|
||||
.selected=${this.instance?.transports}
|
||||
.selector=${makeTransportSelector(this.instance?.transports)}
|
||||
available-label="${msg("Available Transports")}"
|
||||
selected-label="${msg("Selected Transports")}"
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.",
|
||||
|
@ -3,6 +3,12 @@ import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types.js";
|
||||
|
||||
import { PropertymappingsApi, ScopeMapping } from "@goauthentik/api";
|
||||
|
||||
export const defaultScopes = [
|
||||
"goauthentik.io/providers/oauth2/scope-openid",
|
||||
"goauthentik.io/providers/oauth2/scope-email",
|
||||
"goauthentik.io/providers/oauth2/scope-profile",
|
||||
];
|
||||
|
||||
export async function oauth2PropertyMappingsProvider(page = 1, search = "") {
|
||||
const propertyMappings = await new PropertymappingsApi(
|
||||
DEFAULT_CONFIG,
|
||||
@ -23,6 +29,5 @@ export function makeOAuth2PropertyMappingsSelector(instanceMappings: string[] |
|
||||
return localMappings
|
||||
? ([pk, _]: DualSelectPair) => localMappings.has(pk)
|
||||
: ([_0, _1, _2, scope]: DualSelectPair<ScopeMapping>) =>
|
||||
scope?.managed?.startsWith("goauthentik.io/providers/oauth2/scope-") &&
|
||||
scope?.managed !== "goauthentik.io/providers/oauth2/scope-offline_access";
|
||||
scope?.managed && defaultScopes.includes(scope?.managed);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import {
|
||||
makeOAuth2PropertyMappingsSelector,
|
||||
oauth2PropertyMappingsProvider,
|
||||
} from "./OAuth2PropertyMappings.js";
|
||||
import { oauth2SourcesProvider } from "./OAuth2Sources.js";
|
||||
import { makeSourceSelector, oauth2SourcesProvider } from "./OAuth2Sources.js";
|
||||
|
||||
export const clientTypeOptions = [
|
||||
{
|
||||
@ -52,12 +52,6 @@ export const clientTypeOptions = [
|
||||
},
|
||||
];
|
||||
|
||||
export const defaultScopes = [
|
||||
"goauthentik.io/providers/oauth2/scope-openid",
|
||||
"goauthentik.io/providers/oauth2/scope-email",
|
||||
"goauthentik.io/providers/oauth2/scope-profile",
|
||||
];
|
||||
|
||||
export const subjectModeOptions = [
|
||||
{
|
||||
label: msg("Based on the User's hashed ID"),
|
||||
@ -335,12 +329,12 @@ export class OAuth2ProviderFormPage extends BaseProviderForm<OAuth2Provider> {
|
||||
label=${msg("Trusted OIDC Sources")}
|
||||
name="jwksSources"
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selected=${provider?.jwksSources}
|
||||
.selector=${makeSourceSelector(provider?.jwksSources)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
|
||||
|
||||
import { SourcesApi } from "@goauthentik/api";
|
||||
import { OAuthSource, SourcesApi } from "@goauthentik/api";
|
||||
|
||||
export async function oauth2SourcesProvider(page = 1, search = "") {
|
||||
const oauthSources = await new SourcesApi(DEFAULT_CONFIG).sourcesOauthList({
|
||||
@ -19,3 +20,11 @@ export async function oauth2SourcesProvider(page = 1, search = "") {
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
export function makeSourceSelector(instanceSources: string[] | undefined) {
|
||||
const localSources = instanceSources ? new Set(instanceSources) : undefined;
|
||||
|
||||
return localSources
|
||||
? ([pk, _]: DualSelectPair) => localSources.has(pk)
|
||||
: ([_0, _1, _2, prompt]: DualSelectPair<OAuthSource>) => prompt !== undefined;
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
|
||||
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
||||
import { oauth2SourcesProvider } from "@goauthentik/admin/providers/oauth2/OAuth2Sources.js";
|
||||
import {
|
||||
makeSourceSelector,
|
||||
oauth2SourcesProvider,
|
||||
} from "@goauthentik/admin/providers/oauth2/OAuth2Sources.js";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { first } from "@goauthentik/common/utils";
|
||||
import "@goauthentik/components/ak-toggle-group";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/SearchSelect";
|
||||
@ -403,12 +405,12 @@ ${this.instance?.skipPathRegex}</textarea
|
||||
label=${msg("Trusted OIDC Sources")}
|
||||
name="jwksSources"
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${oauth2SourcesProvider}
|
||||
.selected=${this.instance?.jwksSources}
|
||||
.selector=${makeSourceSelector(this.instance?.jwksSources)}
|
||||
available-label=${msg("Available Sources")}
|
||||
selected-label=${msg("Selected Sources")}
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.",
|
||||
|
@ -2,7 +2,9 @@ import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
|
||||
import { deviceTypeRestrictionPair } from "@goauthentik/admin/stages/authenticator_webauthn/utils";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import "@goauthentik/elements/Alert";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider";
|
||||
import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/Radio";
|
||||
@ -18,6 +20,7 @@ import {
|
||||
DeviceClassesEnum,
|
||||
NotConfiguredActionEnum,
|
||||
PaginatedStageList,
|
||||
Stage,
|
||||
StagesApi,
|
||||
UserVerificationEnum,
|
||||
} from "@goauthentik/api";
|
||||
@ -36,6 +39,14 @@ async function stagesProvider(page = 1, search = "") {
|
||||
};
|
||||
}
|
||||
|
||||
export function makeStageSelector(instanceStages: string[] | undefined) {
|
||||
const localStages = instanceStages ? new Set(instanceStages) : undefined;
|
||||
|
||||
return localStages
|
||||
? ([pk, _]: DualSelectPair) => localStages.has(pk)
|
||||
: ([_0, _1, _2, stage]: DualSelectPair<Stage>) => stage !== undefined;
|
||||
}
|
||||
|
||||
async function authenticatorWebauthnDeviceTypesListProvider(page = 1, search = "") {
|
||||
const devicetypes = await new StagesApi(
|
||||
DEFAULT_CONFIG,
|
||||
@ -205,14 +216,14 @@ export class AuthenticatorValidateStageForm extends BaseStageForm<AuthenticatorV
|
||||
label=${msg("Configuration stages")}
|
||||
name="configurationStages"
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${stagesProvider}
|
||||
.selected=${Array.from(
|
||||
this.instance?.configurationStages ?? [],
|
||||
.selector=${makeStageSelector(
|
||||
this.instance?.configurationStages,
|
||||
)}
|
||||
available-label="${msg("Available Stages")}"
|
||||
selected-label="${msg("Selected Stages")}"
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.",
|
||||
|
@ -41,7 +41,7 @@ async function sourcesProvider(page = 1, search = "") {
|
||||
};
|
||||
}
|
||||
|
||||
async function makeSourcesSelector(instanceSources: string[] | undefined) {
|
||||
function makeSourcesSelector(instanceSources: string[] | undefined) {
|
||||
const localSources = instanceSources ? new Set(instanceSources) : undefined;
|
||||
|
||||
return localSources
|
||||
|
@ -2,6 +2,8 @@ import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
|
||||
import "@goauthentik/admin/stages/prompt/PromptForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { PFSize } from "@goauthentik/common/enums";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import { DualSelectPair } from "@goauthentik/elements/ak-dual-select/types.js";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
@ -11,9 +13,9 @@ import { TemplateResult, html, nothing } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import { PoliciesApi, PromptStage, StagesApi } from "@goauthentik/api";
|
||||
import { PoliciesApi, Policy, Prompt, PromptStage, StagesApi } from "@goauthentik/api";
|
||||
|
||||
async function promptsProvider(page = 1, search = "") {
|
||||
async function promptFieldsProvider(page = 1, search = "") {
|
||||
const prompts = await new StagesApi(DEFAULT_CONFIG).stagesPromptPromptsList({
|
||||
ordering: "field_name",
|
||||
pageSize: 20,
|
||||
@ -25,11 +27,19 @@ async function promptsProvider(page = 1, search = "") {
|
||||
pagination: prompts.pagination,
|
||||
options: prompts.results.map((prompt) => [
|
||||
prompt.pk,
|
||||
str`${prompt.name} ("${prompt.fieldKey}", of type ${prompt.type})`,
|
||||
msg(str`${prompt.name} ("${prompt.fieldKey}", of type ${prompt.type})`),
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
||||
function makeFieldSelector(instanceFields: string[] | undefined) {
|
||||
const localFields = instanceFields ? new Set(instanceFields) : undefined;
|
||||
|
||||
return localFields
|
||||
? ([pk, _]: DualSelectPair) => localFields.has(pk)
|
||||
: ([_0, _1, _2, prompt]: DualSelectPair<Prompt>) => prompt !== undefined;
|
||||
}
|
||||
|
||||
async function policiesProvider(page = 1, search = "") {
|
||||
const policies = await new PoliciesApi(DEFAULT_CONFIG).policiesAllList({
|
||||
ordering: "name",
|
||||
@ -47,6 +57,14 @@ async function policiesProvider(page = 1, search = "") {
|
||||
};
|
||||
}
|
||||
|
||||
function makePoliciesSelector(instancePolicies: string[] | undefined) {
|
||||
const localPolicies = instancePolicies ? new Set(instancePolicies) : undefined;
|
||||
|
||||
return localPolicies
|
||||
? ([pk, _]: DualSelectPair) => localPolicies.has(pk)
|
||||
: ([_0, _1, _2, policy]: DualSelectPair<Policy>) => policy !== undefined;
|
||||
}
|
||||
|
||||
@customElement("ak-stage-prompt-form")
|
||||
export class PromptStageForm extends BaseStageForm<PromptStage> {
|
||||
loadInstance(pk: string): Promise<PromptStage> {
|
||||
@ -90,12 +108,12 @@ export class PromptStageForm extends BaseStageForm<PromptStage> {
|
||||
?required=${true}
|
||||
name="fields"
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
.provider=${promptsProvider}
|
||||
.selected=${this.instance?.fields}
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${promptFieldsProvider}
|
||||
.selector=${makeFieldSelector(this.instance?.fields)}
|
||||
available-label="${msg("Available Fields")}"
|
||||
selected-label="${msg("Selected Fields")}"
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
${this.instance
|
||||
? html`<ak-forms-modal size=${PFSize.XLarge}>
|
||||
<span slot="submit"> ${msg("Create")} </span>
|
||||
@ -115,12 +133,12 @@ export class PromptStageForm extends BaseStageForm<PromptStage> {
|
||||
label=${msg("Validation Policies")}
|
||||
name="validationPolicies"
|
||||
>
|
||||
<ak-dual-select-provider
|
||||
<ak-dual-select-dynamic-selected
|
||||
.provider=${policiesProvider}
|
||||
.selected=${this.instance?.validationPolicies}
|
||||
.selector=${makePoliciesSelector(this.instance?.validationPolicies)}
|
||||
available-label="${msg("Available Fields")}"
|
||||
selected-label="${msg("Selected Fields")}"
|
||||
></ak-dual-select-provider>
|
||||
></ak-dual-select-dynamic-selected>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"Selected policies are executed when the stage is submitted to validate the data.",
|
||||
|
Reference in New Issue
Block a user