Skip to content

Commit

Permalink
web/admin: fix misc dual select on different forms (#11203)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
BeryJu committed Sep 4, 2024
1 parent 392a2e5 commit dd75d5f
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 46 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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.",
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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";
Expand Down Expand Up @@ -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.",
Expand Down
16 changes: 13 additions & 3 deletions web/src/admin/events/RuleForm.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -16,6 +18,7 @@ import {
EventsApi,
Group,
NotificationRule,
NotificationTransport,
PaginatedNotificationTransportList,
SeverityEnum,
} from "@goauthentik/api";
Expand All @@ -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;
Expand Down Expand Up @@ -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.",
Expand Down
9 changes: 7 additions & 2 deletions web/src/admin/providers/oauth2/OAuth2PropertyMappings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
14 changes: 4 additions & 10 deletions web/src/admin/providers/oauth2/OAuth2ProviderForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
makeOAuth2PropertyMappingsSelector,
oauth2PropertyMappingsProvider,
} from "./OAuth2PropertyMappings.js";
import { oauth2SourcesProvider } from "./OAuth2Sources.js";
import { makeSourceSelector, oauth2SourcesProvider } from "./OAuth2Sources.js";

export const clientTypeOptions = [
{
Expand All @@ -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"),
Expand Down Expand Up @@ -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.",
Expand Down
11 changes: 10 additions & 1 deletion web/src/admin/providers/oauth2/OAuth2Sources.ts
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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;
}
12 changes: 7 additions & 5 deletions web/src/admin/providers/proxy/ProxyProviderForm.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -18,6 +20,7 @@ import {
DeviceClassesEnum,
NotConfiguredActionEnum,
PaginatedStageList,
Stage,
StagesApi,
UserVerificationEnum,
} from "@goauthentik/api";
Expand All @@ -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,
Expand Down Expand Up @@ -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.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 28 additions & 10 deletions web/src/admin/stages/prompt/PromptStageForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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,
Expand All @@ -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",
Expand All @@ -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> {
Expand Down Expand Up @@ -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>
Expand All @@ -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.",
Expand Down

0 comments on commit dd75d5f

Please sign in to comment.