web: re-organise frontend and cleanup common code (#3572)
* fix repo in api client Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * web: re-organise files to match their interface Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * core: include version in script tags Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * cleanup maybe broken Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * revert rename Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * web: get rid of Client.ts Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * move more to common Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * more moving Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * format Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * unfuck files that vscode fucked, thanks Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * move more Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * finish moving (maybe) Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * ok more moving Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix more stuff that vs code destroyed Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * get rid "web" prefix for virtual package Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix locales Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * use custom base element Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix css file Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * don't run autoDetectLanguage when importing locale Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix circular dependencies Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * web: fix build Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
66
web/src/admin/applications/wizard/ApplicationWizard.ts
Normal file
66
web/src/admin/applications/wizard/ApplicationWizard.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import "@goauthentik/admin/applications/wizard/InitialApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/TypeApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/ldap/TypeLDAPApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/link/TypeLinkApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/oauth/TypeOAuthAPIApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/oauth/TypeOAuthApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/oauth/TypeOAuthCodeApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/oauth/TypeOAuthImplicitApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/proxy/TypeProxyApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/saml/TypeSAMLApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/saml/TypeSAMLConfigApplicationWizardPage";
|
||||
import "@goauthentik/admin/applications/wizard/saml/TypeSAMLImportApplicationWizardPage";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/wizard/Wizard";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
|
||||
import AKGlobal from "@goauthentik/common/styles/authentik.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
@customElement("ak-application-wizard")
|
||||
export class ApplicationWizard extends AKElement {
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFButton, AKGlobal, PFRadio];
|
||||
}
|
||||
|
||||
@property({ type: Boolean })
|
||||
open = false;
|
||||
|
||||
@property()
|
||||
createText = t`Create`;
|
||||
|
||||
@property({ type: Boolean })
|
||||
showButton = true;
|
||||
|
||||
@property({ attribute: false })
|
||||
finalHandler: () => Promise<void> = () => {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`
|
||||
<ak-wizard
|
||||
.open=${this.open}
|
||||
.steps=${["ak-application-wizard-initial", "ak-application-wizard-type"]}
|
||||
header=${t`New application`}
|
||||
description=${t`Create a new application.`}
|
||||
.finalHandler=${() => {
|
||||
return this.finalHandler();
|
||||
}}
|
||||
>
|
||||
${this.showButton
|
||||
? html`<button slot="trigger" class="pf-c-button pf-m-primary">
|
||||
${this.createText}
|
||||
</button>`
|
||||
: html``}
|
||||
</ak-wizard>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { convertToSlug } from "@goauthentik/common/utils";
|
||||
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
import { ApplicationRequest, CoreApi, Provider } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-initial")
|
||||
export class InitialApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`Application details`;
|
||||
|
||||
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
|
||||
const name = data.name as string;
|
||||
let slug = convertToSlug(name || "");
|
||||
// Check if an application with the generated slug already exists
|
||||
const apps = await new CoreApi(DEFAULT_CONFIG).coreApplicationsList({
|
||||
search: slug,
|
||||
});
|
||||
if (apps.results.filter((app) => app.slug == slug)) {
|
||||
slug += "-1";
|
||||
}
|
||||
this.host.state["slug"] = slug;
|
||||
this.host.state["name"] = name;
|
||||
this.host.addActionBefore(t`Create application`, async (): Promise<boolean> => {
|
||||
const req: ApplicationRequest = {
|
||||
name: name || "",
|
||||
slug: slug,
|
||||
metaPublisher: data.metaPublisher as string,
|
||||
metaDescription: data.metaDescription as string,
|
||||
};
|
||||
if ("provider" in this.host.state) {
|
||||
req.provider = (this.host.state["provider"] as Provider).pk;
|
||||
}
|
||||
if ("link" in this.host.state) {
|
||||
req.metaLaunchUrl = this.host.state["link"] as string;
|
||||
}
|
||||
this.host.state["app"] = await new CoreApi(DEFAULT_CONFIG).coreApplicationsCreate({
|
||||
applicationRequest: req,
|
||||
});
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
return html`
|
||||
<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
|
||||
<input type="text" value="" class="pf-c-form-control" required />
|
||||
<p class="pf-c-form__helper-text">${t`Application's display Name.`}</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-group ?expanded=${true}>
|
||||
<span slot="header"> ${t`Additional UI settings`} </span>
|
||||
<div slot="body" class="pf-c-form">
|
||||
<ak-form-element-horizontal label=${t`Description`} name="metaDescription">
|
||||
<textarea class="pf-c-form-control"></textarea>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal label=${t`Publisher`} name="metaPublisher">
|
||||
<input type="text" value="" class="pf-c-form-control" />
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>
|
||||
</form>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
|
||||
import AKGlobal from "@goauthentik/common/styles/authentik.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { TypeCreate } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type")
|
||||
export class TypeApplicationWizardPage extends WizardPage {
|
||||
applicationTypes: TypeCreate[] = [
|
||||
{
|
||||
component: "ak-application-wizard-type-oauth",
|
||||
name: t`OAuth2/OIDC`,
|
||||
description: t`Modern applications, APIs and Single-page applications.`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-saml",
|
||||
name: t`SAML`,
|
||||
description: t`XML-based SSO standard. Use this if your application only supports SAML.`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-proxy",
|
||||
name: t`Proxy`,
|
||||
description: t`Legacy applications which don't natively support SSO.`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-ldap",
|
||||
name: t`LDAP`,
|
||||
description: t`Provide an LDAP interface for applications and users to authenticate against.`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-link",
|
||||
name: t`Link`,
|
||||
description: t`Provide an LDAP interface for applications and users to authenticate against.`,
|
||||
modelName: "",
|
||||
},
|
||||
];
|
||||
|
||||
sidebarLabel = () => t`Authentication method`;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFButton, PFForm, PFRadio, AKGlobal];
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
${this.applicationTypes.map((type) => {
|
||||
return html`<div class="pf-c-radio">
|
||||
<input
|
||||
class="pf-c-radio__input"
|
||||
type="radio"
|
||||
name="type"
|
||||
id=${type.component}
|
||||
@change=${() => {
|
||||
this.host.steps = [
|
||||
"ak-application-wizard-initial",
|
||||
"ak-application-wizard-type",
|
||||
type.component,
|
||||
];
|
||||
this.host.isValid = true;
|
||||
}}
|
||||
/>
|
||||
<label class="pf-c-radio__label" for=${type.component}>${type.name}</label>
|
||||
<span class="pf-c-radio__description">${type.description}</span>
|
||||
</div>`;
|
||||
})}
|
||||
</form>`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
import {
|
||||
CoreApi,
|
||||
FlowDesignationEnum,
|
||||
FlowsApi,
|
||||
LDAPProviderRequest,
|
||||
ProvidersApi,
|
||||
UserServiceAccountResponse,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type-ldap")
|
||||
export class TypeLDAPApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`LDAP details`;
|
||||
|
||||
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
|
||||
let name = this.host.state["name"] as string;
|
||||
// Check if a provider with the name already exists
|
||||
const providers = await new ProvidersApi(DEFAULT_CONFIG).providersAllList({
|
||||
search: name,
|
||||
});
|
||||
if (providers.results.filter((provider) => provider.name == name)) {
|
||||
name += "-1";
|
||||
}
|
||||
this.host.addActionBefore(t`Create service account`, async (): Promise<boolean> => {
|
||||
const serviceAccount = await new CoreApi(DEFAULT_CONFIG).coreUsersServiceAccountCreate({
|
||||
userServiceAccountRequest: {
|
||||
name: name,
|
||||
createGroup: true,
|
||||
},
|
||||
});
|
||||
this.host.state["serviceAccount"] = serviceAccount;
|
||||
return true;
|
||||
});
|
||||
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => {
|
||||
// Get all flows and default to the implicit authorization
|
||||
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
|
||||
designation: FlowDesignationEnum.Authorization,
|
||||
ordering: "slug",
|
||||
});
|
||||
const serviceAccount = this.host.state["serviceAccount"] as UserServiceAccountResponse;
|
||||
const req: LDAPProviderRequest = {
|
||||
name: name,
|
||||
authorizationFlow: flows.results[0].pk,
|
||||
baseDn: data.baseDN as string,
|
||||
searchGroup: serviceAccount.groupPk,
|
||||
};
|
||||
const provider = await new ProvidersApi(DEFAULT_CONFIG).providersLdapCreate({
|
||||
lDAPProviderRequest: req,
|
||||
});
|
||||
this.host.state["provider"] = provider;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
const domainParts = window.location.hostname.split(".");
|
||||
const defaultBaseDN = domainParts.map((part) => `dc=${part}`).join(",");
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-form-element-horizontal label=${t`Base DN`} name="baseDN" ?required=${true}>
|
||||
<input type="text" value="${defaultBaseDN}" class="pf-c-form-control" required />
|
||||
</ak-form-element-horizontal>
|
||||
</form> `;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
@customElement("ak-application-wizard-type-link")
|
||||
export class TypeLinkApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`Application Link`;
|
||||
|
||||
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
|
||||
this.host.state["link"] = data.link;
|
||||
return true;
|
||||
};
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
return html`
|
||||
<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-form-element-horizontal label=${t`Link`} ?required=${true} name="link">
|
||||
<input type="text" value="" class="pf-c-form-control" required />
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`URL which will be opened when a user clicks on the application.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</form>
|
||||
`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
|
||||
import AKGlobal from "@goauthentik/common/styles/authentik.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
@customElement("ak-application-wizard-type-oauth-api")
|
||||
export class TypeOAuthAPIApplicationWizardPage extends WizardPage {
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFButton, PFForm, PFRadio, AKGlobal];
|
||||
}
|
||||
|
||||
sidebarLabel = () => t`Method details`;
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
<p>
|
||||
${t`This configuration can be used to authenticate to authentik with other APIs other otherwise programmatically.`}
|
||||
</p>
|
||||
<p>
|
||||
${t`By default, all service accounts can authenticate as this application, as long as they have a valid token of the type app-password.`}
|
||||
</p>
|
||||
</form> `;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
|
||||
import AKGlobal from "@goauthentik/common/styles/authentik.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { TypeCreate } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type-oauth")
|
||||
export class TypeOAuthApplicationWizardPage extends WizardPage {
|
||||
applicationTypes: TypeCreate[] = [
|
||||
{
|
||||
component: "ak-application-wizard-type-oauth-code",
|
||||
name: t`Web application`,
|
||||
description: t`Applications which handle the authentication server-side (for example, Python, Go, Rust, Java, PHP)`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-oauth-implicit",
|
||||
name: t`Single-page applications`,
|
||||
description: t`Single-page applications which handle authentication in the browser (for example, Javascript, Angular, React, Vue)`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-oauth-implicit",
|
||||
name: t`Native application`,
|
||||
description: t`Applications which redirect users to a non-web callback (for example, Android, iOS)`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-oauth-api",
|
||||
name: t`API`,
|
||||
description: t`Authentication without user interaction, or machine-to-machine authentication.`,
|
||||
modelName: "",
|
||||
},
|
||||
];
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFButton, PFForm, PFRadio, AKGlobal];
|
||||
}
|
||||
|
||||
sidebarLabel = () => t`Application type`;
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
${this.applicationTypes.map((type) => {
|
||||
return html`<div class="pf-c-radio">
|
||||
<input
|
||||
class="pf-c-radio__input"
|
||||
type="radio"
|
||||
name="type"
|
||||
id=${type.component}
|
||||
@change=${() => {
|
||||
this.host.steps = [
|
||||
"ak-application-wizard-initial",
|
||||
"ak-application-wizard-type",
|
||||
"ak-application-wizard-type-oauth",
|
||||
type.component,
|
||||
];
|
||||
this.host.state["oauth-type"] = type.component;
|
||||
this.host.isValid = true;
|
||||
}}
|
||||
/>
|
||||
<label class="pf-c-radio__label" for=${type.component}>${type.name}</label>
|
||||
<span class="pf-c-radio__description">${type.description}</span>
|
||||
</div>`;
|
||||
})}
|
||||
</form> `;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
import "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
import { until } from "lit/directives/until.js";
|
||||
|
||||
import {
|
||||
ClientTypeEnum,
|
||||
FlowsApi,
|
||||
FlowsInstancesListDesignationEnum,
|
||||
OAuth2ProviderRequest,
|
||||
ProvidersApi,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type-oauth-code")
|
||||
export class TypeOAuthCodeApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`Method details`;
|
||||
|
||||
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
|
||||
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => {
|
||||
const req: OAuth2ProviderRequest = {
|
||||
name: this.host.state["name"] as string,
|
||||
clientType: ClientTypeEnum.Confidential,
|
||||
authorizationFlow: data.authorizationFlow as string,
|
||||
};
|
||||
const provider = await new ProvidersApi(DEFAULT_CONFIG).providersOauth2Create({
|
||||
oAuth2ProviderRequest: req,
|
||||
});
|
||||
this.host.state["provider"] = provider;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-form-element-horizontal
|
||||
label=${t`Authorization flow`}
|
||||
?required=${true}
|
||||
name="authorizationFlow"
|
||||
>
|
||||
<select class="pf-c-form-control">
|
||||
${until(
|
||||
new FlowsApi(DEFAULT_CONFIG)
|
||||
.flowsInstancesList({
|
||||
ordering: "slug",
|
||||
designation: FlowsInstancesListDesignationEnum.Authorization,
|
||||
})
|
||||
.then((flows) => {
|
||||
return flows.results.map((flow) => {
|
||||
return html`<option value=${ifDefined(flow.pk)}>
|
||||
${flow.name} (${flow.slug})
|
||||
</option>`;
|
||||
});
|
||||
}),
|
||||
html`<option>${t`Loading...`}</option>`,
|
||||
)}
|
||||
</select>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`Flow used when users access this application.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</form>`;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
@customElement("ak-application-wizard-type-oauth-implicit")
|
||||
export class TypeOAuthImplicitApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`Method details`;
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">some stuff idk</form> `;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
import {
|
||||
FlowDesignationEnum,
|
||||
FlowsApi,
|
||||
ProvidersApi,
|
||||
ProxyProviderRequest,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type-proxy")
|
||||
export class TypeProxyApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`Proxy details`;
|
||||
|
||||
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
|
||||
let name = this.host.state["name"] as string;
|
||||
// Check if a provider with the name already exists
|
||||
const providers = await new ProvidersApi(DEFAULT_CONFIG).providersAllList({
|
||||
search: name,
|
||||
});
|
||||
if (providers.results.filter((provider) => provider.name == name)) {
|
||||
name += "-1";
|
||||
}
|
||||
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => {
|
||||
// Get all flows and default to the implicit authorization
|
||||
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
|
||||
designation: FlowDesignationEnum.Authorization,
|
||||
ordering: "slug",
|
||||
});
|
||||
const req: ProxyProviderRequest = {
|
||||
name: name,
|
||||
authorizationFlow: flows.results[0].pk,
|
||||
externalHost: data.externalHost as string,
|
||||
};
|
||||
const provider = await new ProvidersApi(DEFAULT_CONFIG).providersProxyCreate({
|
||||
proxyProviderRequest: req,
|
||||
});
|
||||
this.host.state["provider"] = provider;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-form-element-horizontal
|
||||
label=${t`External domain`}
|
||||
name="externalHost"
|
||||
?required=${true}
|
||||
>
|
||||
<input type="text" value="" class="pf-c-form-control" required />
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`External domain you will be accessing the domain from.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</form> `;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardPage } from "@goauthentik/elements/wizard/WizardPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
|
||||
import AKGlobal from "@goauthentik/common/styles/authentik.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { TypeCreate } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type-saml")
|
||||
export class TypeOAuthApplicationWizardPage extends WizardPage {
|
||||
applicationTypes: TypeCreate[] = [
|
||||
{
|
||||
component: "ak-application-wizard-type-saml-import",
|
||||
name: t`Import SAML Metadata`,
|
||||
description: t`Import the metadata document of the applicaation you want to configure.`,
|
||||
modelName: "",
|
||||
},
|
||||
{
|
||||
component: "ak-application-wizard-type-saml-config",
|
||||
name: t`Manual configuration`,
|
||||
description: t`Manually configure SAML`,
|
||||
modelName: "",
|
||||
},
|
||||
];
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [PFBase, PFButton, PFForm, PFRadio, AKGlobal];
|
||||
}
|
||||
|
||||
sidebarLabel = () => t`Application type`;
|
||||
|
||||
render(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
${this.applicationTypes.map((type) => {
|
||||
return html`<div class="pf-c-radio">
|
||||
<input
|
||||
class="pf-c-radio__input"
|
||||
type="radio"
|
||||
name="type"
|
||||
id=${type.component}
|
||||
@change=${() => {
|
||||
this.host.steps = [
|
||||
"ak-application-wizard-initial",
|
||||
"ak-application-wizard-type",
|
||||
"ak-application-wizard-type-saml",
|
||||
type.component,
|
||||
];
|
||||
this.host.state["saml-type"] = type.component;
|
||||
this.host.isValid = true;
|
||||
}}
|
||||
/>
|
||||
<label class="pf-c-radio__label" for=${type.component}>${type.name}</label>
|
||||
<span class="pf-c-radio__description">${type.description}</span>
|
||||
</div>`;
|
||||
})}
|
||||
</form> `;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
import { FlowDesignationEnum, FlowsApi, ProvidersApi, SAMLProviderRequest } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type-saml-config")
|
||||
export class TypeSAMLApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`SAML details`;
|
||||
|
||||
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
|
||||
let name = this.host.state["name"] as string;
|
||||
// Check if a provider with the name already exists
|
||||
const providers = await new ProvidersApi(DEFAULT_CONFIG).providersAllList({
|
||||
search: name,
|
||||
});
|
||||
if (providers.results.filter((provider) => provider.name == name)) {
|
||||
name += "-1";
|
||||
}
|
||||
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => {
|
||||
// Get all flows and default to the implicit authorization
|
||||
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
|
||||
designation: FlowDesignationEnum.Authorization,
|
||||
ordering: "slug",
|
||||
});
|
||||
const req: SAMLProviderRequest = {
|
||||
name: name,
|
||||
authorizationFlow: flows.results[0].pk,
|
||||
acsUrl: data.acsUrl as string,
|
||||
};
|
||||
const provider = await new ProvidersApi(DEFAULT_CONFIG).providersSamlCreate({
|
||||
sAMLProviderRequest: req,
|
||||
});
|
||||
this.host.state["provider"] = provider;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-form-element-horizontal label=${t`ACS URL`} name="acsUrl" ?required=${true}>
|
||||
<input type="text" value="" class="pf-c-form-control" required />
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`URL that authentik will redirect back to after successful authentication.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</form> `;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { KeyUnknown } from "@goauthentik/elements/forms/Form";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { WizardFormPage } from "@goauthentik/elements/wizard/WizardFormPage";
|
||||
|
||||
import { t } from "@lingui/macro";
|
||||
|
||||
import { customElement } from "@lit/reactive-element/decorators/custom-element.js";
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
import {
|
||||
FlowDesignationEnum,
|
||||
FlowsApi,
|
||||
ProvidersApi,
|
||||
ProvidersSamlImportMetadataCreateRequest,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-application-wizard-type-saml-import")
|
||||
export class TypeSAMLImportApplicationWizardPage extends WizardFormPage {
|
||||
sidebarLabel = () => t`Import SAML metadata`;
|
||||
|
||||
nextDataCallback = async (data: KeyUnknown): Promise<boolean> => {
|
||||
let name = this.host.state["name"] as string;
|
||||
// Check if a provider with the name already exists
|
||||
const providers = await new ProvidersApi(DEFAULT_CONFIG).providersAllList({
|
||||
search: name,
|
||||
});
|
||||
if (providers.results.filter((provider) => provider.name == name)) {
|
||||
name += "-1";
|
||||
}
|
||||
this.host.addActionBefore(t`Create provider`, async (): Promise<boolean> => {
|
||||
// Get all flows and default to the implicit authorization
|
||||
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
|
||||
designation: FlowDesignationEnum.Authorization,
|
||||
ordering: "slug",
|
||||
});
|
||||
const req: ProvidersSamlImportMetadataCreateRequest = {
|
||||
name: name,
|
||||
authorizationFlow: flows.results[0].slug,
|
||||
file: data["metadata"] as Blob,
|
||||
};
|
||||
const provider = await new ProvidersApi(
|
||||
DEFAULT_CONFIG,
|
||||
).providersSamlImportMetadataCreate(req);
|
||||
this.host.state["provider"] = provider;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
renderForm(): TemplateResult {
|
||||
return html`<form class="pf-c-form pf-m-horizontal">
|
||||
<ak-form-element-horizontal label=${t`Metadata`} name="metadata">
|
||||
<input type="file" value="" class="pf-c-form-control" />
|
||||
</ak-form-element-horizontal>
|
||||
</form> `;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user