stages/redirect: create redirect stage (#12275)
* create redirect stage * show "keep context" toggle in Flow mode only * fix typos * add docs Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> * simplify property pass * simplify toggle * remove `print` statements whoops * fix typo * remove default from `RedirectStage.mode` * remove migration Signed-off-by: Jens Langhammer <jens@goauthentik.io> * oops Signed-off-by: Jens Langhammer <jens@goauthentik.io> * adjust docs Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -189,21 +189,28 @@ export class FlowForm extends WithCapabilitiesConfig(ModelForm<Flow, string>) {
|
||||
?selected=${this.instance?.authentication ===
|
||||
AuthenticationEnum.RequireUnauthenticated}
|
||||
>
|
||||
${msg("Require no authentication.")}
|
||||
${msg("Require no authentication")}
|
||||
</option>
|
||||
<option
|
||||
value=${AuthenticationEnum.RequireSuperuser}
|
||||
?selected=${this.instance?.authentication ===
|
||||
AuthenticationEnum.RequireSuperuser}
|
||||
>
|
||||
${msg("Require superuser.")}
|
||||
${msg("Require superuser")}
|
||||
</option>
|
||||
<option
|
||||
value=${AuthenticationEnum.RequireRedirect}
|
||||
?selected=${this.instance?.authentication ===
|
||||
AuthenticationEnum.RequireRedirect}
|
||||
>
|
||||
${msg("Require being redirected from another flow")}
|
||||
</option>
|
||||
<option
|
||||
value=${AuthenticationEnum.RequireOutpost}
|
||||
?selected=${this.instance?.authentication ===
|
||||
AuthenticationEnum.RequireOutpost}
|
||||
>
|
||||
${msg("Require Outpost (flow can only be executed from an outpost).")}
|
||||
${msg("Require Outpost (flow can only be executed from an outpost)")}
|
||||
</option>
|
||||
</select>
|
||||
<p class="pf-c-form__helper-text">
|
||||
|
@ -17,6 +17,7 @@ import "@goauthentik/admin/stages/identification/IdentificationStageForm";
|
||||
import "@goauthentik/admin/stages/invitation/InvitationStageForm";
|
||||
import "@goauthentik/admin/stages/password/PasswordStageForm";
|
||||
import "@goauthentik/admin/stages/prompt/PromptStageForm";
|
||||
import "@goauthentik/admin/stages/redirect/RedirectStageForm";
|
||||
import "@goauthentik/admin/stages/source/SourceStageForm";
|
||||
import "@goauthentik/admin/stages/user_delete/UserDeleteStageForm";
|
||||
import "@goauthentik/admin/stages/user_login/UserLoginStageForm";
|
||||
|
@ -15,6 +15,7 @@ import "@goauthentik/admin/stages/identification/IdentificationStageForm";
|
||||
import "@goauthentik/admin/stages/invitation/InvitationStageForm";
|
||||
import "@goauthentik/admin/stages/password/PasswordStageForm";
|
||||
import "@goauthentik/admin/stages/prompt/PromptStageForm";
|
||||
import "@goauthentik/admin/stages/redirect/RedirectStageForm";
|
||||
import "@goauthentik/admin/stages/source/SourceStageForm";
|
||||
import "@goauthentik/admin/stages/user_delete/UserDeleteStageForm";
|
||||
import "@goauthentik/admin/stages/user_login/UserLoginStageForm";
|
||||
|
@ -83,13 +83,13 @@ export class ConsentStageForm extends BaseStageForm<ConsentStage> {
|
||||
value=${ConsentStageModeEnum.Permanent}
|
||||
?selected=${this.instance?.mode === ConsentStageModeEnum.Permanent}
|
||||
>
|
||||
${msg("Consent given last indefinitely")}
|
||||
${msg("Consent given lasts indefinitely")}
|
||||
</option>
|
||||
<option
|
||||
value=${ConsentStageModeEnum.Expiring}
|
||||
?selected=${this.instance?.mode === ConsentStageModeEnum.Expiring}
|
||||
>
|
||||
${msg("Consent expires.")}
|
||||
${msg("Consent expires")}
|
||||
</option>
|
||||
</select>
|
||||
</ak-form-element-horizontal>
|
||||
|
145
web/src/admin/stages/redirect/RedirectStageForm.ts
Normal file
145
web/src/admin/stages/redirect/RedirectStageForm.ts
Normal file
@ -0,0 +1,145 @@
|
||||
import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
|
||||
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import {
|
||||
Flow,
|
||||
FlowsApi,
|
||||
FlowsInstancesListRequest,
|
||||
RedirectStage,
|
||||
RedirectStageModeEnum,
|
||||
StagesApi,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-stage-redirect-form")
|
||||
export class RedirectStageForm extends BaseStageForm<RedirectStage> {
|
||||
@property({ type: String })
|
||||
mode: string = RedirectStageModeEnum.Static;
|
||||
|
||||
loadInstance(pk: string): Promise<RedirectStage> {
|
||||
return new StagesApi(DEFAULT_CONFIG)
|
||||
.stagesRedirectRetrieve({
|
||||
stageUuid: pk,
|
||||
})
|
||||
.then((stage) => {
|
||||
this.mode = stage.mode ?? RedirectStageModeEnum.Static;
|
||||
return stage;
|
||||
});
|
||||
}
|
||||
|
||||
async send(data: RedirectStage): Promise<RedirectStage> {
|
||||
if (this.instance) {
|
||||
return new StagesApi(DEFAULT_CONFIG).stagesRedirectUpdate({
|
||||
stageUuid: this.instance.pk || "",
|
||||
redirectStageRequest: data,
|
||||
});
|
||||
} else {
|
||||
return new StagesApi(DEFAULT_CONFIG).stagesRedirectCreate({
|
||||
redirectStageRequest: data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
return html`<span>
|
||||
${msg("Redirect the user to another flow, potentially with all gathered context")}
|
||||
</span>
|
||||
<ak-form-element-horizontal label=${msg("Name")} required name="name">
|
||||
<input
|
||||
type="text"
|
||||
value="${this.instance?.name ?? ""}"
|
||||
class="pf-c-form-control"
|
||||
required
|
||||
/>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-group expanded>
|
||||
<span slot="header"> ${msg("Stage-specific settings")} </span>
|
||||
<div slot="body" class="pf-c-form">
|
||||
<ak-form-element-horizontal label=${msg("Mode")} required name="mode">
|
||||
<select
|
||||
class="pf-c-form-control"
|
||||
@change=${(ev: Event) => {
|
||||
const target = ev.target as HTMLSelectElement;
|
||||
this.mode = target.selectedOptions[0].value;
|
||||
}}
|
||||
>
|
||||
<option
|
||||
value=${RedirectStageModeEnum.Static}
|
||||
?selected=${this.instance?.mode === RedirectStageModeEnum.Static}
|
||||
>
|
||||
${msg("Static")}
|
||||
</option>
|
||||
<option
|
||||
value=${RedirectStageModeEnum.Flow}
|
||||
?selected=${this.instance?.mode === RedirectStageModeEnum.Flow}
|
||||
>
|
||||
${msg("Flow")}
|
||||
</option>
|
||||
</select>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
?hidden=${this.mode !== RedirectStageModeEnum.Static}
|
||||
label=${msg("Target URL")}
|
||||
name="targetStatic"
|
||||
required
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
value="${this.instance?.targetStatic ?? ""}"
|
||||
class="pf-c-form-control"
|
||||
/>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg("Redirect the user to a static URL.")}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal
|
||||
?hidden=${this.mode !== RedirectStageModeEnum.Flow}
|
||||
label=${msg("Target Flow")}
|
||||
name="targetFlow"
|
||||
required
|
||||
>
|
||||
<ak-search-select
|
||||
.fetchObjects=${async (query?: string): Promise<Flow[]> => {
|
||||
const args: FlowsInstancesListRequest = {
|
||||
ordering: "slug",
|
||||
};
|
||||
if (query !== undefined) {
|
||||
args.search = query;
|
||||
}
|
||||
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList(
|
||||
args,
|
||||
);
|
||||
return flows.results;
|
||||
}}
|
||||
.renderElement=${(flow: Flow): string => RenderFlowOption(flow)}
|
||||
.renderDescription=${(flow: Flow): TemplateResult => html`${flow.name}`}
|
||||
.value=${(flow: Flow | undefined): string | undefined => flow?.pk}
|
||||
.selected=${(flow: Flow): boolean =>
|
||||
this.instance?.targetFlow === flow.pk}
|
||||
blankable
|
||||
>
|
||||
</ak-search-select>
|
||||
<p class="pf-c-form__helper-text">${msg("Redirect the user to a Flow.")}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-switch-input
|
||||
?hidden=${this.mode !== RedirectStageModeEnum.Flow}
|
||||
name="keepContext"
|
||||
label=${msg("Keep flow context")}
|
||||
?checked="${this.instance?.keepContext ?? true}"
|
||||
>
|
||||
</ak-switch-input>
|
||||
</div>
|
||||
</ak-form-group>`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-stage-redirect-form": RedirectStageForm;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user