web: re-format with prettier

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer
2021-08-03 17:52:21 +02:00
parent 77ed25ae34
commit 2c60ec50be
218 changed files with 11696 additions and 8225 deletions

View File

@ -58,88 +58,76 @@ export class ProviderListPage extends TablePage<Provider> {
row(item: Provider): TemplateResult[] {
return [
html`<a href="#/core/providers/${item.pk}">
${item.name}
</a>`,
item.assignedApplicationName ?
html`<i class="pf-icon pf-icon-ok pf-m-success"></i>
${t`Assigned to application `}
<a href="#/core/applications/${item.assignedApplicationSlug}">${item.assignedApplicationName}</a>` :
html`<i class="pf-icon pf-icon-warning-triangle pf-m-warning"></i>
${t`Warning: Provider not assigned to any application.`}`,
html`<a href="#/core/providers/${item.pk}"> ${item.name} </a>`,
item.assignedApplicationName
? html`<i class="pf-icon pf-icon-ok pf-m-success"></i>
${t`Assigned to application `}
<a href="#/core/applications/${item.assignedApplicationSlug}"
>${item.assignedApplicationName}</a
>`
: html`<i class="pf-icon pf-icon-warning-triangle pf-m-warning"></i>
${t`Warning: Provider not assigned to any application.`}`,
html`${item.verboseName}`,
html`
<ak-forms-modal>
<span slot="submit">
${t`Update`}
</span>
<span slot="header">
${t`Update ${item.verboseName}`}
</span>
<ak-proxy-form
slot="form"
.args=${{
"instancePk": item.pk
html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span>
<span slot="header"> ${t`Update ${item.verboseName}`} </span>
<ak-proxy-form
slot="form"
.args=${{
instancePk: item.pk,
}}
type=${ifDefined(item.component)}
>
</ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary">${t`Edit`}</button>
</ak-forms-modal>
<ak-forms-delete
.obj=${item}
objectLabel=${t`Provider`}
.usedBy=${() => {
return new ProvidersApi(DEFAULT_CONFIG).providersAllUsedByList({
id: item.pk,
});
}}
type=${ifDefined(item.component)}>
</ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`}
</button>
</ak-forms-modal>
<ak-forms-delete
.obj=${item}
objectLabel=${t`Provider`}
.usedBy=${() => {
return new ProvidersApi(DEFAULT_CONFIG).providersAllUsedByList({
id: item.pk
});
}}
.delete=${() => {
return new ProvidersApi(DEFAULT_CONFIG).providersAllDestroy({
id: item.pk
});
}}>
<button slot="trigger" class="pf-c-button pf-m-danger">
${t`Delete`}
</button>
</ak-forms-delete>`,
.delete=${() => {
return new ProvidersApi(DEFAULT_CONFIG).providersAllDestroy({
id: item.pk,
});
}}
>
<button slot="trigger" class="pf-c-button pf-m-danger">${t`Delete`}</button>
</ak-forms-delete>`,
];
}
renderToolbar(): TemplateResult {
return html`
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${t`Create`}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
${until(new ProvidersApi(DEFAULT_CONFIG).providersAllTypesList().then((types) => {
return types.map((type) => {
return html`<li>
<ak-forms-modal>
<span slot="submit">
${t`Create`}
</span>
<span slot="header">
${t`Create ${type.name}`}
</span>
<ak-proxy-form
slot="form"
type=${type.component}>
</ak-proxy-form>
<button slot="trigger" class="pf-c-dropdown__menu-item">
${type.name}<br>
<small>${type.description}</small>
</button>
</ak-forms-modal>
</li>`;
});
}), html`<ak-spinner></ak-spinner>`)}
</ul>
</ak-dropdown>
${super.renderToolbar()}`;
return html` <ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${t`Create`}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
${until(
new ProvidersApi(DEFAULT_CONFIG).providersAllTypesList().then((types) => {
return types.map((type) => {
return html`<li>
<ak-forms-modal>
<span slot="submit"> ${t`Create`} </span>
<span slot="header"> ${t`Create ${type.name}`} </span>
<ak-proxy-form slot="form" type=${type.component}>
</ak-proxy-form>
<button slot="trigger" class="pf-c-dropdown__menu-item">
${type.name}<br />
<small>${type.description}</small>
</button>
</ak-forms-modal>
</li>`;
});
}),
html`<ak-spinner></ak-spinner>`,
)}
</ul>
</ak-dropdown>
${super.renderToolbar()}`;
}
}

View File

@ -14,12 +14,13 @@ import { ifDefined } from "lit-html/directives/if-defined";
@customElement("ak-provider-view")
export class ProviderViewPage extends LitElement {
@property({type: Number})
@property({ type: Number })
set providerID(value: number) {
new ProvidersApi(DEFAULT_CONFIG).providersAllRetrieve({
id: value,
}).then((prov) => (this.provider = prov));
new ProvidersApi(DEFAULT_CONFIG)
.providersAllRetrieve({
id: value,
})
.then((prov) => (this.provider = prov));
}
@property({ attribute: false })
@ -31,13 +32,21 @@ export class ProviderViewPage extends LitElement {
}
switch (this.provider?.component) {
case "ak-provider-saml-form":
return html`<ak-provider-saml-view providerID=${ifDefined(this.provider.pk)}></ak-provider-saml-view>`;
return html`<ak-provider-saml-view
providerID=${ifDefined(this.provider.pk)}
></ak-provider-saml-view>`;
case "ak-provider-oauth2-form":
return html`<ak-provider-oauth2-view providerID=${ifDefined(this.provider.pk)}></ak-provider-oauth2-view>`;
return html`<ak-provider-oauth2-view
providerID=${ifDefined(this.provider.pk)}
></ak-provider-oauth2-view>`;
case "ak-provider-proxy-form":
return html`<ak-provider-proxy-view providerID=${ifDefined(this.provider.pk)}></ak-provider-proxy-view>`;
return html`<ak-provider-proxy-view
providerID=${ifDefined(this.provider.pk)}
></ak-provider-proxy-view>`;
case "ak-provider-ldap-form":
return html`<ak-provider-ldap-view providerID=${ifDefined(this.provider.pk)}></ak-provider-ldap-view>`;
return html`<ak-provider-ldap-view
providerID=${ifDefined(this.provider.pk)}
></ak-provider-ldap-view>`;
default:
return html`<p>Invalid provider type ${this.provider?.component}</p>`;
}
@ -45,10 +54,11 @@ export class ProviderViewPage extends LitElement {
render(): TemplateResult {
return html`<ak-page-header
icon="pf-icon pf-icon-integration"
header=${ifDefined(this.provider?.name)}
description=${ifDefined(this.provider?.verboseName)}>
</ak-page-header>
${this.renderProvider()}`;
icon="pf-icon pf-icon-integration"
header=${ifDefined(this.provider?.name)}
description=${ifDefined(this.provider?.verboseName)}
>
</ak-page-header>
${this.renderProvider()}`;
}
}

View File

@ -10,12 +10,11 @@ import "../../pages/applications/ApplicationForm";
@customElement("ak-provider-related-application")
export class RelatedApplicationButton extends LitElement {
static get styles(): CSSResult[] {
return [PFBase, PFButton];
}
@property({attribute: false})
@property({ attribute: false })
provider?: Provider;
render(): TemplateResult {
@ -25,18 +24,10 @@ export class RelatedApplicationButton extends LitElement {
</a>`;
}
return html`<ak-forms-modal>
<span slot="submit">
${t`Create`}
</span>
<span slot="header">
${t`Create Application`}
</span>
<ak-application-form slot="form" .provider=${this.provider?.pk}>
</ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Create`}
</button>
<span slot="submit"> ${t`Create`} </span>
<span slot="header"> ${t`Create Application`} </span>
<ak-application-form slot="form" .provider=${this.provider?.pk}> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${t`Create`}</button>
</ak-forms-modal>`;
}
}

View File

@ -1,4 +1,11 @@
import { FlowsApi, ProvidersApi, LDAPProvider, CoreApi, FlowsInstancesListDesignationEnum, CryptoApi } from "authentik-api";
import {
FlowsApi,
ProvidersApi,
LDAPProvider,
CoreApi,
FlowsInstancesListDesignationEnum,
CryptoApi,
} from "authentik-api";
import { t } from "@lingui/macro";
import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html";
@ -12,7 +19,6 @@ import { first } from "../../../utils";
@customElement("ak-provider-ldap-form")
export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
loadInstance(pk: number): Promise<LDAPProvider> {
return new ProvidersApi(DEFAULT_CONFIG).providersLdapRetrieve({
id: pk,
@ -31,109 +37,165 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersLdapUpdate({
id: this.instance.pk || 0,
lDAPProviderRequest: data
lDAPProviderRequest: data,
});
} else {
return new ProvidersApi(DEFAULT_CONFIG).providersLdapCreate({
lDAPProviderRequest: data
lDAPProviderRequest: data,
});
}
};
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="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
<input
type="text"
value="${ifDefined(this.instance?.name)}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Bind flow`}
?required=${true}
name="authorizationFlow">
name="authorizationFlow"
>
<select class="pf-c-form-control">
${until(tenant().then(t => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authentication,
}).then(flows => {
return flows.results.map(flow => {
let selected = flow.pk === t.flowAuthentication;
if (this.instance?.authorizationFlow === flow.pk) {
selected = true;
}
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
});
});
}), html`<option>${t`Loading...`}</option>`)}
${until(
tenant().then((t) => {
return new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authentication,
})
.then((flows) => {
return flows.results.map((flow) => {
let selected = flow.pk === t.flowAuthentication;
if (this.instance?.authorizationFlow === flow.pk) {
selected = true;
}
return html`<option
value=${ifDefined(flow.pk)}
?selected=${selected}
>
${flow.name} (${flow.slug})
</option>`;
});
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Flow used for users to authenticate. Currently only identification and password stages are supported.`}</p>
<p class="pf-c-form__helper-text">
${t`Flow used for users to authenticate. Currently only identification and password stages are supported.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Group`}
name="searchGroup">
<ak-form-element-horizontal label=${t`Group`} name="searchGroup">
<select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.searchGroup === undefined}>---------</option>
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => {
return groups.results.map(group => {
return html`<option value=${ifDefined(group.pk)} ?selected=${this.instance?.searchGroup === group.pk}>${group.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
<option value="" ?selected=${this.instance?.searchGroup === undefined}>
---------
</option>
${until(
new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then((groups) => {
return groups.results.map((group) => {
return html`<option
value=${ifDefined(group.pk)}
?selected=${this.instance?.searchGroup === group.pk}
>
${group.name}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed.`}</p>
<p class="pf-c-form__helper-text">
${t`Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed.`}
</p>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}>
<span slot="header">
${t`Protocol settings`}
</span>
<span slot="header"> ${t`Protocol settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Base DN`}
?required=${true}
name="baseDn">
<input type="text" value="${first(this.instance?.baseDn, "DC=ldap,DC=goauthentik,DC=io")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`LDAP DN under which bind requests and search requests can be made.`}</p>
<ak-form-element-horizontal label=${t`Base DN`} ?required=${true} name="baseDn">
<input
type="text"
value="${first(this.instance?.baseDn, "DC=ldap,DC=goauthentik,DC=io")}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`LDAP DN under which bind requests and search requests can be made.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`TLS Server name`}
name="tlsServerName">
<input type="text" value="${first(this.instance?.tlsServerName, "")}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`Server name for which this provider's certificate is valid for.`}</p>
<ak-form-element-horizontal label=${t`TLS Server name`} name="tlsServerName">
<input
type="text"
value="${first(this.instance?.tlsServerName, "")}"
class="pf-c-form-control"
/>
<p class="pf-c-form__helper-text">
${t`Server name for which this provider's certificate is valid for.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Certificate`}
name="certificate">
<ak-form-element-horizontal label=${t`Certificate`} name="certificate">
<select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.certificate === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
}).then(keys => {
return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.certificate === key.pk}>${key.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
<option value="" ?selected=${this.instance?.certificate === undefined}>
---------
</option>
${until(
new CryptoApi(DEFAULT_CONFIG)
.cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
})
.then((keys) => {
return keys.results.map((key) => {
return html`<option
value=${ifDefined(key.pk)}
?selected=${this.instance?.certificate === key.pk}
>
${key.name}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`UID start number`}
?required=${true}
name="uidStartNumber">
<input type="number" value="${first(this.instance?.uidStartNumber, 2000)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber`}</p>
name="uidStartNumber"
>
<input
type="number"
value="${first(this.instance?.uidStartNumber, 2000)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`GID start number`}
?required=${true}
name="gidStartNumber">
<input type="number" value="${first(this.instance?.gidStartNumber, 4000)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber`}</p>
name="gidStartNumber"
>
<input
type="number"
value="${first(this.instance?.gidStartNumber, 4000)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber`}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
</form>`;
}
}

View File

@ -25,24 +25,37 @@ import { EVENT_REFRESH } from "../../../constants";
@customElement("ak-provider-ldap-view")
export class LDAPProviderViewPage extends LitElement {
@property()
set args(value: { [key: string]: number }) {
this.providerID = value.id;
}
@property({type: Number})
@property({ type: Number })
set providerID(value: number) {
new ProvidersApi(DEFAULT_CONFIG).providersLdapRetrieve({
id: value,
}).then((prov) => (this.provider = prov));
new ProvidersApi(DEFAULT_CONFIG)
.providersLdapRetrieve({
id: value,
})
.then((prov) => (this.provider = prov));
}
@property({ attribute: false })
provider?: LDAPProvider;
static get styles(): CSSResult[] {
return [PFBase, PFButton, PFPage, PFFlex, PFDisplay, PFGallery, PFContent, PFCard, PFDescriptionList, PFSizing, AKGlobal];
return [
PFBase,
PFButton,
PFPage,
PFFlex,
PFDisplay,
PFGallery,
PFContent,
PFCard,
PFDescriptionList,
PFSizing,
AKGlobal,
];
}
constructor() {
@ -58,72 +71,90 @@ export class LDAPProviderViewPage extends LitElement {
return html``;
}
return html`<ak-tabs>
<section slot="page-overview" data-tab-title="${t`Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.name}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Assigned to application`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application .provider=${this.provider}></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Base DN`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.baseDn}</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit">
${t`Update`}
</span>
<span slot="header">
${t`Update LDAP Provider`}
</span>
<ak-provider-ldap-form
slot="form"
.instancePk=${this.provider.pk}>
</ak-provider-ldap-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
<section
slot="page-overview"
data-tab-title="${t`Overview`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Name`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.name}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Assigned to application`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application
.provider=${this.provider}
></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Base DN`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.baseDn}
</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span>
<span slot="header"> ${t`Update LDAP Provider`} </span>
<ak-provider-ldap-form
slot="form"
.instancePk=${this.provider.pk}
>
</ak-provider-ldap-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
</div>
</div>
</section>
<section slot="page-changelog" data-tab-title="${t`Changelog`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_ldap"
targetModelName="LDAPProvider">
</ak-object-changelog>
</div>
</div>
</section>
<section
slot="page-changelog"
data-tab-title="${t`Changelog`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_ldap"
targetModelName="LDAPProvider"
>
</ak-object-changelog>
</div>
</section>
</ak-tabs>`;
</div>
</section>
</ak-tabs>`;
}
}

View File

@ -1,4 +1,15 @@
import { CryptoApi, FlowsApi, OAuth2Provider, ClientTypeEnum, IssuerModeEnum, JwtAlgEnum, SubModeEnum, PropertymappingsApi, ProvidersApi, FlowsInstancesListDesignationEnum } from "authentik-api";
import {
CryptoApi,
FlowsApi,
OAuth2Provider,
ClientTypeEnum,
IssuerModeEnum,
JwtAlgEnum,
SubModeEnum,
PropertymappingsApi,
ProvidersApi,
FlowsInstancesListDesignationEnum,
} from "authentik-api";
import { t } from "@lingui/macro";
import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html";
@ -12,17 +23,18 @@ import { first, randomString } from "../../../utils";
@customElement("ak-provider-oauth2-form")
export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
loadInstance(pk: number): Promise<OAuth2Provider> {
return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Retrieve({
id: pk,
}).then(provider => {
this.showClientSecret = provider.clientType === ClientTypeEnum.Confidential;
return provider;
});
return new ProvidersApi(DEFAULT_CONFIG)
.providersOauth2Retrieve({
id: pk,
})
.then((provider) => {
this.showClientSecret = provider.clientType === ClientTypeEnum.Confidential;
return provider;
});
}
@property({type: Boolean})
@property({ type: Boolean })
showClientSecret = true;
getSuccessMessage(): string {
@ -37,82 +49,122 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Update({
id: this.instance.pk || 0,
oAuth2ProviderRequest: data
oAuth2ProviderRequest: data,
});
} else {
return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Create({
oAuth2ProviderRequest: data
oAuth2ProviderRequest: data,
});
}
};
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="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
<input
type="text"
value="${ifDefined(this.instance?.name)}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Authorization flow`}
?required=${true}
name="authorizationFlow">
name="authorizationFlow"
>
<select class="pf-c-form-control">
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
}).then(flows => {
return flows.results.map(flow => {
return html`<option value=${ifDefined(flow.pk)} ?selected=${this.instance?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
${until(
new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
})
.then((flows) => {
return flows.results.map((flow) => {
return html`<option
value=${ifDefined(flow.pk)}
?selected=${this.instance?.authorizationFlow === flow.pk}
>
${flow.name} (${flow.slug})
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Flow used when authorizing this provider.`}</p>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
</p>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}>
<span slot="header">
${t`Protocol settings`}
</span>
<span slot="header"> ${t`Protocol settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Client type`}
?required=${true}
name="clientType">
<select class="pf-c-form-control" @change=${(ev: Event) => {
const target = ev.target as HTMLSelectElement;
if (target.selectedOptions[0].value === ClientTypeEnum.Public) {
this.showClientSecret = false;
} else {
this.showClientSecret = true;
}
}}>
<option value=${ClientTypeEnum.Confidential} ?selected=${this.instance?.clientType === ClientTypeEnum.Confidential}>
name="clientType"
>
<select
class="pf-c-form-control"
@change=${(ev: Event) => {
const target = ev.target as HTMLSelectElement;
if (target.selectedOptions[0].value === ClientTypeEnum.Public) {
this.showClientSecret = false;
} else {
this.showClientSecret = true;
}
}}
>
<option
value=${ClientTypeEnum.Confidential}
?selected=${this.instance?.clientType ===
ClientTypeEnum.Confidential}
>
${t`Confidential`}
</option>
<option value=${ClientTypeEnum.Public} ?selected=${this.instance?.clientType === ClientTypeEnum.Public}>
<option
value=${ClientTypeEnum.Public}
?selected=${this.instance?.clientType === ClientTypeEnum.Public}
>
${t`Public`}
</option>
</select>
<p class="pf-c-form__helper-text">${t`Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable.`}</p>
<p class="pf-c-form__helper-text">
${t`Confidential clients are capable of maintaining the confidentiality of their credentials. Public clients are incapable.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Client ID`}
?required=${true}
name="clientId">
<input type="text" value="${first(this.instance?.clientId, randomString(40))}" class="pf-c-form-control" required>
name="clientId"
>
<input
type="text"
value="${first(this.instance?.clientId, randomString(40))}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
?hidden=${!this.showClientSecret}
label=${t`Client Secret`}
name="clientSecret">
<input type="text" value="${first(this.instance?.clientSecret, randomString(128))}" class="pf-c-form-control">
name="clientSecret"
>
<input
type="text"
value="${first(this.instance?.clientSecret, randomString(128))}"
class="pf-c-form-control"
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Redirect URIs/Origins`}
name="redirectUris">
<textarea class="pf-c-form-control">${this.instance?.redirectUris}</textarea>
name="redirectUris"
>
<textarea class="pf-c-form-control">
${this.instance?.redirectUris}</textarea
>
<p class="pf-c-form__helper-text">
${t`Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.`}
</p>
@ -124,98 +176,167 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
</ak-form-group>
<ak-form-group>
<span slot="header">
${t`Advanced protocol settings`}
</span>
<span slot="header"> ${t`Advanced protocol settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Access code validity`}
?required=${true}
name="accessCodeValidity">
<input type="text" value="${first(this.instance?.accessCodeValidity, "minutes=1")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Configure how long access codes are valid for.`}</p>
<p class="pf-c-form__helper-text">${t`(Format: hours=-1;minutes=-2;seconds=-3).`}</p>
name="accessCodeValidity"
>
<input
type="text"
value="${first(this.instance?.accessCodeValidity, "minutes=1")}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`Configure how long access codes are valid for.`}
</p>
<p class="pf-c-form__helper-text">
${t`(Format: hours=-1;minutes=-2;seconds=-3).`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Token validity`}
?required=${true}
name="tokenValidity">
<input type="text" value="${first(this.instance?.tokenValidity, "minutes=10")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Configure how long refresh tokens and their id_tokens are valid for.`}</p>
<p class="pf-c-form__helper-text">${t`(Format: hours=-1;minutes=-2;seconds=-3).`}</p>
name="tokenValidity"
>
<input
type="text"
value="${first(this.instance?.tokenValidity, "minutes=10")}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`Configure how long refresh tokens and their id_tokens are valid for.`}
</p>
<p class="pf-c-form__helper-text">
${t`(Format: hours=-1;minutes=-2;seconds=-3).`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`JWT Algorithm`}
?required=${true}
name="jwtAlg">
name="jwtAlg"
>
<select class="pf-c-form-control">
<option value=${JwtAlgEnum.Rs256} ?selected=${this.instance?.jwtAlg === JwtAlgEnum.Rs256}>
<option
value=${JwtAlgEnum.Rs256}
?selected=${this.instance?.jwtAlg === JwtAlgEnum.Rs256}
>
${t`RS256 (Asymmetric Encryption)`}
</option>
<option value=${JwtAlgEnum.Hs256} ?selected=${this.instance?.jwtAlg === JwtAlgEnum.Hs256}>
<option
value=${JwtAlgEnum.Hs256}
?selected=${this.instance?.jwtAlg === JwtAlgEnum.Hs256}
>
${t`HS256 (Symmetric Encryption)`}
</option>
</select>
<p class="pf-c-form__helper-text">${t`Algorithm used to sign the JWT Tokens.`}</p>
<p class="pf-c-form__helper-text">
${t`Algorithm used to sign the JWT Tokens.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Scopes`}
name="propertyMappings">
<ak-form-element-horizontal label=${t`Scopes`} name="propertyMappings">
<select class="pf-c-form-control" multiple>
${until(new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsScopeList({
ordering: "scope_name"
}).then(scopes => {
return scopes.results.map(scope => {
let selected = false;
if (!this.instance?.propertyMappings) {
selected = scope.managed?.startsWith("goauthentik.io/providers/oauth2/scope-") || false;
} else {
selected = Array.from(this.instance?.propertyMappings).some(su => {
return su == scope.pk;
${until(
new PropertymappingsApi(DEFAULT_CONFIG)
.propertymappingsScopeList({
ordering: "scope_name",
})
.then((scopes) => {
return scopes.results.map((scope) => {
let selected = false;
if (!this.instance?.propertyMappings) {
selected =
scope.managed?.startsWith(
"goauthentik.io/providers/oauth2/scope-",
) || false;
} else {
selected = Array.from(
this.instance?.propertyMappings,
).some((su) => {
return su == scope.pk;
});
}
return html`<option
value=${ifDefined(scope.pk)}
?selected=${selected}
>
${scope.name}
</option>`;
});
}
return html`<option value=${ifDefined(scope.pk)} ?selected=${selected}>${scope.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Select which scopes can be used by the client. The client stil has to specify the scope to access the data.`}</p>
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
<p class="pf-c-form__helper-text">
${t`Select which scopes can be used by the client. The client stil has to specify the scope to access the data.`}
</p>
<p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`RSA Key`}
name="rsaKey">
<ak-form-element-horizontal label=${t`RSA Key`} name="rsaKey">
<select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.rsaKey === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
}).then(keys => {
return keys.results.map(key => {
let selected = this.instance?.rsaKey === key.pk;
if (keys.results.length === 1) {
selected = true;
}
return html`<option value=${ifDefined(key.pk)} ?selected=${selected}>${key.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
<option value="" ?selected=${this.instance?.rsaKey === undefined}>
---------
</option>
${until(
new CryptoApi(DEFAULT_CONFIG)
.cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
})
.then((keys) => {
return keys.results.map((key) => {
let selected = this.instance?.rsaKey === key.pk;
if (keys.results.length === 1) {
selected = true;
}
return html`<option
value=${ifDefined(key.pk)}
?selected=${selected}
>
${key.name}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Key used to sign the tokens. Only required when JWT Algorithm is set to RS256.`}</p>
<p class="pf-c-form__helper-text">
${t`Key used to sign the tokens. Only required when JWT Algorithm is set to RS256.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Subject mode`}
?required=${true}
name="subMode">
name="subMode"
>
<select class="pf-c-form-control">
<option value="${SubModeEnum.HashedUserId}" ?selected=${this.instance?.subMode === SubModeEnum.HashedUserId}>
<option
value="${SubModeEnum.HashedUserId}"
?selected=${this.instance?.subMode === SubModeEnum.HashedUserId}
>
${t`Based on the Hashed User ID`}
</option>
<option value="${SubModeEnum.UserUsername}" ?selected=${this.instance?.subMode === SubModeEnum.UserUsername}>
<option
value="${SubModeEnum.UserUsername}"
?selected=${this.instance?.subMode === SubModeEnum.UserUsername}
>
${t`Based on the username`}
</option>
<option value="${SubModeEnum.UserEmail}" ?selected=${this.instance?.subMode === SubModeEnum.UserEmail}>
<option
value="${SubModeEnum.UserEmail}"
?selected=${this.instance?.subMode === SubModeEnum.UserEmail}
>
${t`Based on the User's Email. This is recommended over the UPN method.`}
</option>
<option value="${SubModeEnum.UserUpn}" ?selected=${this.instance?.subMode === SubModeEnum.UserUpn}>
<option
value="${SubModeEnum.UserUpn}"
?selected=${this.instance?.subMode === SubModeEnum.UserUpn}
>
${t`Based on the User's UPN, only works if user has a 'upn' attribute set. Use this method only if you have different UPN and Mail domains.`}
</option>
</select>
@ -225,22 +346,36 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
</ak-form-element-horizontal>
<ak-form-element-horizontal name="includeClaimsInIdToken">
<div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.includeClaimsInIdToken, true)}>
<input
type="checkbox"
class="pf-c-check__input"
?checked=${first(this.instance?.includeClaimsInIdToken, true)}
/>
<label class="pf-c-check__label">
${t`Include claims in id_token`}
</label>
</div>
<p class="pf-c-form__helper-text">${t`Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.`}</p>
<p class="pf-c-form__helper-text">
${t`Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Issuer mode`}
?required=${true}
name="issuerMode">
name="issuerMode"
>
<select class="pf-c-form-control">
<option value="${IssuerModeEnum.PerProvider}" ?selected=${this.instance?.issuerMode === IssuerModeEnum.PerProvider}>
<option
value="${IssuerModeEnum.PerProvider}"
?selected=${this.instance?.issuerMode ===
IssuerModeEnum.PerProvider}
>
${t`Each provider has a different issuer, based on the application slug.`}
</option>
<option value="${IssuerModeEnum.Global}" ?selected=${this.instance?.issuerMode === IssuerModeEnum.Global}>
<option
value="${IssuerModeEnum.Global}"
?selected=${this.instance?.issuerMode === IssuerModeEnum.Global}
>
${t`Same identifier is used for all providers`}
</option>
</select>
@ -252,5 +387,4 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
</ak-form-group>
</form>`;
}
}

View File

@ -28,17 +28,16 @@ import { EVENT_REFRESH } from "../../../constants";
@customElement("ak-provider-oauth2-view")
export class OAuth2ProviderViewPage extends LitElement {
@property({type: Number})
@property({ type: Number })
set providerID(value: number) {
const api = new ProvidersApi(DEFAULT_CONFIG);
api.providersOauth2Retrieve({
id: value
id: value,
}).then((prov) => {
this.provider = prov;
});
api.providersOauth2SetupUrlsRetrieve({
id: value
id: value,
}).then((prov) => {
this.providerUrls = prov;
});
@ -51,7 +50,21 @@ export class OAuth2ProviderViewPage extends LitElement {
providerUrls?: OAuth2ProviderSetupURLs;
static get styles(): CSSResult[] {
return [PFBase, PFButton, PFPage, PFFlex, PFDisplay, PFGallery, PFContent, PFCard, PFDescriptionList, PFSizing, PFForm, PFFormControl, AKGlobal];
return [
PFBase,
PFButton,
PFPage,
PFFlex,
PFDisplay,
PFGallery,
PFContent,
PFCard,
PFDescriptionList,
PFSizing,
PFForm,
PFFormControl,
AKGlobal,
];
}
constructor() {
@ -67,137 +80,227 @@ export class OAuth2ProviderViewPage extends LitElement {
return html``;
}
return html`<ak-tabs>
<section slot="page-overview" data-tab-title="${t`Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-2-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.name}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Assigned to application`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application .provider=${this.provider}></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Client type`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${convertToTitle(this.provider.clientType || "")}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Client ID`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.clientId}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Redirect URIs`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.redirectUris}</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit">
${t`Update`}
</span>
<span slot="header">
${t`Update OAuth2 Provider`}
</span>
<ak-provider-oauth2-form
slot="form"
.instancePk=${this.provider.pk || 0}>
</ak-provider-oauth2-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
<section
slot="page-overview"
data-tab-title="${t`Overview`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-2-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Name`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.name}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Assigned to application`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application
.provider=${this.provider}
></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Client type`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${convertToTitle(this.provider.clientType || "")}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Client ID`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.clientId}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Redirect URIs`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.redirectUris}
</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span>
<span slot="header"> ${t`Update OAuth2 Provider`} </span>
<ak-provider-oauth2-form
slot="form"
.instancePk=${this.provider.pk || 0}
>
</ak-provider-oauth2-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
</div>
</div>
</section>
<section slot="page-changelog" data-tab-title="${t`Changelog`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_oauth2"
targetModelName="oauth2provider">
</ak-object-changelog>
</div>
</div>
</section>
<section
slot="page-changelog"
data-tab-title="${t`Changelog`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_oauth2"
targetModelName="oauth2provider"
>
</ak-object-changelog>
</div>
</section>
<section slot="page-metadata" data-tab-title="${t`Metadata`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<form class="pf-c-form">
<div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name">
<span class="pf-c-form__label-text">${t`OpenID Configuration URL`}</span>
</label>
<input class="pf-c-form-control" readonly type="text" value="${this.providerUrls?.providerInfo || "-"}" />
</div>
<div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name">
<span class="pf-c-form__label-text">${t`OpenID Configuration Issuer`}</span>
</label>
<input class="pf-c-form-control" readonly type="text" value="${this.providerUrls?.issuer || "-"}" />
</div>
<hr>
<div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name">
<span class="pf-c-form__label-text">${t`Authorize URL`}</span>
</label>
<input class="pf-c-form-control" readonly type="text" value="${this.providerUrls?.authorize || "-"}" />
</div>
<div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name">
<span class="pf-c-form__label-text">${t`Token URL`}</span>
</label>
<input class="pf-c-form-control" readonly type="text" value="${this.providerUrls?.token || "-"}" />
</div>
<div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name">
<span class="pf-c-form__label-text">${t`Userinfo URL`}</span>
</label>
<input class="pf-c-form-control" readonly type="text" value="${this.providerUrls?.userInfo || "-"}" />
</div>
<div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name">
<span class="pf-c-form__label-text">${t`Logout URL`}</span>
</label>
<input class="pf-c-form-control" readonly type="text" value="${this.providerUrls?.logout || "-"}" />
</div>
</form>
</div>
</div>
</section>
<section
slot="page-metadata"
data-tab-title="${t`Metadata`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<form class="pf-c-form">
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="help-text-simple-form-name"
>
<span class="pf-c-form__label-text"
>${t`OpenID Configuration URL`}</span
>
</label>
<input
class="pf-c-form-control"
readonly
type="text"
value="${this.providerUrls?.providerInfo || "-"}"
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="help-text-simple-form-name"
>
<span class="pf-c-form__label-text"
>${t`OpenID Configuration Issuer`}</span
>
</label>
<input
class="pf-c-form-control"
readonly
type="text"
value="${this.providerUrls?.issuer || "-"}"
/>
</div>
<hr />
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="help-text-simple-form-name"
>
<span class="pf-c-form__label-text"
>${t`Authorize URL`}</span
>
</label>
<input
class="pf-c-form-control"
readonly
type="text"
value="${this.providerUrls?.authorize || "-"}"
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="help-text-simple-form-name"
>
<span class="pf-c-form__label-text"
>${t`Token URL`}</span
>
</label>
<input
class="pf-c-form-control"
readonly
type="text"
value="${this.providerUrls?.token || "-"}"
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="help-text-simple-form-name"
>
<span class="pf-c-form__label-text"
>${t`Userinfo URL`}</span
>
</label>
<input
class="pf-c-form-control"
readonly
type="text"
value="${this.providerUrls?.userInfo || "-"}"
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="help-text-simple-form-name"
>
<span class="pf-c-form__label-text"
>${t`Logout URL`}</span
>
</label>
<input
class="pf-c-form-control"
readonly
type="text"
value="${this.providerUrls?.logout || "-"}"
/>
</div>
</form>
</div>
</div>
</div>
</section>
</ak-tabs>`;
</div>
</section>
</ak-tabs>`;
}
}

View File

@ -1,4 +1,11 @@
import { CryptoApi, FlowsApi, FlowsInstancesListDesignationEnum, ProvidersApi, ProxyMode, ProxyProvider } from "authentik-api";
import {
CryptoApi,
FlowsApi,
FlowsInstancesListDesignationEnum,
ProvidersApi,
ProxyMode,
ProxyProvider,
} from "authentik-api";
import { t } from "@lingui/macro";
import { css, CSSResult, customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html";
@ -15,29 +22,35 @@ import { first } from "../../../utils";
@customElement("ak-provider-proxy-form")
export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
static get styles(): CSSResult[] {
return super.styles.concat(PFToggleGroup, PFContent, PFSpacing, css`
.pf-c-toggle-group {
justify-content: center;
}
`);
return super.styles.concat(
PFToggleGroup,
PFContent,
PFSpacing,
css`
.pf-c-toggle-group {
justify-content: center;
}
`,
);
}
loadInstance(pk: number): Promise<ProxyProvider> {
return new ProvidersApi(DEFAULT_CONFIG).providersProxyRetrieve({
id: pk,
}).then(provider => {
this.showHttpBasic = first(provider.basicAuthEnabled, true);
this.mode = first(provider.mode, ProxyMode.Proxy);
return provider;
});
return new ProvidersApi(DEFAULT_CONFIG)
.providersProxyRetrieve({
id: pk,
})
.then((provider) => {
this.showHttpBasic = first(provider.basicAuthEnabled, true);
this.mode = first(provider.mode, ProxyMode.Proxy);
return provider;
});
}
@property({type: Boolean})
@property({ type: Boolean })
showHttpBasic = true;
@property({attribute: false})
@property({ attribute: false })
mode: ProxyMode = ProxyMode.Proxy;
getSuccessMessage(): string {
@ -53,11 +66,11 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersProxyUpdate({
id: this.instance.pk || 0,
proxyProviderRequest: data
proxyProviderRequest: data,
});
} else {
return new ProvidersApi(DEFAULT_CONFIG).providersProxyCreate({
proxyProviderRequest: data
proxyProviderRequest: data,
});
}
};
@ -68,40 +81,73 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
}
return html`<ak-form-element-horizontal
label=${t`HTTP-Basic Username Key`}
name="basicAuthUserAttribute">
<input type="text" value="${ifDefined(this.instance?.basicAuthUserAttribute)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`User/Group Attribute used for the user part of the HTTP-Basic Header. If not set, the user's Email address is used.`}</p>
name="basicAuthUserAttribute"
>
<input
type="text"
value="${ifDefined(this.instance?.basicAuthUserAttribute)}"
class="pf-c-form-control"
/>
<p class="pf-c-form__helper-text">
${t`User/Group Attribute used for the user part of the HTTP-Basic Header. If not set, the user's Email address is used.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`HTTP-Basic Password Key`}
name="basicAuthPasswordAttribute">
<input type="text" value="${ifDefined(this.instance?.basicAuthPasswordAttribute)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`User/Group Attribute used for the password part of the HTTP-Basic Header.`}</p>
name="basicAuthPasswordAttribute"
>
<input
type="text"
value="${ifDefined(this.instance?.basicAuthPasswordAttribute)}"
class="pf-c-form-control"
/>
<p class="pf-c-form__helper-text">
${t`User/Group Attribute used for the password part of the HTTP-Basic Header.`}
</p>
</ak-form-element-horizontal>`;
}
renderModeSelector(): TemplateResult {
return html`
<div class="pf-c-toggle-group__item">
<button class="pf-c-toggle-group__button ${this.mode === ProxyMode.Proxy ? "pf-m-selected" : ""}" type="button" @click=${() => {
this.mode = ProxyMode.Proxy;
}}>
return html` <div class="pf-c-toggle-group__item">
<button
class="pf-c-toggle-group__button ${this.mode === ProxyMode.Proxy
? "pf-m-selected"
: ""}"
type="button"
@click=${() => {
this.mode = ProxyMode.Proxy;
}}
>
<span class="pf-c-toggle-group__text">${t`Proxy`}</span>
</button>
</div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div>
<div class="pf-c-toggle-group__item">
<button class="pf-c-toggle-group__button ${this.mode === ProxyMode.ForwardSingle ? "pf-m-selected" : ""}" type="button" @click=${() => {
this.mode = ProxyMode.ForwardSingle;
}}>
<span class="pf-c-toggle-group__text">${t`Forward auth (single application)`}</span>
<button
class="pf-c-toggle-group__button ${this.mode === ProxyMode.ForwardSingle
? "pf-m-selected"
: ""}"
type="button"
@click=${() => {
this.mode = ProxyMode.ForwardSingle;
}}
>
<span class="pf-c-toggle-group__text"
>${t`Forward auth (single application)`}</span
>
</button>
</div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div>
<div class="pf-c-toggle-group__item">
<button class="pf-c-toggle-group__button ${this.mode === ProxyMode.ForwardDomain ? "pf-m-selected" : ""}" type="button" @click=${() => {
this.mode = ProxyMode.ForwardDomain;
}}>
<button
class="pf-c-toggle-group__button ${this.mode === ProxyMode.ForwardDomain
? "pf-m-selected"
: ""}"
type="button"
@click=${() => {
this.mode = ProxyMode.ForwardDomain;
}}
>
<span class="pf-c-toggle-group__text">${t`Forward auth (domain level)`}</span>
</button>
</div>`;
@ -110,146 +156,213 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
renderSettings(): TemplateResult {
switch (this.mode) {
case ProxyMode.Proxy:
return html`
<p class="pf-u-mb-xl">
return html` <p class="pf-u-mb-xl">
${t`This provider will behave like a transparent reverse-proxy, except requests must be authenticated. If your upstream application uses HTTPS, make sure to connect to the outpost using HTTPS as well.`}
</p>
<ak-form-element-horizontal
label=${t`External host`}
?required=${true}
name="externalHost">
<input type="text" value="${ifDefined(this.instance?.externalHost)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`The external URL you'll access the application at. Include any non-standard port.`}</p>
name="externalHost"
>
<input
type="text"
value="${ifDefined(this.instance?.externalHost)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`The external URL you'll access the application at. Include any non-standard port.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Internal host`}
?required=${true}
name="internalHost">
<input type="text" value="${ifDefined(this.instance?.internalHost)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Upstream host that the requests are forwarded to.`}</p>
name="internalHost"
>
<input
type="text"
value="${ifDefined(this.instance?.internalHost)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`Upstream host that the requests are forwarded to.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="internalHostSslValidation">
<div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.internalHostSslValidation, true)}>
<input
type="checkbox"
class="pf-c-check__input"
?checked=${first(this.instance?.internalHostSslValidation, true)}
/>
<label class="pf-c-check__label">
${t`Internal host SSL Validation`}
</label>
</div>
<p class="pf-c-form__helper-text">${t`Validate SSL Certificates of upstream servers.`}</p>
<p class="pf-c-form__helper-text">
${t`Validate SSL Certificates of upstream servers.`}
</p>
</ak-form-element-horizontal>`;
case ProxyMode.ForwardSingle:
return html`
<p class="pf-u-mb-xl">
return html` <p class="pf-u-mb-xl">
${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you).`}
</p>
<ak-form-element-horizontal
label=${t`External host`}
?required=${true}
name="externalHost">
<input type="text" value="${ifDefined(this.instance?.externalHost)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`The external URL you'll access the application at. Include any non-standard port.`}</p>
name="externalHost"
>
<input
type="text"
value="${ifDefined(this.instance?.externalHost)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`The external URL you'll access the application at. Include any non-standard port.`}
</p>
</ak-form-element-horizontal>`;
case ProxyMode.ForwardDomain:
return html`
<p class="pf-u-mb-xl">
return html` <p class="pf-u-mb-xl">
${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application.`}
</p>
<ak-form-element-horizontal
label=${t`External host`}
?required=${true}
name="externalHost">
<input type="text" value="${first(this.instance?.externalHost, window.location.origin)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`The external URL you'll authenticate at. Can be the same domain as authentik.`}</p>
name="externalHost"
>
<input
type="text"
value="${first(this.instance?.externalHost, window.location.origin)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`The external URL you'll authenticate at. Can be the same domain as authentik.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Cookie domain`}
name="cookieDomain">
<input type="text" value="${ifDefined(this.instance?.cookieDomain)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.`}</p>
<ak-form-element-horizontal label=${t`Cookie domain`} name="cookieDomain">
<input
type="text"
value="${ifDefined(this.instance?.cookieDomain)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`Optionally set this to your parent domain, if you want authentication and authorization to happen on a domain level. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.`}
</p>
</ak-form-element-horizontal>`;
}
}
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="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
<input
type="text"
value="${ifDefined(this.instance?.name)}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Authorization flow`}
?required=${true}
name="authorizationFlow">
name="authorizationFlow"
>
<select class="pf-c-form-control">
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
}).then(flows => {
return flows.results.map(flow => {
return html`<option value=${ifDefined(flow.pk)} ?selected=${this.instance?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
${until(
new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
})
.then((flows) => {
return flows.results.map((flow) => {
return html`<option
value=${ifDefined(flow.pk)}
?selected=${this.instance?.authorizationFlow === flow.pk}
>
${flow.name} (${flow.slug})
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Flow used when authorizing this provider.`}</p>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
</p>
</ak-form-element-horizontal>
<div class="pf-c-card pf-m-selectable pf-m-selected">
<div class="pf-c-card__body">
<div class="pf-c-toggle-group">
${this.renderModeSelector()}
</div>
</div>
<div class="pf-c-card__footer">
${this.renderSettings()}
<div class="pf-c-toggle-group">${this.renderModeSelector()}</div>
</div>
<div class="pf-c-card__footer">${this.renderSettings()}</div>
</div>
<ak-form-group>
<span slot="header">
${t`Advanced protocol settings`}
</span>
<span slot="header"> ${t`Advanced protocol settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Certificate`}
name="certificate">
<ak-form-element-horizontal label=${t`Certificate`} name="certificate">
<select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.certificate === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
}).then(keys => {
return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.certificate === key.pk}>${key.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
<option value="" ?selected=${this.instance?.certificate === undefined}>
---------
</option>
${until(
new CryptoApi(DEFAULT_CONFIG)
.cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
})
.then((keys) => {
return keys.results.map((key) => {
return html`<option
value=${ifDefined(key.pk)}
?selected=${this.instance?.certificate === key.pk}
>
${key.name}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Skip path regex`}
name="skipPathRegex">
<textarea class="pf-c-form-control">${this.instance?.skipPathRegex}</textarea>
<p class="pf-c-form__helper-text">${t`Regular expressions for which authentication is not required. Each new line is interpreted as a new Regular Expression.`}</p>
<ak-form-element-horizontal label=${t`Skip path regex`} name="skipPathRegex">
<textarea class="pf-c-form-control">
${this.instance?.skipPathRegex}</textarea
>
<p class="pf-c-form__helper-text">
${t`Regular expressions for which authentication is not required. Each new line is interpreted as a new Regular Expression.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="basicAuthEnabled">
<div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.basicAuthEnabled, false)} @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showHttpBasic = el.checked;
}}>
<input
type="checkbox"
class="pf-c-check__input"
?checked=${first(this.instance?.basicAuthEnabled, false)}
@change=${(ev: Event) => {
const el = ev.target as HTMLInputElement;
this.showHttpBasic = el.checked;
}}
/>
<label class="pf-c-check__label">
${t`Set HTTP-Basic Authentication`}
</label>
</div>
<p class="pf-c-form__helper-text">${t`Set a custom HTTP-Basic Authentication header based on values from authentik.`}</p>
<p class="pf-c-form__helper-text">
${t`Set a custom HTTP-Basic Authentication header based on values from authentik.`}
</p>
</ak-form-element-horizontal>
${this.renderHttpBasic()}
</div>
</ak-form-group>
</form>`;
}
}

View File

@ -24,24 +24,35 @@ import { convertToTitle } from "../../../utils";
@customElement("ak-provider-proxy-view")
export class ProxyProviderViewPage extends LitElement {
@property()
set args(value: { [key: string]: number }) {
this.providerID = value.id;
}
@property({type: Number})
@property({ type: Number })
set providerID(value: number) {
new ProvidersApi(DEFAULT_CONFIG).providersProxyRetrieve({
id: value,
}).then((prov) => (this.provider = prov));
new ProvidersApi(DEFAULT_CONFIG)
.providersProxyRetrieve({
id: value,
})
.then((prov) => (this.provider = prov));
}
@property({ attribute: false })
provider?: ProxyProvider;
static get styles(): CSSResult[] {
return [PFBase, PFButton, PFPage, PFGrid, PFGallery, PFContent, PFCard, PFDescriptionList, AKGlobal];
return [
PFBase,
PFButton,
PFPage,
PFGrid,
PFGallery,
PFContent,
PFCard,
PFDescriptionList,
AKGlobal,
];
}
constructor() {
@ -57,128 +68,165 @@ export class ProxyProviderViewPage extends LitElement {
return html``;
}
return html`<ak-tabs>
<section slot="page-overview" data-tab-title="${t`Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-l-grid pf-m-gutter">
<div class="pf-l-grid__item pf-m-6-col">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.name}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Assigned to application`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application .provider=${this.provider}></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Internal Host`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.internalHost}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`External Host`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.externalHost}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Basic-Auth`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.basicAuthEnabled ?
html`<span class="pf-c-button__icon pf-m-start">
<i class="fas fa-check-circle" aria-hidden="true"></i>&nbsp;
</span>${t`Yes`}`:
html`<span class="pf-c-button__icon pf-m-start">
<i class="fas fa-times-circle" aria-hidden="true"></i>&nbsp;
</span>${t`No`}`
}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Mode`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${convertToTitle(this.provider.mode || "")}
</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit">
${t`Update`}
</span>
<span slot="header">
${t`Update Proxy Provider`}
</span>
<ak-provider-proxy-form
slot="form"
.instancePk=${this.provider.pk || 0}>
</ak-provider-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
<section
slot="page-overview"
data-tab-title="${t`Overview`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-l-grid pf-m-gutter">
<div class="pf-l-grid__item pf-m-6-col">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Name`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.name}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Assigned to application`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application
.provider=${this.provider}
></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Internal Host`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.internalHost}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`External Host`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.externalHost}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Basic-Auth`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.basicAuthEnabled
? html`<span
class="pf-c-button__icon pf-m-start"
>
<i
class="fas fa-check-circle"
aria-hidden="true"
></i
>&nbsp; </span
>${t`Yes`}`
: html`<span
class="pf-c-button__icon pf-m-start"
>
<i
class="fas fa-times-circle"
aria-hidden="true"
></i
>&nbsp; </span
>${t`No`}`}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Mode`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${convertToTitle(this.provider.mode || "")}
</div>
</dd>
</div>
</dl>
</div>
</div>
<div class="pf-l-grid__item pf-m-6-col">
<div class="pf-c-card">
<div class="pf-c-card__title">
${t`Protocol Settings`}
</div>
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Allowed Redirect URIs`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.redirectUris}
</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span>
<span slot="header"> ${t`Update Proxy Provider`} </span>
<ak-provider-proxy-form
slot="form"
.instancePk=${this.provider.pk || 0}
>
</ak-provider-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
</div>
</div>
</section>
<section slot="page-changelog" data-tab-title="${t`Changelog`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_proxy"
targetModelName="proxyprovider">
</ak-object-changelog>
<div class="pf-l-grid__item pf-m-6-col">
<div class="pf-c-card">
<div class="pf-c-card__title">${t`Protocol Settings`}</div>
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Allowed Redirect URIs`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.redirectUris}
</div>
</dd>
</div>
</dl>
</div>
</div>
</div>
</section>
</ak-tabs>`;
</div>
</section>
<section
slot="page-changelog"
data-tab-title="${t`Changelog`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_proxy"
targetModelName="proxyprovider"
>
</ak-object-changelog>
</div>
</div>
</section>
</ak-tabs>`;
}
}

View File

@ -1,4 +1,14 @@
import { CryptoApi, FlowsApi, SAMLProvider, ProvidersApi, PropertymappingsApi, SpBindingEnum, DigestAlgorithmEnum, SignatureAlgorithmEnum, FlowsInstancesListDesignationEnum } from "authentik-api";
import {
CryptoApi,
FlowsApi,
SAMLProvider,
ProvidersApi,
PropertymappingsApi,
SpBindingEnum,
DigestAlgorithmEnum,
SignatureAlgorithmEnum,
FlowsInstancesListDesignationEnum,
} from "authentik-api";
import { t } from "@lingui/macro";
import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html";
@ -11,7 +21,6 @@ import "../../../elements/forms/FormGroup";
@customElement("ak-provider-saml-form")
export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
loadInstance(pk: number): Promise<SAMLProvider> {
return new ProvidersApi(DEFAULT_CONFIG).providersSamlRetrieve({
id: pk,
@ -30,193 +39,331 @@ export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersSamlUpdate({
id: this.instance.pk || 0,
sAMLProviderRequest: data
sAMLProviderRequest: data,
});
} else {
return new ProvidersApi(DEFAULT_CONFIG).providersSamlCreate({
sAMLProviderRequest: data
sAMLProviderRequest: data,
});
}
};
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="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
<input
type="text"
value="${ifDefined(this.instance?.name)}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Authorization flow`}
?required=${true}
name="authorizationFlow">
name="authorizationFlow"
>
<select class="pf-c-form-control">
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
}).then(flows => {
return flows.results.map(flow => {
return html`<option value=${ifDefined(flow.pk)} ?selected=${this.instance?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
${until(
new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
})
.then((flows) => {
return flows.results.map((flow) => {
return html`<option
value=${ifDefined(flow.pk)}
?selected=${this.instance?.authorizationFlow === flow.pk}
>
${flow.name} (${flow.slug})
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Flow used when authorizing this provider.`}</p>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
</p>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}>
<span slot="header">
${t`Protocol settings`}
</span>
<span slot="header"> ${t`Protocol settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`ACS URL`}
?required=${true}
name="acsUrl">
<input type="text" value="${ifDefined(this.instance?.acsUrl)}" class="pf-c-form-control" required>
<ak-form-element-horizontal label=${t`ACS URL`} ?required=${true} name="acsUrl">
<input
type="text"
value="${ifDefined(this.instance?.acsUrl)}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Issuer`}
?required=${true}
name="issuer">
<input type="text" value="${this.instance?.issuer || "authentik"}" class="pf-c-form-control" required>
<ak-form-element-horizontal label=${t`Issuer`} ?required=${true} name="issuer">
<input
type="text"
value="${this.instance?.issuer || "authentik"}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Service Provider Binding`}
?required=${true}
name="spBinding">
name="spBinding"
>
<select class="pf-c-form-control">
<option value=${SpBindingEnum.Redirect} ?selected=${this.instance?.spBinding === SpBindingEnum.Redirect}>
<option
value=${SpBindingEnum.Redirect}
?selected=${this.instance?.spBinding === SpBindingEnum.Redirect}
>
${t`Redirect`}
</option>
<option value=${SpBindingEnum.Post} ?selected=${this.instance?.spBinding === SpBindingEnum.Post}>
<option
value=${SpBindingEnum.Post}
?selected=${this.instance?.spBinding === SpBindingEnum.Post}
>
${t`Post`}
</option>
</select>
<p class="pf-c-form__helper-text">${t`Determines how authentik sends the response back to the Service Provider.`}</p>
<p class="pf-c-form__helper-text">
${t`Determines how authentik sends the response back to the Service Provider.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Audience`}
name="audience">
<input type="text" value="${ifDefined(this.instance?.audience)}" class="pf-c-form-control">
<ak-form-element-horizontal label=${t`Audience`} name="audience">
<input
type="text"
value="${ifDefined(this.instance?.audience)}"
class="pf-c-form-control"
/>
</ak-form-element-horizontal>
</div>
</ak-form-group>
<ak-form-group>
<span slot="header">
${t`Advanced protocol settings`}
</span>
<span slot="header"> ${t`Advanced protocol settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Signing Certificate`}
name="signingKp">
<ak-form-element-horizontal label=${t`Signing Certificate`} name="signingKp">
<select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.signingKp === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
}).then(keys => {
return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.signingKp === key.pk}>${key.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
<option value="" ?selected=${this.instance?.signingKp === undefined}>
---------
</option>
${until(
new CryptoApi(DEFAULT_CONFIG)
.cryptoCertificatekeypairsList({
ordering: "pk",
hasKey: true,
})
.then((keys) => {
return keys.results.map((key) => {
return html`<option
value=${ifDefined(key.pk)}
?selected=${this.instance?.signingKp === key.pk}
>
${key.name}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Certificate used to sign outgoing Responses going to the Service Provider.`}</p>
<p class="pf-c-form__helper-text">
${t`Certificate used to sign outgoing Responses going to the Service Provider.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Verification Certificate`}
name="verificationKp">
name="verificationKp"
>
<select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.verificationKp === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk",
}).then(keys => {
return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.verificationKp === key.pk}>${key.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
<option
value=""
?selected=${this.instance?.verificationKp === undefined}
>
---------
</option>
${until(
new CryptoApi(DEFAULT_CONFIG)
.cryptoCertificatekeypairsList({
ordering: "pk",
})
.then((keys) => {
return keys.results.map((key) => {
return html`<option
value=${ifDefined(key.pk)}
?selected=${this.instance?.verificationKp ===
key.pk}
>
${key.name}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.`}</p>
<p class="pf-c-form__helper-text">
${t`When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Property mappings`}
?required=${true}
name="propertyMappings">
name="propertyMappings"
>
<select class="pf-c-form-control" multiple>
${until(new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlList({
ordering: "saml_name"
}).then(mappings => {
return mappings.results.map(mapping => {
let selected = false;
if (!this.instance?.propertyMappings) {
selected = mapping.managed?.startsWith("goauthentik.io/providers/saml") || false;
} else {
selected = Array.from(this.instance?.propertyMappings).some(su => {
return su == mapping.pk;
${until(
new PropertymappingsApi(DEFAULT_CONFIG)
.propertymappingsSamlList({
ordering: "saml_name",
})
.then((mappings) => {
return mappings.results.map((mapping) => {
let selected = false;
if (!this.instance?.propertyMappings) {
selected =
mapping.managed?.startsWith(
"goauthentik.io/providers/saml",
) || false;
} else {
selected = Array.from(
this.instance?.propertyMappings,
).some((su) => {
return su == mapping.pk;
});
}
return html`<option
value=${ifDefined(mapping.pk)}
?selected=${selected}
>
${mapping.name}
</option>`;
});
}
return html`<option value=${ifDefined(mapping.pk)} ?selected=${selected}>${mapping.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
<p class="pf-c-form__helper-text">
${t`Hold control/command to select multiple items.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`NameID Property Mapping`}
name="nameIdMapping">
name="nameIdMapping"
>
<select class="pf-c-form-control">
<option value="" ?selected=${this.instance?.nameIdMapping === undefined}>---------</option>
${until(new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlList({
ordering: "saml_name"
}).then(mappings => {
return mappings.results.map(mapping => {
return html`<option value=${ifDefined(mapping.pk)} ?selected=${this.instance?.nameIdMapping === mapping.pk}>${mapping.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
<option
value=""
?selected=${this.instance?.nameIdMapping === undefined}
>
---------
</option>
${until(
new PropertymappingsApi(DEFAULT_CONFIG)
.propertymappingsSamlList({
ordering: "saml_name",
})
.then((mappings) => {
return mappings.results.map((mapping) => {
return html`<option
value=${ifDefined(mapping.pk)}
?selected=${this.instance?.nameIdMapping ===
mapping.pk}
>
${mapping.name}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected.`}</p>
<p class="pf-c-form__helper-text">
${t`Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Assertion valid not before`}
?required=${true}
name="assertionValidNotBefore">
<input type="text" value="${this.instance?.assertionValidNotBefore || "minutes=-5"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Configure the maximum allowed time drift for an asseration.`}</p>
<p class="pf-c-form__helper-text">${t`(Format: hours=-1;minutes=-2;seconds=-3).`}</p>
name="assertionValidNotBefore"
>
<input
type="text"
value="${this.instance?.assertionValidNotBefore || "minutes=-5"}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`Configure the maximum allowed time drift for an asseration.`}
</p>
<p class="pf-c-form__helper-text">
${t`(Format: hours=-1;minutes=-2;seconds=-3).`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Assertion valid not on or after`}
?required=${true}
name="assertionValidNotOnOrAfter">
<input type="text" value="${this.instance?.assertionValidNotOnOrAfter || "minutes=5"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Assertion not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).`}</p>
name="assertionValidNotOnOrAfter"
>
<input
type="text"
value="${this.instance?.assertionValidNotOnOrAfter || "minutes=5"}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`Assertion not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Session valid not on or after`}
?required=${true}
name="sessionValidNotOnOrAfter">
<input type="text" value="${this.instance?.sessionValidNotOnOrAfter || "minutes=86400"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Session not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).`}</p>
name="sessionValidNotOnOrAfter"
>
<input
type="text"
value="${this.instance?.sessionValidNotOnOrAfter || "minutes=86400"}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${t`Session not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Digest algorithm`}
?required=${true}
name="digestAlgorithm">
name="digestAlgorithm"
>
<select class="pf-c-form-control">
<option value=${DigestAlgorithmEnum._200009Xmldsigsha1} ?selected=${this.instance?.digestAlgorithm === DigestAlgorithmEnum._200009Xmldsigsha1}>
<option
value=${DigestAlgorithmEnum._200009Xmldsigsha1}
?selected=${this.instance?.digestAlgorithm ===
DigestAlgorithmEnum._200009Xmldsigsha1}
>
${t`SHA1`}
</option>
<option value=${DigestAlgorithmEnum._200104Xmlencsha256} ?selected=${this.instance?.digestAlgorithm === DigestAlgorithmEnum._200104Xmlencsha256 || this.instance?.digestAlgorithm === undefined}>
<option
value=${DigestAlgorithmEnum._200104Xmlencsha256}
?selected=${this.instance?.digestAlgorithm ===
DigestAlgorithmEnum._200104Xmlencsha256 ||
this.instance?.digestAlgorithm === undefined}
>
${t`SHA256`}
</option>
<option value=${DigestAlgorithmEnum._200104XmldsigMoresha384} ?selected=${this.instance?.digestAlgorithm === DigestAlgorithmEnum._200104XmldsigMoresha384}>
<option
value=${DigestAlgorithmEnum._200104XmldsigMoresha384}
?selected=${this.instance?.digestAlgorithm ===
DigestAlgorithmEnum._200104XmldsigMoresha384}
>
${t`SHA384`}
</option>
<option value=${DigestAlgorithmEnum._200104Xmlencsha512} ?selected=${this.instance?.digestAlgorithm === DigestAlgorithmEnum._200104Xmlencsha512}>
<option
value=${DigestAlgorithmEnum._200104Xmlencsha512}
?selected=${this.instance?.digestAlgorithm ===
DigestAlgorithmEnum._200104Xmlencsha512}
>
${t`SHA512`}
</option>
</select>
@ -224,21 +371,43 @@ export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
<ak-form-element-horizontal
label=${t`Signature algorithm`}
?required=${true}
name="signatureAlgorithm">
name="signatureAlgorithm"
>
<select class="pf-c-form-control">
<option value=${SignatureAlgorithmEnum._200009XmldsigrsaSha1} ?selected=${this.instance?.signatureAlgorithm === SignatureAlgorithmEnum._200009XmldsigrsaSha1}>
<option
value=${SignatureAlgorithmEnum._200009XmldsigrsaSha1}
?selected=${this.instance?.signatureAlgorithm ===
SignatureAlgorithmEnum._200009XmldsigrsaSha1}
>
${t`RSA-SHA1`}
</option>
<option value=${SignatureAlgorithmEnum._200104XmldsigMorersaSha256} ?selected=${this.instance?.signatureAlgorithm === SignatureAlgorithmEnum._200104XmldsigMorersaSha256 || this.instance?.signatureAlgorithm === undefined}>
<option
value=${SignatureAlgorithmEnum._200104XmldsigMorersaSha256}
?selected=${this.instance?.signatureAlgorithm ===
SignatureAlgorithmEnum._200104XmldsigMorersaSha256 ||
this.instance?.signatureAlgorithm === undefined}
>
${t`RSA-SHA256`}
</option>
<option value=${SignatureAlgorithmEnum._200104XmldsigMorersaSha384} ?selected=${this.instance?.signatureAlgorithm === SignatureAlgorithmEnum._200104XmldsigMorersaSha384}>
<option
value=${SignatureAlgorithmEnum._200104XmldsigMorersaSha384}
?selected=${this.instance?.signatureAlgorithm ===
SignatureAlgorithmEnum._200104XmldsigMorersaSha384}
>
${t`RSA-SHA384`}
</option>
<option value=${SignatureAlgorithmEnum._200104XmldsigMorersaSha512} ?selected=${this.instance?.signatureAlgorithm === SignatureAlgorithmEnum._200104XmldsigMorersaSha512}>
<option
value=${SignatureAlgorithmEnum._200104XmldsigMorersaSha512}
?selected=${this.instance?.signatureAlgorithm ===
SignatureAlgorithmEnum._200104XmldsigMorersaSha512}
>
${t`RSA-SHA512`}
</option>
<option value=${SignatureAlgorithmEnum._200009XmldsigdsaSha1} ?selected=${this.instance?.signatureAlgorithm === SignatureAlgorithmEnum._200009XmldsigdsaSha1}>
<option
value=${SignatureAlgorithmEnum._200009XmldsigdsaSha1}
?selected=${this.instance?.signatureAlgorithm ===
SignatureAlgorithmEnum._200009XmldsigdsaSha1}
>
${t`DSA-SHA1`}
</option>
</select>
@ -247,5 +416,4 @@ export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
</ak-form-group>
</form>`;
}
}

View File

@ -1,4 +1,9 @@
import { FlowsApi, FlowsInstancesListDesignationEnum, ProvidersApi, SAMLProvider } from "authentik-api";
import {
FlowsApi,
FlowsInstancesListDesignationEnum,
ProvidersApi,
SAMLProvider,
} from "authentik-api";
import { t } from "@lingui/macro";
import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html";
@ -9,7 +14,6 @@ import "../../../elements/forms/HorizontalFormElement";
@customElement("ak-provider-saml-import-form")
export class SAMLProviderImportForm extends Form<SAMLProvider> {
getSuccessMessage(): string {
return t`Successfully imported provider.`;
}
@ -29,35 +33,39 @@ export class SAMLProviderImportForm extends Form<SAMLProvider> {
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" class="pf-c-form-control" required>
<ak-form-element-horizontal label=${t`Name`} ?required=${true} name="name">
<input type="text" class="pf-c-form-control" required />
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Authorization flow`}
?required=${true}
name="authorizationFlow">
name="authorizationFlow"
>
<select class="pf-c-form-control">
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
}).then(flows => {
return flows.results.map(flow => {
return html`<option value=${flow.slug}>${flow.name} (${flow.slug})</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
${until(
new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesList({
ordering: "pk",
designation: FlowsInstancesListDesignationEnum.Authorization,
})
.then((flows) => {
return flows.results.map((flow) => {
return html`<option value=${flow.slug}>
${flow.name} (${flow.slug})
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">${t`Flow used when authorizing this provider.`}</p>
<p class="pf-c-form__helper-text">
${t`Flow used when authorizing this provider.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Metadata`}
name="flow">
<input type="file" value="" class="pf-c-form-control">
<ak-form-element-horizontal label=${t`Metadata`} name="flow">
<input type="file" value="" class="pf-c-form-control" />
</ak-form-element-horizontal>
</form>`;
}
}

View File

@ -28,24 +28,37 @@ import { ifDefined } from "lit-html/directives/if-defined";
@customElement("ak-provider-saml-view")
export class SAMLProviderViewPage extends LitElement {
@property()
set args(value: { [key: string]: number }) {
this.providerID = value.id;
}
@property({type: Number})
@property({ type: Number })
set providerID(value: number) {
new ProvidersApi(DEFAULT_CONFIG).providersSamlRetrieve({
id: value,
}).then((prov) => (this.provider = prov));
new ProvidersApi(DEFAULT_CONFIG)
.providersSamlRetrieve({
id: value,
})
.then((prov) => (this.provider = prov));
}
@property({ attribute: false })
provider?: SAMLProvider;
static get styles(): CSSResult[] {
return [PFBase, PFPage, PFButton, PFFlex, PFDisplay, PFGallery, PFContent, PFCard, PFDescriptionList, PFSizing, AKGlobal];
return [
PFBase,
PFPage,
PFButton,
PFFlex,
PFDisplay,
PFGallery,
PFContent,
PFCard,
PFDescriptionList,
PFSizing,
AKGlobal,
];
}
constructor() {
@ -61,118 +74,163 @@ export class SAMLProviderViewPage extends LitElement {
return html``;
}
return html`<ak-tabs>
<section slot="page-overview" data-tab-title="${t`Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Name`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.name}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Assigned to application`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application .provider=${this.provider}></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`ACS URL`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.acsUrl}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Audience`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.audience}</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${t`Issuer`}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${this.provider.issuer}</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit">
${t`Update`}
</span>
<span slot="header">
${t`Update SAML Provider`}
</span>
<ak-provider-saml-form
slot="form"
.instancePk=${this.provider.pk || 0}>
</ak-provider-saml-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
<section
slot="page-overview"
data-tab-title="${t`Overview`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
<dl class="pf-c-description-list pf-m-3-col-on-lg">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Name`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.name}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Assigned to application`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<ak-provider-related-application
.provider=${this.provider}
></ak-provider-related-application>
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`ACS URL`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.acsUrl}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Audience`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.audience}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${t`Issuer`}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${this.provider.issuer}
</div>
</dd>
</div>
</dl>
</div>
<div class="pf-c-card__footer">
<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span>
<span slot="header"> ${t`Update SAML Provider`} </span>
<ak-provider-saml-form
slot="form"
.instancePk=${this.provider.pk || 0}
>
</ak-provider-saml-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`}
</button>
</ak-forms-modal>
</div>
</div>
</div>
</section>
<section slot="page-changelog" data-tab-title="${t`Changelog`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_saml"
targetModelName="samlprovider">
</ak-object-changelog>
</div>
</div>
</section>
<section
slot="page-changelog"
data-tab-title="${t`Changelog`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-c-card">
<div class="pf-c-card__body">
<ak-object-changelog
targetModelPk=${this.provider.pk || ""}
targetModelApp="authentik_providers_saml"
targetModelName="samlprovider"
>
</ak-object-changelog>
</div>
</section>
${this.provider.assignedApplicationName ? html`
<section slot="page-metadata" data-tab-title="${t`Metadata`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
${until(new ProvidersApi(DEFAULT_CONFIG).providersSamlMetadataRetrieve({
id: this.provider.pk || 0,
}).then(m => {
return html`<ak-codemirror mode="xml" ?readOnly=${true} value="${ifDefined(m.metadata)}"></ak-codemirror>`;
}))}
</div>
<div class="pf-c-card__footer">
<a class="pf-c-button pf-m-primary" target="_blank"
href=${this.provider.metadataDownloadUrl}>
${t`Download`}
</a>
<ak-action-button
class="pf-m-secondary"
.apiRequest=${() => {
const fullUrl = window.location.origin + this.provider?.metadataDownloadUrl;
return navigator.clipboard.writeText(fullUrl);
}}>
${t`Copy download URL`}
</ak-action-button>
</div>
</div>
</div>
</div>
</section>` : html``}
</ak-tabs>`;
</div>
</section>
${this.provider.assignedApplicationName
? html` <section
slot="page-metadata"
data-tab-title="${t`Metadata`}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">
<div class="pf-c-card">
<div class="pf-c-card__body">
${until(
new ProvidersApi(DEFAULT_CONFIG)
.providersSamlMetadataRetrieve({
id: this.provider.pk || 0,
})
.then((m) => {
return html`<ak-codemirror
mode="xml"
?readOnly=${true}
value="${ifDefined(m.metadata)}"
></ak-codemirror>`;
}),
)}
</div>
<div class="pf-c-card__footer">
<a
class="pf-c-button pf-m-primary"
target="_blank"
href=${this.provider.metadataDownloadUrl}
>
${t`Download`}
</a>
<ak-action-button
class="pf-m-secondary"
.apiRequest=${() => {
const fullUrl =
window.location.origin +
this.provider?.metadataDownloadUrl;
return navigator.clipboard.writeText(fullUrl);
}}
>
${t`Copy download URL`}
</ak-action-button>
</div>
</div>
</div>
</div>
</section>`
: html``}
</ak-tabs>`;
}
}