Merge pull request #862 from goauthentik/form-refresh-on-save

Form refresh on save
This commit is contained in:
Jens L 2021-05-11 14:23:32 +02:00 committed by GitHub
commit 36f7cad23b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 2342 additions and 2393 deletions

View File

@ -34,7 +34,6 @@ class PlexSourceSerializer(SourceSerializer):
"allow_friends", "allow_friends",
"plex_token", "plex_token",
] ]
extra_kwargs = {"plex_token": {"write_only": True}}
class PlexTokenRedeemSerializer(PassiveSerializer): class PlexTokenRedeemSerializer(PassiveSerializer):

View File

@ -15,6 +15,7 @@ import { MessageLevel } from "../messages/Message";
import { IronFormElement } from "@polymer/iron-form/iron-form"; import { IronFormElement } from "@polymer/iron-form/iron-form";
import { camelToSnake, convertToSlug } from "../../utils"; import { camelToSnake, convertToSlug } from "../../utils";
import { ValidationError } from "authentik-api/src"; import { ValidationError } from "authentik-api/src";
import { EVENT_REFRESH } from "../../constants";
export class APIError extends Error { export class APIError extends Error {
@ -140,6 +141,12 @@ export class Form<T> extends LitElement {
level: MessageLevel.success, level: MessageLevel.success,
message: this.getSuccessMessage() message: this.getSuccessMessage()
}); });
this.dispatchEvent(
new CustomEvent(EVENT_REFRESH, {
bubbles: true,
composed: true,
})
);
return r; return r;
}).catch((ex: Response) => { }).catch((ex: Response) => {
if (ex.status > 399 && ex.status < 500) { if (ex.status > 399 && ex.status < 500) {

View File

@ -0,0 +1,36 @@
import { property } from "lit-element";
import { EVENT_REFRESH } from "../../constants";
import { Form } from "./Form";
export abstract class ModelForm<T, PKT extends string | number> extends Form<T> {
abstract loadInstance(pk: PKT): Promise<T>;
@property({attribute: false})
set instancePk(value: PKT) {
this._instancePk = value;
this.loadInstance(value).then(instance => {
this.instance = instance;
});
}
private _instancePk?: PKT;
@property({ attribute: false })
instance?: T = this.defaultInstance;
get defaultInstance(): T | undefined {
return undefined;
}
constructor() {
super();
this.addEventListener(EVENT_REFRESH, () => {
if (!this._instancePk) return;
this.loadInstance(this._instancePk).then(instance => {
this.instance = instance;
});
});
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,6 @@ import { t } from "@lingui/macro";
import { CSSResult, customElement, property } from "lit-element"; import { CSSResult, customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/buttons/Dropdown"; import "../../elements/buttons/Dropdown";
@ -13,18 +12,22 @@ import "../../elements/forms/ModalForm";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/forms/FormGroup"; import "../../elements/forms/FormGroup";
import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css"; import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-application-form") @customElement("ak-application-form")
export class ApplicationForm extends Form<Application> { export class ApplicationForm extends ModelForm<Application, string> {
@property({ attribute: false }) loadInstance(pk: string): Promise<Application> {
application?: Application; return new CoreApi(DEFAULT_CONFIG).coreApplicationsRead({
slug: pk
});
}
@property({ attribute: false }) @property({ attribute: false })
provider?: number; provider?: number;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.application) { if (this.instance) {
return t`Successfully updated application.`; return t`Successfully updated application.`;
} else { } else {
return t`Successfully created application.`; return t`Successfully created application.`;
@ -37,9 +40,9 @@ export class ApplicationForm extends Form<Application> {
send = (data: Application): Promise<Application | void> => { send = (data: Application): Promise<Application | void> => {
let writeOp: Promise<Application>; let writeOp: Promise<Application>;
if (this.application) { if (this.instance) {
writeOp = new CoreApi(DEFAULT_CONFIG).coreApplicationsUpdate({ writeOp = new CoreApi(DEFAULT_CONFIG).coreApplicationsUpdate({
slug: this.application.slug, slug: this.instance.slug,
data: data data: data
}); });
} else { } else {
@ -72,7 +75,7 @@ export class ApplicationForm extends Form<Application> {
${Array.from(m).map(([group, providers]) => { ${Array.from(m).map(([group, providers]) => {
return html`<optgroup label=${group}> return html`<optgroup label=${group}>
${providers.map(p => { ${providers.map(p => {
const selected = (this.application?.provider === p.pk) || (this.provider === p.pk); const selected = (this.instance?.provider === p.pk) || (this.provider === p.pk);
return html`<option ?selected=${selected} value=${ifDefined(p.pk)}>${p.name}</option>`; return html`<option ?selected=${selected} value=${ifDefined(p.pk)}>${p.name}</option>`;
})} })}
</optgroup>`; </optgroup>`;
@ -86,21 +89,21 @@ export class ApplicationForm extends Form<Application> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.application?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Application's display Name.`}</p> <p class="pf-c-form__helper-text">${t`Application's display Name.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Slug`} label=${t`Slug`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.application?.slug)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Internal application name, used in URLs.`}</p> <p class="pf-c-form__helper-text">${t`Internal application name, used in URLs.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Provider`} label=${t`Provider`}
name="provider"> name="provider">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.application?.provider === undefined}>---------</option> <option value="" ?selected=${this.instance?.provider === undefined}>---------</option>
${until(new ProvidersApi(DEFAULT_CONFIG).providersAllList({}).then(providers => { ${until(new ProvidersApi(DEFAULT_CONFIG).providersAllList({}).then(providers => {
return this.groupProviders(providers.results); return this.groupProviders(providers.results);
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
@ -142,10 +145,10 @@ export class ApplicationForm extends Form<Application> {
?required=${true} ?required=${true}
name="policyEngineMode"> name="policyEngineMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${ApplicationPolicyEngineModeEnum.Any} ?selected=${this.application?.policyEngineMode === ApplicationPolicyEngineModeEnum.Any}> <option value=${ApplicationPolicyEngineModeEnum.Any} ?selected=${this.instance?.policyEngineMode === ApplicationPolicyEngineModeEnum.Any}>
${t`ANY, any policy must match to grant access.`} ${t`ANY, any policy must match to grant access.`}
</option> </option>
<option value=${ApplicationPolicyEngineModeEnum.All} ?selected=${this.application?.policyEngineMode === ApplicationPolicyEngineModeEnum.All}> <option value=${ApplicationPolicyEngineModeEnum.All} ?selected=${this.instance?.policyEngineMode === ApplicationPolicyEngineModeEnum.All}>
${t`ALL, all policies must match to grant access.`} ${t`ALL, all policies must match to grant access.`}
</option> </option>
</select> </select>
@ -158,23 +161,23 @@ export class ApplicationForm extends Form<Application> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Launch URL`} label=${t`Launch URL`}
name="metaLaunchUrl"> name="metaLaunchUrl">
<input type="text" value="${ifDefined(this.application?.metaLaunchUrl)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.metaLaunchUrl)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`If left empty, authentik will try to extract the launch URL based on the selected provider.`}</p> <p class="pf-c-form__helper-text">${t`If left empty, authentik will try to extract the launch URL based on the selected provider.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Icon`} label=${t`Icon`}
name="metaIcon"> name="metaIcon">
<input type="file" value="${ifDefined(this.application?.metaIcon)}" class="pf-c-form-control"> <input type="file" value="${ifDefined(this.instance?.metaIcon)}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Description`} label=${t`Description`}
name="metaDescription"> name="metaDescription">
<textarea class="pf-c-form-control">${ifDefined(this.application?.metaDescription)}</textarea> <textarea class="pf-c-form-control">${ifDefined(this.instance?.metaDescription)}</textarea>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Publisher`} label=${t`Publisher`}
name="metaPublisher"> name="metaPublisher">
<input type="text" value="${ifDefined(this.application?.metaPublisher)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.metaPublisher)}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>

View File

@ -89,7 +89,7 @@ export class ApplicationListPage extends TablePage<Application> {
<span slot="header"> <span slot="header">
${t`Update Application`} ${t`Update Application`}
</span> </span>
<ak-application-form slot="form" .application=${item}> <ak-application-form slot="form" .instancePk=${item.slug}>
</ak-application-form> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -102,7 +102,7 @@ export class ApplicationViewPage extends LitElement {
<span slot="header"> <span slot="header">
${t`Update Application`} ${t`Update Application`}
</span> </span>
<ak-application-form slot="form" .application=${this.application}> <ak-application-form slot="form" .instancePk=${this.application.slug}>
</ak-application-form> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -1,21 +1,24 @@
import { CertificateKeyPair, CryptoApi } from "authentik-api"; import { CertificateKeyPair, CryptoApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror"; import "../../elements/CodeMirror";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-crypto-certificate-form") @customElement("ak-crypto-certificate-form")
export class CertificateKeyPairForm extends Form<CertificateKeyPair> { export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<CertificateKeyPair> {
keyPair?: CertificateKeyPair; return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsRead({
kpUuid: pk,
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.keyPair) { if (this.instance) {
return t`Successfully updated certificate-key pair.`; return t`Successfully updated certificate-key pair.`;
} else { } else {
return t`Successfully created certificate-key pair.`; return t`Successfully created certificate-key pair.`;
@ -23,9 +26,9 @@ export class CertificateKeyPairForm extends Form<CertificateKeyPair> {
} }
send = (data: CertificateKeyPair): Promise<CertificateKeyPair> => { send = (data: CertificateKeyPair): Promise<CertificateKeyPair> => {
if (this.keyPair) { if (this.instance) {
return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsPartialUpdate({ return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsPartialUpdate({
kpUuid: this.keyPair.pk || "", kpUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -41,21 +44,21 @@ export class CertificateKeyPairForm extends Form<CertificateKeyPair> {
label=${t`Name`} label=${t`Name`}
name="name" name="name"
?required=${true}> ?required=${true}>
<input type="text" value="${ifDefined(this.keyPair?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Certificate`} label=${t`Certificate`}
name="certificateData" name="certificateData"
?writeOnly=${this.keyPair !== undefined} ?writeOnly=${this.instance !== undefined}
?required=${true}> ?required=${true}>
<textarea class="pf-c-form-control" required>${ifDefined(this.keyPair?.certificateData)}</textarea> <textarea class="pf-c-form-control" required>${ifDefined(this.instance?.certificateData)}</textarea>
<p class="pf-c-form__helper-text">${t`PEM-encoded Certificate data.`}</p> <p class="pf-c-form__helper-text">${t`PEM-encoded Certificate data.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
name="keyData" name="keyData"
?writeOnly=${this.keyPair !== undefined} ?writeOnly=${this.instance !== undefined}
label=${t`Private Key`}> label=${t`Private Key`}>
<textarea class="pf-c-form-control" >${ifDefined(this.keyPair?.keyData)}</textarea> <textarea class="pf-c-form-control" >${ifDefined(this.instance?.keyData)}</textarea>
<p class="pf-c-form__helper-text">${t`Optional Private Key. If this is set, you can use this keypair for encryption.`}</p> <p class="pf-c-form__helper-text">${t`Optional Private Key. If this is set, you can use this keypair for encryption.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;

View File

@ -70,7 +70,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
<span slot="header"> <span slot="header">
${t`Update Certificate-Key Pair`} ${t`Update Certificate-Key Pair`}
</span> </span>
<ak-crypto-certificate-form slot="form" .keyPair=${item}> <ak-crypto-certificate-form slot="form" .instancePk=${item.pk}>
</ak-crypto-certificate-form> </ak-crypto-certificate-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -1,21 +1,24 @@
import { CoreApi, EventsApi, NotificationRule, NotificationRuleSeverityEnum } from "authentik-api"; import { CoreApi, EventsApi, NotificationRule, NotificationRuleSeverityEnum } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-event-rule-form") @customElement("ak-event-rule-form")
export class RuleForm extends Form<NotificationRule> { export class RuleForm extends ModelForm<NotificationRule, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<NotificationRule> {
rule?: NotificationRule; return new EventsApi(DEFAULT_CONFIG).eventsRulesRead({
pbmUuid: pk,
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.rule) { if (this.instance) {
return t`Successfully updated rule.`; return t`Successfully updated rule.`;
} else { } else {
return t`Successfully created rule.`; return t`Successfully created rule.`;
@ -23,9 +26,9 @@ export class RuleForm extends Form<NotificationRule> {
} }
send = (data: NotificationRule): Promise<NotificationRule> => { send = (data: NotificationRule): Promise<NotificationRule> => {
if (this.rule) { if (this.instance) {
return new EventsApi(DEFAULT_CONFIG).eventsRulesUpdate({ return new EventsApi(DEFAULT_CONFIG).eventsRulesUpdate({
pbmUuid: this.rule.pk || "", pbmUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -37,13 +40,13 @@ export class RuleForm extends Form<NotificationRule> {
renderSeverity(): TemplateResult { renderSeverity(): TemplateResult {
return html` return html`
<option value=${NotificationRuleSeverityEnum.Alert} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Alert}> <option value=${NotificationRuleSeverityEnum.Alert} ?selected=${this.instance?.severity === NotificationRuleSeverityEnum.Alert}>
${t`Alert`} ${t`Alert`}
</option> </option>
<option value=${NotificationRuleSeverityEnum.Warning} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Warning}> <option value=${NotificationRuleSeverityEnum.Warning} ?selected=${this.instance?.severity === NotificationRuleSeverityEnum.Warning}>
${t`Warning`} ${t`Warning`}
</option> </option>
<option value=${NotificationRuleSeverityEnum.Notice} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Notice}> <option value=${NotificationRuleSeverityEnum.Notice} ?selected=${this.instance?.severity === NotificationRuleSeverityEnum.Notice}>
${t`Notice`} ${t`Notice`}
</option> </option>
`; `;
@ -55,16 +58,16 @@ export class RuleForm extends Form<NotificationRule> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.rule?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Group`} label=${t`Group`}
name="group"> name="group">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.rule?.group === undefined}>---------</option> <option value="" ?selected=${this.instance?.group === undefined}>---------</option>
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => { ${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => {
return groups.results.map(group => { return groups.results.map(group => {
return html`<option value=${ifDefined(group.pk)} ?selected=${this.rule?.group?.groupUuid === group.pk}>${group.name}</option>`; return html`<option value=${ifDefined(group.pk)} ?selected=${this.instance?.group?.groupUuid === group.pk}>${group.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -76,7 +79,7 @@ export class RuleForm extends Form<NotificationRule> {
<select name="users" class="pf-c-form-control" multiple> <select name="users" class="pf-c-form-control" multiple>
${until(new EventsApi(DEFAULT_CONFIG).eventsTransportsList({}).then(transports => { ${until(new EventsApi(DEFAULT_CONFIG).eventsTransportsList({}).then(transports => {
return transports.results.map(transport => { return transports.results.map(transport => {
const selected = Array.from(this.rule?.transports || []).some(su => { const selected = Array.from(this.instance?.transports || []).some(su => {
return su.uuid == transport.pk; return su.uuid == transport.pk;
}); });
return html`<option value=${ifDefined(transport.pk)} ?selected=${selected}>${transport.name}</option>`; return html`<option value=${ifDefined(transport.pk)} ?selected=${selected}>${transport.name}</option>`;

View File

@ -64,7 +64,7 @@ export class RuleListPage extends TablePage<NotificationRule> {
<span slot="header"> <span slot="header">
${t`Update Notification Rule`} ${t`Update Notification Rule`}
</span> </span>
<ak-event-rule-form slot="form" .rule=${item}> <ak-event-rule-form slot="form" .instancePk=${item.pk}>
</ak-event-rule-form> </ak-event-rule-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -3,22 +3,25 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import { first } from "../../utils"; import { first } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-event-transport-form") @customElement("ak-event-transport-form")
export class TransportForm extends Form<NotificationTransport> { export class TransportForm extends ModelForm<NotificationTransport, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<NotificationTransport> {
transport?: NotificationTransport; return new EventsApi(DEFAULT_CONFIG).eventsTransportsRead({
uuid: pk,
});
}
@property({type: Boolean}) @property({type: Boolean})
showWebhook = false; showWebhook = false;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.transport) { if (this.instance) {
return t`Successfully updated transport.`; return t`Successfully updated transport.`;
} else { } else {
return t`Successfully created transport.`; return t`Successfully created transport.`;
@ -26,9 +29,9 @@ export class TransportForm extends Form<NotificationTransport> {
} }
send = (data: NotificationTransport): Promise<NotificationTransport> => { send = (data: NotificationTransport): Promise<NotificationTransport> => {
if (this.transport) { if (this.instance) {
return new EventsApi(DEFAULT_CONFIG).eventsTransportsUpdate({ return new EventsApi(DEFAULT_CONFIG).eventsTransportsUpdate({
uuid: this.transport.pk || "", uuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -40,21 +43,21 @@ export class TransportForm extends Form<NotificationTransport> {
renderTransportModes(): TemplateResult { renderTransportModes(): TemplateResult {
return html` return html`
<option value=${NotificationTransportModeEnum.Email} ?selected=${this.transport?.mode === NotificationTransportModeEnum.Email}> <option value=${NotificationTransportModeEnum.Email} ?selected=${this.instance?.mode === NotificationTransportModeEnum.Email}>
${t`Email`} ${t`Email`}
</option> </option>
<option value=${NotificationTransportModeEnum.Webhook} ?selected=${this.transport?.mode === NotificationTransportModeEnum.Webhook}> <option value=${NotificationTransportModeEnum.Webhook} ?selected=${this.instance?.mode === NotificationTransportModeEnum.Webhook}>
${t`Webhook (generic)`} ${t`Webhook (generic)`}
</option> </option>
<option value=${NotificationTransportModeEnum.WebhookSlack} ?selected=${this.transport?.mode === NotificationTransportModeEnum.WebhookSlack}> <option value=${NotificationTransportModeEnum.WebhookSlack} ?selected=${this.instance?.mode === NotificationTransportModeEnum.WebhookSlack}>
${t`Webhook (Slack/Discord)`} ${t`Webhook (Slack/Discord)`}
</option> </option>
`; `;
} }
firstUpdated(): void { firstUpdated(): void {
if (this.transport) { if (this.instance) {
this.onModeChange(this.transport.mode); this.onModeChange(this.instance.mode);
} }
} }
@ -72,7 +75,7 @@ export class TransportForm extends Form<NotificationTransport> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.transport?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Mode`} label=${t`Mode`}
@ -89,11 +92,11 @@ export class TransportForm extends Form<NotificationTransport> {
?hidden=${!this.showWebhook} ?hidden=${!this.showWebhook}
label=${t`Webhook URL`} label=${t`Webhook URL`}
name="webhookUrl"> name="webhookUrl">
<input type="text" value="${ifDefined(this.transport?.webhookUrl)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.webhookUrl)}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="sendOnce"> <ak-form-element-horizontal name="sendOnce">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.transport?.sendOnce, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.sendOnce, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Send once`} ${t`Send once`}
</label> </label>

View File

@ -68,7 +68,7 @@ export class TransportListPage extends TablePage<NotificationTransport> {
<span slot="header"> <span slot="header">
${t`Update Notification Transport`} ${t`Update Notification Transport`}
</span> </span>
<ak-event-transport-form slot="form" .transport=${item}> <ak-event-transport-form slot="form" .instancePk=${item.pk}>
</ak-event-transport-form> </ak-event-transport-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -58,7 +58,7 @@ export class BoundStagesList extends Table<FlowStageBinding> {
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
"stageUUID": item.stage "instancePk": item.stage
}} }}
type=${ifDefined(item.stageObj?.component)}> type=${ifDefined(item.stageObj?.component)}>
</ak-proxy-form> </ak-proxy-form>
@ -73,7 +73,7 @@ export class BoundStagesList extends Table<FlowStageBinding> {
<span slot="header"> <span slot="header">
${t`Update Stage binding`} ${t`Update Stage binding`}
</span> </span>
<ak-stage-binding-form slot="form" .fsb=${item}> <ak-stage-binding-form slot="form" .instancePk=${item.pk}>
</ak-stage-binding-form> </ak-stage-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit Binding`} ${t`Edit Binding`}

View File

@ -1,20 +1,23 @@
import { Flow, FlowDesignationEnum, FlowPolicyEngineModeEnum, FlowsApi } from "authentik-api"; import { Flow, FlowDesignationEnum, FlowPolicyEngineModeEnum, FlowsApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-flow-form") @customElement("ak-flow-form")
export class FlowForm extends Form<Flow> { export class FlowForm extends ModelForm<Flow, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<Flow> {
flow?: Flow; return new FlowsApi(DEFAULT_CONFIG).flowsInstancesRead({
slug: pk,
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.flow) { if (this.instance) {
return t`Successfully updated flow.`; return t`Successfully updated flow.`;
} else { } else {
return t`Successfully created flow.`; return t`Successfully created flow.`;
@ -23,9 +26,9 @@ export class FlowForm extends Form<Flow> {
send = (data: Flow): Promise<void | Flow> => { send = (data: Flow): Promise<void | Flow> => {
let writeOp: Promise<Flow>; let writeOp: Promise<Flow>;
if (this.flow) { if (this.instance) {
writeOp = new FlowsApi(DEFAULT_CONFIG).flowsInstancesUpdate({ writeOp = new FlowsApi(DEFAULT_CONFIG).flowsInstancesUpdate({
slug: this.flow.slug, slug: this.instance.slug,
data: data data: data
}); });
} else { } else {
@ -47,25 +50,25 @@ export class FlowForm extends Form<Flow> {
renderDesignations(): TemplateResult { renderDesignations(): TemplateResult {
return html` return html`
<option value=${FlowDesignationEnum.Authentication} ?selected=${this.flow?.designation === FlowDesignationEnum.Authentication}> <option value=${FlowDesignationEnum.Authentication} ?selected=${this.instance?.designation === FlowDesignationEnum.Authentication}>
${t`Authentication`} ${t`Authentication`}
</option> </option>
<option value=${FlowDesignationEnum.Authorization} ?selected=${this.flow?.designation === FlowDesignationEnum.Authorization}> <option value=${FlowDesignationEnum.Authorization} ?selected=${this.instance?.designation === FlowDesignationEnum.Authorization}>
${t`Authorization`} ${t`Authorization`}
</option> </option>
<option value=${FlowDesignationEnum.Enrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Enrollment}> <option value=${FlowDesignationEnum.Enrollment} ?selected=${this.instance?.designation === FlowDesignationEnum.Enrollment}>
${t`Enrollment`} ${t`Enrollment`}
</option> </option>
<option value=${FlowDesignationEnum.Invalidation} ?selected=${this.flow?.designation === FlowDesignationEnum.Invalidation}> <option value=${FlowDesignationEnum.Invalidation} ?selected=${this.instance?.designation === FlowDesignationEnum.Invalidation}>
${t`Invalidation`} ${t`Invalidation`}
</option> </option>
<option value=${FlowDesignationEnum.Recovery} ?selected=${this.flow?.designation === FlowDesignationEnum.Recovery}> <option value=${FlowDesignationEnum.Recovery} ?selected=${this.instance?.designation === FlowDesignationEnum.Recovery}>
${t`Recovery`} ${t`Recovery`}
</option> </option>
<option value=${FlowDesignationEnum.StageConfiguration} ?selected=${this.flow?.designation === FlowDesignationEnum.StageConfiguration}> <option value=${FlowDesignationEnum.StageConfiguration} ?selected=${this.instance?.designation === FlowDesignationEnum.StageConfiguration}>
${t`Stage Configuration`} ${t`Stage Configuration`}
</option> </option>
<option value=${FlowDesignationEnum.Unenrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Unenrollment}> <option value=${FlowDesignationEnum.Unenrollment} ?selected=${this.instance?.designation === FlowDesignationEnum.Unenrollment}>
${t`Unenrollment`} ${t`Unenrollment`}
</option> </option>
`; `;
@ -77,20 +80,20 @@ export class FlowForm extends Form<Flow> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.flow?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Title`} label=${t`Title`}
?required=${true} ?required=${true}
name="title"> name="title">
<input type="text" value="${ifDefined(this.flow?.title)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.title)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Shown as the Title in Flow pages.`}</p> <p class="pf-c-form__helper-text">${t`Shown as the Title in Flow pages.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Slug`} label=${t`Slug`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.flow?.slug)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Visible in the URL.`}</p> <p class="pf-c-form__helper-text">${t`Visible in the URL.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
@ -98,10 +101,10 @@ export class FlowForm extends Form<Flow> {
?required=${true} ?required=${true}
name="policyEngineMode"> name="policyEngineMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${FlowPolicyEngineModeEnum.Any} ?selected=${this.flow?.policyEngineMode === FlowPolicyEngineModeEnum.Any}> <option value=${FlowPolicyEngineModeEnum.Any} ?selected=${this.instance?.policyEngineMode === FlowPolicyEngineModeEnum.Any}>
${t`ANY, any policy must match to grant access.`} ${t`ANY, any policy must match to grant access.`}
</option> </option>
<option value=${FlowPolicyEngineModeEnum.All} ?selected=${this.flow?.policyEngineMode === FlowPolicyEngineModeEnum.All}> <option value=${FlowPolicyEngineModeEnum.All} ?selected=${this.instance?.policyEngineMode === FlowPolicyEngineModeEnum.All}>
${t`ALL, all policies must match to grant access.`} ${t`ALL, all policies must match to grant access.`}
</option> </option>
</select> </select>
@ -111,7 +114,7 @@ export class FlowForm extends Form<Flow> {
?required=${true} ?required=${true}
name="designation"> name="designation">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.flow?.designation === undefined}>---------</option> <option value="" ?selected=${this.instance?.designation === undefined}>---------</option>
${this.renderDesignations()} ${this.renderDesignations()}
</select> </select>
<p class="pf-c-form__helper-text">${t`Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.`}</p> <p class="pf-c-form__helper-text">${t`Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.`}</p>
@ -119,7 +122,7 @@ export class FlowForm extends Form<Flow> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Background`} label=${t`Background`}
name="background"> name="background">
<input type="file" value="${ifDefined(this.flow?.background)}" class="pf-c-form-control"> <input type="file" value="${ifDefined(this.instance?.background)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`Background shown during execution.`}</p> <p class="pf-c-form__helper-text">${t`Background shown during execution.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;

View File

@ -68,7 +68,7 @@ export class FlowListPage extends TablePage<Flow> {
<span slot="header"> <span slot="header">
${t`Update Flow`} ${t`Update Flow`}
</span> </span>
<ak-flow-form slot="form" .flow=${item}> <ak-flow-form slot="form" .instancePk=${item.pk}>
</ak-flow-form> </ak-flow-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -3,23 +3,26 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import { first, groupBy } from "../../utils"; import { first, groupBy } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-stage-binding-form") @customElement("ak-stage-binding-form")
export class StageBindingForm extends Form<FlowStageBinding> { export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<FlowStageBinding> {
fsb?: FlowStageBinding; return new FlowsApi(DEFAULT_CONFIG).flowsBindingsRead({
fsbUuid: pk,
});
}
@property() @property()
targetPk?: string; targetPk?: string;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.fsb) { if (this.instance) {
return t`Successfully updated binding.`; return t`Successfully updated binding.`;
} else { } else {
return t`Successfully created binding.`; return t`Successfully created binding.`;
@ -27,9 +30,9 @@ export class StageBindingForm extends Form<FlowStageBinding> {
} }
send = (data: FlowStageBinding): Promise<FlowStageBinding> => { send = (data: FlowStageBinding): Promise<FlowStageBinding> => {
if (this.fsb) { if (this.instance) {
return new FlowsApi(DEFAULT_CONFIG).flowsBindingsUpdate({ return new FlowsApi(DEFAULT_CONFIG).flowsBindingsUpdate({
fsbUuid: this.fsb.pk || "", fsbUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -45,7 +48,7 @@ export class StageBindingForm extends Form<FlowStageBinding> {
${groupBy<Stage>(stages, (s => s.verboseName || "")).map(([group, stages]) => { ${groupBy<Stage>(stages, (s => s.verboseName || "")).map(([group, stages]) => {
return html`<optgroup label=${group}> return html`<optgroup label=${group}>
${stages.map(stage => { ${stages.map(stage => {
const selected = (this.fsb?.stage === stage.pk); const selected = (this.instance?.stage === stage.pk);
return html`<option ?selected=${selected} value=${ifDefined(stage.pk)}>${stage.name}</option>`; return html`<option ?selected=${selected} value=${ifDefined(stage.pk)}>${stage.name}</option>`;
})} })}
</optgroup>`; </optgroup>`;
@ -54,8 +57,8 @@ export class StageBindingForm extends Form<FlowStageBinding> {
} }
getOrder(): Promise<number> { getOrder(): Promise<number> {
if (this.fsb) { if (this.instance) {
return Promise.resolve(this.fsb.order); return Promise.resolve(this.instance.order);
} }
return new FlowsApi(DEFAULT_CONFIG).flowsBindingsList({ return new FlowsApi(DEFAULT_CONFIG).flowsBindingsList({
target: this.targetPk || "", target: this.targetPk || "",
@ -69,9 +72,9 @@ export class StageBindingForm extends Form<FlowStageBinding> {
} }
renderTarget(): TemplateResult { renderTarget(): TemplateResult {
if (this.fsb?.target || this.targetPk) { if (this.instance?.target || this.targetPk) {
return html` return html`
<input required name="target" type="hidden" value=${ifDefined(this.fsb?.target || this.targetPk)}> <input required name="target" type="hidden" value=${ifDefined(this.instance?.target || this.targetPk)}>
`; `;
} }
return html`<ak-form-element-horizontal return html`<ak-form-element-horizontal
@ -114,7 +117,7 @@ export class StageBindingForm extends Form<FlowStageBinding> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="evaluateOnPlan"> <ak-form-element-horizontal name="evaluateOnPlan">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.fsb?.evaluateOnPlan, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.evaluateOnPlan, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Evaluate on plan`} ${t`Evaluate on plan`}
</label> </label>
@ -125,7 +128,7 @@ export class StageBindingForm extends Form<FlowStageBinding> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="reEvaluatePolicies"> <ak-form-element-horizontal name="reEvaluatePolicies">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.fsb?.reEvaluatePolicies, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.reEvaluatePolicies, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Re-evaluate policies`} ${t`Re-evaluate policies`}
</label> </label>
@ -137,10 +140,10 @@ export class StageBindingForm extends Form<FlowStageBinding> {
?required=${true} ?required=${true}
name="policyEngineMode"> name="policyEngineMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${FlowStageBindingPolicyEngineModeEnum.Any} ?selected=${this.fsb?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.Any}> <option value=${FlowStageBindingPolicyEngineModeEnum.Any} ?selected=${this.instance?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.Any}>
${t`ANY, any policy must match to include this stage access.`} ${t`ANY, any policy must match to include this stage access.`}
</option> </option>
<option value=${FlowStageBindingPolicyEngineModeEnum.All} ?selected=${this.fsb?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.All}> <option value=${FlowStageBindingPolicyEngineModeEnum.All} ?selected=${this.instance?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.All}>
${t`ALL, all policies must match to include this stage access.`} ${t`ALL, all policies must match to include this stage access.`}
</option> </option>
</select> </select>

View File

@ -1,9 +1,8 @@
import { CoreApi, Group, User } from "authentik-api"; import { CoreApi, Group, User } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
@ -13,15 +12,19 @@ import "../../elements/chips/Chip";
import "./MemberSelectModal"; import "./MemberSelectModal";
import YAML from "yaml"; import YAML from "yaml";
import { first } from "../../utils"; import { first } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-group-form") @customElement("ak-group-form")
export class GroupForm extends Form<Group> { export class GroupForm extends ModelForm<Group, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<Group> {
group?: Group; return new CoreApi(DEFAULT_CONFIG).coreGroupsRead({
groupUuid: pk
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.group) { if (this.instance) {
return t`Successfully updated group.`; return t`Successfully updated group.`;
} else { } else {
return t`Successfully created group.`; return t`Successfully created group.`;
@ -29,13 +32,13 @@ export class GroupForm extends Form<Group> {
} }
send = (data: Group): Promise<Group> => { send = (data: Group): Promise<Group> => {
if (this.group?.pk) { if (this.instance?.pk) {
return new CoreApi(DEFAULT_CONFIG).coreGroupsUpdate({ return new CoreApi(DEFAULT_CONFIG).coreGroupsUpdate({
groupUuid: this.group.pk || "", groupUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
data.users = Array.from(this.group?.users || []) as unknown as Set<number>; data.users = Array.from(this.instance?.users || []) as unknown as Set<number>;
return new CoreApi(DEFAULT_CONFIG).coreGroupsCreate({ return new CoreApi(DEFAULT_CONFIG).coreGroupsCreate({
data: data data: data
}); });
@ -48,11 +51,11 @@ export class GroupForm extends Form<Group> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.group?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="isSuperuser"> <ak-form-element-horizontal name="isSuperuser">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.group?.isSuperuser, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.isSuperuser, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Is superuser`} ${t`Is superuser`}
</label> </label>
@ -63,10 +66,10 @@ export class GroupForm extends Form<Group> {
label=${t`Parent`} label=${t`Parent`}
name="parent"> name="parent">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.group?.parent === undefined}>---------</option> <option value="" ?selected=${this.instance?.parent === undefined}>---------</option>
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => { ${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => {
return groups.results.map(group => { return groups.results.map(group => {
return html`<option value=${ifDefined(group.pk)} ?selected=${this.group?.parent === group.pk}>${group.name}</option>`; return html`<option value=${ifDefined(group.pk)} ?selected=${this.instance?.parent === group.pk}>${group.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -79,8 +82,8 @@ export class GroupForm extends Form<Group> {
.confirm=${(items: User[]) => { .confirm=${(items: User[]) => {
// Because the model only has the IDs, map the user list to IDs // Because the model only has the IDs, map the user list to IDs
const ids = items.map(u => u.pk || 0); const ids = items.map(u => u.pk || 0);
if (!this.group) this.group = {} as Group; if (!this.instance) this.instance = {} as Group;
this.group.users = new Set(Array.from(this.group?.users || []).concat(ids)); this.instance.users = new Set(Array.from(this.instance?.users || []).concat(ids));
this.requestUpdate(); this.requestUpdate();
return Promise.resolve(); return Promise.resolve();
}}> }}>
@ -94,7 +97,7 @@ export class GroupForm extends Form<Group> {
ordering: "username", ordering: "username",
}).then(users => { }).then(users => {
return users.results.map(user => { return users.results.map(user => {
const selected = Array.from(this.group?.users || []).some(su => { const selected = Array.from(this.instance?.users || []).some(su => {
return su == user.pk; return su == user.pk;
}); });
if (!selected) return; if (!selected) return;
@ -102,11 +105,11 @@ export class GroupForm extends Form<Group> {
.removable=${true} .removable=${true}
value=${ifDefined(user.pk)} value=${ifDefined(user.pk)}
@remove=${() => { @remove=${() => {
if (!this.group) return; if (!this.instance) return;
const users = Array.from(this.group?.users || []); const users = Array.from(this.instance?.users || []);
const idx = users.indexOf(user.pk || 0); const idx = users.indexOf(user.pk || 0);
users.splice(idx, 1); users.splice(idx, 1);
this.group.users = new Set(users); this.instance.users = new Set(users);
this.requestUpdate(); this.requestUpdate();
}}> }}>
${user.username} ${user.username}
@ -122,7 +125,7 @@ export class GroupForm extends Form<Group> {
label=${t`Attributes`} label=${t`Attributes`}
?required=${true} ?required=${true}
name="attributes"> name="attributes">
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.group?.attributes, {}))}"> <ak-codemirror mode="yaml" value="${YAML.stringify(first(this.instance?.attributes, {}))}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p> <p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -63,7 +63,7 @@ export class GroupListPage extends TablePage<Group> {
<span slot="header"> <span slot="header">
${t`Update Group`} ${t`Update Group`}
</span> </span>
<ak-group-form slot="form" .group=${item}> <ak-group-form slot="form" .instancePk=${item.pk}>
</ak-group-form> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -1,23 +1,26 @@
import { Outpost, OutpostsApi, OutpostTypeEnum, ProvidersApi } from "authentik-api"; import { Outpost, OutpostsApi, OutpostTypeEnum, ProvidersApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror"; import "../../elements/CodeMirror";
import YAML from "yaml"; import YAML from "yaml";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-outpost-form") @customElement("ak-outpost-form")
export class OutpostForm extends Form<Outpost> { export class OutpostForm extends ModelForm<Outpost, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<Outpost> {
outpost?: Outpost; return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesRead({
uuid: pk
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.outpost) { if (this.instance) {
return t`Successfully updated outpost.`; return t`Successfully updated outpost.`;
} else { } else {
return t`Successfully created outpost.`; return t`Successfully created outpost.`;
@ -25,9 +28,9 @@ export class OutpostForm extends Form<Outpost> {
} }
send = (data: Outpost): Promise<Outpost> => { send = (data: Outpost): Promise<Outpost> => {
if (this.outpost) { if (this.instance) {
return new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsUpdate({ return new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsUpdate({
uuid: this.outpost.pk || "", uuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -43,27 +46,27 @@ export class OutpostForm extends Form<Outpost> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.outpost?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Type`} label=${t`Type`}
?required=${true} ?required=${true}
name="type"> name="type">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${OutpostTypeEnum.Proxy} ?selected=${this.outpost?.type === OutpostTypeEnum.Proxy}>${t`Proxy`}</option> <option value=${OutpostTypeEnum.Proxy} ?selected=${this.instance?.type === OutpostTypeEnum.Proxy}>${t`Proxy`}</option>
<option value=${OutpostTypeEnum.Ldap} ?selected=${this.outpost?.type === OutpostTypeEnum.Ldap}>${t`LDAP (Technical preview)`}</option> <option value=${OutpostTypeEnum.Ldap} ?selected=${this.instance?.type === OutpostTypeEnum.Ldap}>${t`LDAP (Technical preview)`}</option>
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Service connection`} label=${t`Service connection`}
name="serviceConnection"> name="serviceConnection">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.outpost?.serviceConnection === undefined}>---------</option> <option value="" ?selected=${this.instance?.serviceConnection === undefined}>---------</option>
${until(new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllList({ ${until(new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllList({
ordering: "pk" ordering: "pk"
}).then(scs => { }).then(scs => {
return scs.results.map(sc => { return scs.results.map(sc => {
return html`<option value=${ifDefined(sc.pk)} ?selected=${this.outpost?.serviceConnection === sc.pk}> return html`<option value=${ifDefined(sc.pk)} ?selected=${this.instance?.serviceConnection === sc.pk}>
${sc.name} (${sc.verboseName}) ${sc.name} (${sc.verboseName})
</option>`; </option>`;
}); });
@ -83,7 +86,7 @@ export class OutpostForm extends Form<Outpost> {
ordering: "pk" ordering: "pk"
}).then(providers => { }).then(providers => {
return providers.results.map(provider => { return providers.results.map(provider => {
const selected = Array.from(this.outpost?.providers || []).some(sp => { const selected = Array.from(this.instance?.providers || []).some(sp => {
return sp == provider.pk; return sp == provider.pk;
}); });
return html`<option value=${ifDefined(provider.pk)} ?selected=${selected}>${provider.verboseName} ${provider.name}</option>`; return html`<option value=${ifDefined(provider.pk)} ?selected=${selected}>${provider.verboseName} ${provider.name}</option>`;
@ -93,7 +96,7 @@ export class OutpostForm extends Form<Outpost> {
ordering: "pk" ordering: "pk"
}).then(providers => { }).then(providers => {
return providers.results.map(provider => { return providers.results.map(provider => {
const selected = Array.from(this.outpost?.providers || []).some(sp => { const selected = Array.from(this.instance?.providers || []).some(sp => {
return sp == provider.pk; return sp == provider.pk;
}); });
return html`<option value=${ifDefined(provider.pk)} ?selected=${selected}>${provider.verboseName} ${provider.name}</option>`; return html`<option value=${ifDefined(provider.pk)} ?selected=${selected}>${provider.verboseName} ${provider.name}</option>`;
@ -107,8 +110,8 @@ export class OutpostForm extends Form<Outpost> {
name="config"> name="config">
<ak-codemirror mode="yaml" value="${until(new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDefaultSettings({}).then(config => { <ak-codemirror mode="yaml" value="${until(new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDefaultSettings({}).then(config => {
let fc = config.config; let fc = config.config;
if (this.outpost) { if (this.instance) {
fc = this.outpost.config; fc = this.instance.config;
} }
return YAML.stringify(fc); return YAML.stringify(fc);
}))}"></ak-codemirror> }))}"></ak-codemirror>

View File

@ -66,7 +66,7 @@ export class OutpostListPage extends TablePage<Outpost> {
<span slot="header"> <span slot="header">
${t`Update Outpost`} ${t`Update Outpost`}
</span> </span>
<ak-outpost-form slot="form" .outpost=${item}> <ak-outpost-form slot="form" .instancePk=${item.pk}>
</ak-outpost-form> </ak-outpost-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -1,30 +1,25 @@
import { CryptoApi, DockerServiceConnection, OutpostsApi } from "authentik-api"; import { CryptoApi, DockerServiceConnection, OutpostsApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import { first } from "../../utils"; import { first } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-service-connection-docker-form") @customElement("ak-service-connection-docker-form")
export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> { export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnection, string> {
set scUUID(value: string) { loadInstance(pk: string): Promise<DockerServiceConnection> {
new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsDockerRead({ return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsDockerRead({
uuid: value, uuid: pk,
}).then(sc => {
this.sc = sc;
}); });
} }
@property({attribute: false})
sc?: DockerServiceConnection;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.sc) { if (this.instance) {
return t`Successfully updated service-connection.`; return t`Successfully updated service-connection.`;
} else { } else {
return t`Successfully created service-connection.`; return t`Successfully created service-connection.`;
@ -32,9 +27,9 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
} }
send = (data: DockerServiceConnection): Promise<DockerServiceConnection> => { send = (data: DockerServiceConnection): Promise<DockerServiceConnection> => {
if (this.sc) { if (this.instance) {
return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsDockerUpdate({ return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsDockerUpdate({
uuid: this.sc.pk || "", uuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -50,11 +45,11 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.sc?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="local"> <ak-form-element-horizontal name="local">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.sc?.local, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.local, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Local`} ${t`Local`}
</label> </label>
@ -65,19 +60,19 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
label=${t`Docker URL`} label=${t`Docker URL`}
?required=${true} ?required=${true}
name="url"> name="url">
<input type="text" value="${ifDefined(this.sc?.url)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.url)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system.`}</p> <p class="pf-c-form__helper-text">${t`Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`TLS Verification Certificate`} label=${t`TLS Verification Certificate`}
name="tlsVerification"> name="tlsVerification">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.sc?.tlsVerification === undefined}>---------</option> <option value="" ?selected=${this.instance?.tlsVerification === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({ ${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk" ordering: "pk"
}).then(certs => { }).then(certs => {
return certs.results.map(cert => { return certs.results.map(cert => {
return html`<option value=${ifDefined(cert.pk)} ?selected=${this.sc?.tlsVerification === cert.pk}>${cert.name}</option>`; return html`<option value=${ifDefined(cert.pk)} ?selected=${this.instance?.tlsVerification === cert.pk}>${cert.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -87,12 +82,12 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
label=${t`TLS Authentication Certificate`} label=${t`TLS Authentication Certificate`}
name="tlsAuthentication"> name="tlsAuthentication">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.sc?.tlsAuthentication === undefined}>---------</option> <option value="" ?selected=${this.instance?.tlsAuthentication === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({ ${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk" ordering: "pk"
}).then(certs => { }).then(certs => {
return certs.results.map(cert => { return certs.results.map(cert => {
return html`<option value=${ifDefined(cert.pk)} ?selected=${this.sc?.tlsAuthentication === cert.pk}>${cert.name}</option>`; return html`<option value=${ifDefined(cert.pk)} ?selected=${this.instance?.tlsAuthentication === cert.pk}>${cert.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>

View File

@ -1,31 +1,26 @@
import { KubernetesServiceConnection, OutpostsApi } from "authentik-api"; import { KubernetesServiceConnection, OutpostsApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror"; import "../../elements/CodeMirror";
import YAML from "yaml"; import YAML from "yaml";
import { first } from "../../utils"; import { first } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-service-connection-kubernetes-form") @customElement("ak-service-connection-kubernetes-form")
export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConnection> { export class ServiceConnectionKubernetesForm extends ModelForm<KubernetesServiceConnection, string> {
set scUUID(value: string) { loadInstance(pk: string): Promise<KubernetesServiceConnection> {
new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsKubernetesRead({ return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsKubernetesRead({
uuid: value, uuid: pk,
}).then(sc => {
this.sc = sc;
}); });
} }
@property({attribute: false})
sc?: KubernetesServiceConnection;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.sc) { if (this.instance) {
return t`Successfully updated service-connection.`; return t`Successfully updated service-connection.`;
} else { } else {
return t`Successfully created service-connection.`; return t`Successfully created service-connection.`;
@ -33,9 +28,9 @@ export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConne
} }
send = (data: KubernetesServiceConnection): Promise<KubernetesServiceConnection> => { send = (data: KubernetesServiceConnection): Promise<KubernetesServiceConnection> => {
if (this.sc) { if (this.instance) {
return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsKubernetesUpdate({ return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsKubernetesUpdate({
uuid: this.sc.pk || "", uuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -51,11 +46,11 @@ export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConne
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.sc?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="local"> <ak-form-element-horizontal name="local">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.sc?.local, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.local, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Local`} ${t`Local`}
</label> </label>
@ -65,7 +60,7 @@ export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConne
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Kubeconfig`} label=${t`Kubeconfig`}
name="kubeconfig"> name="kubeconfig">
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.sc?.kubeconfig, {}))}"> <ak-codemirror mode="yaml" value="${YAML.stringify(first(this.instance?.kubeconfig, {}))}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p> <p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -82,7 +82,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
"scUUID": item.pk "instancePk": item.pk
}} }}
type=${ifDefined(item.component)}> type=${ifDefined(item.component)}>
</ak-proxy-form> </ak-proxy-form>

View File

@ -88,7 +88,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
<span slot="header"> <span slot="header">
${t`Update Group`} ${t`Update Group`}
</span> </span>
<ak-group-form slot="form" .group=${item.groupObj}> <ak-group-form slot="form" .instancePk=${item.groupObj?.pk}>
</ak-group-form> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit Group`} ${t`Edit Group`}
@ -102,7 +102,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
<span slot="header"> <span slot="header">
${t`Update User`} ${t`Update User`}
</span> </span>
<ak-user-form slot="form" .user=${item.userObj}> <ak-user-form slot="form" .instancePk=${item.userObj?.pk}>
</ak-user-form> </ak-user-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit User`} ${t`Edit User`}
@ -128,7 +128,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
<span slot="header"> <span slot="header">
${t`Update Binding`} ${t`Update Binding`}
</span> </span>
<ak-policy-binding-form slot="form" .binding=${item} targetPk=${ifDefined(this.target)} ?policyOnly=${this.policyOnly}> <ak-policy-binding-form slot="form" .instancePk=${item.pk} targetPk=${ifDefined(this.target)} ?policyOnly=${this.policyOnly}>
</ak-policy-binding-form> </ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit Binding`} ${t`Edit Binding`}

View File

@ -3,41 +3,38 @@ import { t } from "@lingui/macro";
import { css, CSSResult, customElement, property } from "lit-element"; import { css, CSSResult, customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import { first, groupBy } from "../../utils"; import { first, groupBy } from "../../utils";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import PFToggleGroup from "@patternfly/patternfly/components/ToggleGroup/toggle-group.css"; import PFToggleGroup from "@patternfly/patternfly/components/ToggleGroup/toggle-group.css";
import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css";
import { ModelForm } from "../../elements/forms/ModelForm";
enum target { enum target {
policy, group, user policy, group, user
} }
@customElement("ak-policy-binding-form") @customElement("ak-policy-binding-form")
export class PolicyBindingForm extends Form<PolicyBinding> { export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<PolicyBinding> {
set binding(value: PolicyBinding | undefined) { return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsRead({
this._binding = value; policyBindingUuid: pk
if (value?.policyObj) { }).then(binding => {
if (binding?.policyObj) {
this.policyGroupUser = target.policy; this.policyGroupUser = target.policy;
} }
if (value?.groupObj) { if (binding?.groupObj) {
this.policyGroupUser = target.group; this.policyGroupUser = target.group;
} }
if (value?.userObj) { if (binding?.userObj) {
this.policyGroupUser = target.user; this.policyGroupUser = target.user;
} }
return binding;
});
} }
get binding(): PolicyBinding | undefined {
return this._binding;
}
_binding?: PolicyBinding;
@property() @property()
targetPk?: string; targetPk?: string;
@ -48,7 +45,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
policyOnly = false; policyOnly = false;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.binding) { if (this.instance) {
return t`Successfully updated binding.`; return t`Successfully updated binding.`;
} else { } else {
return t`Successfully created binding.`; return t`Successfully created binding.`;
@ -64,9 +61,9 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
} }
send = (data: PolicyBinding): Promise<PolicyBinding> => { send = (data: PolicyBinding): Promise<PolicyBinding> => {
if (this.binding) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsUpdate({
policyBindingUuid: this.binding.pk || "", policyBindingUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -81,7 +78,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
${groupBy<Policy>(policies, (p => p.verboseName || "")).map(([group, policies]) => { ${groupBy<Policy>(policies, (p => p.verboseName || "")).map(([group, policies]) => {
return html`<optgroup label=${group}> return html`<optgroup label=${group}>
${policies.map(p => { ${policies.map(p => {
const selected = (this.binding?.policy === p.pk); const selected = (this.instance?.policy === p.pk);
return html`<option ?selected=${selected} value=${ifDefined(p.pk)}>${p.name}</option>`; return html`<option ?selected=${selected} value=${ifDefined(p.pk)}>${p.name}</option>`;
})} })}
</optgroup>`; </optgroup>`;
@ -90,8 +87,8 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
} }
getOrder(): Promise<number> { getOrder(): Promise<number> {
if (this.binding) { if (this.instance) {
return Promise.resolve(this.binding.order); return Promise.resolve(this.instance.order);
} }
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({ return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({
target: this.targetPk || "", target: this.targetPk || "",
@ -154,7 +151,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
name="policy" name="policy"
?hidden=${this.policyGroupUser !== target.policy}> ?hidden=${this.policyGroupUser !== target.policy}>
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.binding?.policy === undefined}>---------</option> <option value="" ?selected=${this.instance?.policy === undefined}>---------</option>
${until(new PoliciesApi(DEFAULT_CONFIG).policiesAllList({ ${until(new PoliciesApi(DEFAULT_CONFIG).policiesAllList({
ordering: "pk" ordering: "pk"
}).then(policies => { }).then(policies => {
@ -167,12 +164,12 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
name="group" name="group"
?hidden=${this.policyGroupUser !== target.group}> ?hidden=${this.policyGroupUser !== target.group}>
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.binding?.group === undefined}>---------</option> <option value="" ?selected=${this.instance?.group === undefined}>---------</option>
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({ ${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({
ordering: "pk" ordering: "pk"
}).then(groups => { }).then(groups => {
return groups.results.map(group => { return groups.results.map(group => {
return html`<option value=${ifDefined(group.pk)} ?selected=${group.pk === this.binding?.group}>${group.name}</option>`; return html`<option value=${ifDefined(group.pk)} ?selected=${group.pk === this.instance?.group}>${group.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -182,22 +179,22 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
name="user" name="user"
?hidden=${this.policyGroupUser !== target.user}> ?hidden=${this.policyGroupUser !== target.user}>
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.binding?.user === undefined}>---------</option> <option value="" ?selected=${this.instance?.user === undefined}>---------</option>
${until(new CoreApi(DEFAULT_CONFIG).coreUsersList({ ${until(new CoreApi(DEFAULT_CONFIG).coreUsersList({
ordering: "pk" ordering: "pk"
}).then(users => { }).then(users => {
return users.results.map(user => { return users.results.map(user => {
return html`<option value=${ifDefined(user.pk)} ?selected=${user.pk === this.binding?.user}>${user.name}</option>`; return html`<option value=${ifDefined(user.pk)} ?selected=${user.pk === this.instance?.user}>${user.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</div> </div>
<input required name="target" type="hidden" value=${ifDefined(this.binding?.target || this.targetPk)}> <input required name="target" type="hidden" value=${ifDefined(this.instance?.target || this.targetPk)}>
<ak-form-element-horizontal name="enabled"> <ak-form-element-horizontal name="enabled">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.binding?.enabled, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.enabled, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Enabled`} ${t`Enabled`}
</label> </label>
@ -213,7 +210,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
label=${t`Timeout`} label=${t`Timeout`}
?required=${true} ?required=${true}
name="timeout"> name="timeout">
<input type="number" value="${first(this.binding?.timeout, 30)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.timeout, 30)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -82,7 +82,7 @@ export class PolicyListPage extends TablePage<Policy> {
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
"policyUUID": item.pk "instancePk": item.pk
}} }}
type=${ifDefined(item.component)}> type=${ifDefined(item.component)}>
</ak-proxy-form> </ak-proxy-form>

View File

@ -1,30 +1,25 @@
import { DummyPolicy, PoliciesApi } from "authentik-api"; import { DummyPolicy, PoliciesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-policy-dummy-form") @customElement("ak-policy-dummy-form")
export class DummyPolicyForm extends Form<DummyPolicy> { export class DummyPolicyForm extends ModelForm<DummyPolicy, string> {
set policyUUID(value: string) { loadInstance(pk: string): Promise<DummyPolicy> {
new PoliciesApi(DEFAULT_CONFIG).policiesDummyRead({ return new PoliciesApi(DEFAULT_CONFIG).policiesDummyRead({
policyUuid: value, policyUuid: pk,
}).then(policy => {
this.policy = policy;
}); });
} }
@property({attribute: false})
policy?: DummyPolicy;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.instance) {
return t`Successfully updated policy.`; return t`Successfully updated policy.`;
} else { } else {
return t`Successfully created policy.`; return t`Successfully created policy.`;
@ -32,9 +27,9 @@ export class DummyPolicyForm extends Form<DummyPolicy> {
} }
send = (data: DummyPolicy): Promise<DummyPolicy> => { send = (data: DummyPolicy): Promise<DummyPolicy> => {
if (this.policy) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesDummyUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesDummyUpdate({
policyUuid: this.policy.pk || "", policyUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -53,11 +48,11 @@ export class DummyPolicyForm extends Form<DummyPolicy> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging"> <ak-form-element-horizontal name="executionLogging">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.executionLogging, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.executionLogging, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Execution logging`} ${t`Execution logging`}
</label> </label>
@ -73,7 +68,7 @@ export class DummyPolicyForm extends Form<DummyPolicy> {
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="result"> <ak-form-element-horizontal name="result">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.result, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.result, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Pass policy?`} ${t`Pass policy?`}
</label> </label>
@ -83,14 +78,14 @@ export class DummyPolicyForm extends Form<DummyPolicy> {
label=${t`Wait (min)`} label=${t`Wait (min)`}
?required=${true} ?required=${true}
name="waitMin"> name="waitMin">
<input type="number" value="${first(this.policy?.waitMin, 1)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.waitMin, 1)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`The policy takes a random time to execute. This controls the minimum time it will take.`}</p> <p class="pf-c-form__helper-text">${t`The policy takes a random time to execute. This controls the minimum time it will take.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Wait (max)`} label=${t`Wait (max)`}
?required=${true} ?required=${true}
name="waitMax"> name="waitMax">
<input type="number" value="${first(this.policy?.waitMax, 5)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.waitMax, 5)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>

View File

@ -1,31 +1,26 @@
import { AdminApi, EventMatcherPolicy, EventsApi, PoliciesApi } from "authentik-api"; import { AdminApi, EventMatcherPolicy, EventsApi, PoliciesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-policy-event-matcher-form") @customElement("ak-policy-event-matcher-form")
export class EventMatcherPolicyForm extends Form<EventMatcherPolicy> { export class EventMatcherPolicyForm extends ModelForm<EventMatcherPolicy, string> {
set policyUUID(value: string) { loadInstance(pk: string): Promise<EventMatcherPolicy> {
new PoliciesApi(DEFAULT_CONFIG).policiesEventMatcherRead({ return new PoliciesApi(DEFAULT_CONFIG).policiesEventMatcherRead({
policyUuid: value, policyUuid: pk,
}).then(policy => {
this.policy = policy;
}); });
} }
@property({attribute: false})
policy?: EventMatcherPolicy;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.instance) {
return t`Successfully updated policy.`; return t`Successfully updated policy.`;
} else { } else {
return t`Successfully created policy.`; return t`Successfully created policy.`;
@ -33,9 +28,9 @@ export class EventMatcherPolicyForm extends Form<EventMatcherPolicy> {
} }
send = (data: EventMatcherPolicy): Promise<EventMatcherPolicy> => { send = (data: EventMatcherPolicy): Promise<EventMatcherPolicy> => {
if (this.policy) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesEventMatcherUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesEventMatcherUpdate({
policyUuid: this.policy.pk || "", policyUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -54,11 +49,11 @@ export class EventMatcherPolicyForm extends Form<EventMatcherPolicy> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging"> <ak-form-element-horizontal name="executionLogging">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.executionLogging, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.executionLogging, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Execution logging`} ${t`Execution logging`}
</label> </label>
@ -76,10 +71,10 @@ export class EventMatcherPolicyForm extends Form<EventMatcherPolicy> {
label=${t`Action`} label=${t`Action`}
name="action"> name="action">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.policy?.action === undefined}>---------</option> <option value="" ?selected=${this.instance?.action === undefined}>---------</option>
${until(new EventsApi(DEFAULT_CONFIG).eventsEventsActions().then(actions => { ${until(new EventsApi(DEFAULT_CONFIG).eventsEventsActions().then(actions => {
return actions.map(action => { return actions.map(action => {
return html`<option value=${action.component} ?selected=${this.policy?.action === action.component}>${action.name}</option>`; return html`<option value=${action.component} ?selected=${this.instance?.action === action.component}>${action.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -88,17 +83,17 @@ export class EventMatcherPolicyForm extends Form<EventMatcherPolicy> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Client IP`} label=${t`Client IP`}
name="clientIp"> name="clientIp">
<input type="text" value="${ifDefined(this.policy?.clientIp || "")}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.clientIp || "")}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`Matches Event's Client IP (strict matching, for network matching use an Expression Policy.`}</p> <p class="pf-c-form__helper-text">${t`Matches Event's Client IP (strict matching, for network matching use an Expression Policy.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`App`} label=${t`App`}
name="app"> name="app">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.policy?.app === undefined}>---------</option> <option value="" ?selected=${this.instance?.app === undefined}>---------</option>
${until(new AdminApi(DEFAULT_CONFIG).adminAppsList().then(apps => { ${until(new AdminApi(DEFAULT_CONFIG).adminAppsList().then(apps => {
return apps.map(app => { return apps.map(app => {
return html`<option value=${app.name} ?selected=${this.policy?.app === app.name}>${app.label}</option>`; return html`<option value=${app.name} ?selected=${this.instance?.app === app.name}>${app.label}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>

View File

@ -1,30 +1,25 @@
import { PasswordExpiryPolicy, PoliciesApi } from "authentik-api"; import { PasswordExpiryPolicy, PoliciesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-policy-password-expiry-form") @customElement("ak-policy-password-expiry-form")
export class PasswordExpiryPolicyForm extends Form<PasswordExpiryPolicy> { export class PasswordExpiryPolicyForm extends ModelForm<PasswordExpiryPolicy, string> {
set policyUUID(value: string) { loadInstance(pk: string): Promise<PasswordExpiryPolicy> {
new PoliciesApi(DEFAULT_CONFIG).policiesPasswordExpiryRead({ return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordExpiryRead({
policyUuid: value, policyUuid: pk,
}).then(policy => {
this.policy = policy;
}); });
} }
@property({attribute: false})
policy?: PasswordExpiryPolicy;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.instance) {
return t`Successfully updated policy.`; return t`Successfully updated policy.`;
} else { } else {
return t`Successfully created policy.`; return t`Successfully created policy.`;
@ -32,9 +27,9 @@ export class PasswordExpiryPolicyForm extends Form<PasswordExpiryPolicy> {
} }
send = (data: PasswordExpiryPolicy): Promise<PasswordExpiryPolicy> => { send = (data: PasswordExpiryPolicy): Promise<PasswordExpiryPolicy> => {
if (this.policy) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordExpiryUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordExpiryUpdate({
policyUuid: this.policy.pk || "", policyUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -53,11 +48,11 @@ export class PasswordExpiryPolicyForm extends Form<PasswordExpiryPolicy> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging"> <ak-form-element-horizontal name="executionLogging">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.executionLogging, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.executionLogging, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Execution logging`} ${t`Execution logging`}
</label> </label>
@ -75,11 +70,11 @@ export class PasswordExpiryPolicyForm extends Form<PasswordExpiryPolicy> {
label=${t`Maximum age (in days)`} label=${t`Maximum age (in days)`}
?required=${true} ?required=${true}
name="days"> name="days">
<input type="number" value="${ifDefined(this.policy?.days || "")}" class="pf-c-form-control" required> <input type="number" value="${ifDefined(this.instance?.days || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="denyOnly"> <ak-form-element-horizontal name="denyOnly">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.denyOnly, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.denyOnly, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Only fail the policy, don't invalidate user's password.`} ${t`Only fail the policy, don't invalidate user's password.`}
</label> </label>

View File

@ -1,31 +1,26 @@
import { ExpressionPolicy, PoliciesApi } from "authentik-api"; import { ExpressionPolicy, PoliciesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import "../../../elements/CodeMirror"; import "../../../elements/CodeMirror";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-policy-expression-form") @customElement("ak-policy-expression-form")
export class ExpressionPolicyForm extends Form<ExpressionPolicy> { export class ExpressionPolicyForm extends ModelForm<ExpressionPolicy, string> {
set policyUUID(value: string) { loadInstance(pk: string): Promise<ExpressionPolicy> {
new PoliciesApi(DEFAULT_CONFIG).policiesExpressionRead({ return new PoliciesApi(DEFAULT_CONFIG).policiesExpressionRead({
policyUuid: value, policyUuid: pk,
}).then(policy => {
this.policy = policy;
}); });
} }
@property({attribute: false})
policy?: ExpressionPolicy;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.instance) {
return t`Successfully updated policy.`; return t`Successfully updated policy.`;
} else { } else {
return t`Successfully created policy.`; return t`Successfully created policy.`;
@ -33,9 +28,9 @@ export class ExpressionPolicyForm extends Form<ExpressionPolicy> {
} }
send = (data: ExpressionPolicy): Promise<ExpressionPolicy> => { send = (data: ExpressionPolicy): Promise<ExpressionPolicy> => {
if (this.policy) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesExpressionUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesExpressionUpdate({
policyUuid: this.policy.pk || "", policyUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -54,11 +49,11 @@ export class ExpressionPolicyForm extends Form<ExpressionPolicy> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging"> <ak-form-element-horizontal name="executionLogging">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.executionLogging, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.executionLogging, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Execution logging`} ${t`Execution logging`}
</label> </label>
@ -76,7 +71,7 @@ export class ExpressionPolicyForm extends Form<ExpressionPolicy> {
label=${t`Expression`} label=${t`Expression`}
?required=${true} ?required=${true}
name="expression"> name="expression">
<ak-codemirror mode="python" value="${ifDefined(this.policy?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${t`Expression using Python.`}

View File

@ -1,30 +1,25 @@
import { HaveIBeenPwendPolicy, PoliciesApi } from "authentik-api"; import { HaveIBeenPwendPolicy, PoliciesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-policy-hibp-form") @customElement("ak-policy-hibp-form")
export class HaveIBeenPwnedPolicyForm extends Form<HaveIBeenPwendPolicy> { export class HaveIBeenPwnedPolicyForm extends ModelForm<HaveIBeenPwendPolicy, string> {
set policyUUID(value: string) { loadInstance(pk: string): Promise<HaveIBeenPwendPolicy> {
new PoliciesApi(DEFAULT_CONFIG).policiesHaveibeenpwnedRead({ return new PoliciesApi(DEFAULT_CONFIG).policiesHaveibeenpwnedRead({
policyUuid: value, policyUuid: pk,
}).then(policy => {
this.policy = policy;
}); });
} }
@property({attribute: false})
policy?: HaveIBeenPwendPolicy;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.instance) {
return t`Successfully updated policy.`; return t`Successfully updated policy.`;
} else { } else {
return t`Successfully created policy.`; return t`Successfully created policy.`;
@ -32,9 +27,9 @@ export class HaveIBeenPwnedPolicyForm extends Form<HaveIBeenPwendPolicy> {
} }
send = (data: HaveIBeenPwendPolicy): Promise<HaveIBeenPwendPolicy> => { send = (data: HaveIBeenPwendPolicy): Promise<HaveIBeenPwendPolicy> => {
if (this.policy) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesHaveibeenpwnedUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesHaveibeenpwnedUpdate({
policyUuid: this.policy.pk || "", policyUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -54,11 +49,11 @@ export class HaveIBeenPwnedPolicyForm extends Form<HaveIBeenPwendPolicy> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging"> <ak-form-element-horizontal name="executionLogging">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.executionLogging, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.executionLogging, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Execution logging`} ${t`Execution logging`}
</label> </label>
@ -76,14 +71,14 @@ export class HaveIBeenPwnedPolicyForm extends Form<HaveIBeenPwendPolicy> {
label=${t`Password field`} label=${t`Password field`}
?required=${true} ?required=${true}
name="passwordField"> name="passwordField">
<input type="text" value="${ifDefined(this.policy?.passwordField || "password")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.passwordField || "password")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Field key to check, field keys defined in Prompt stages are available.`}</p> <p class="pf-c-form__helper-text">${t`Field key to check, field keys defined in Prompt stages are available.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Allowed count`} label=${t`Allowed count`}
?required=${true} ?required=${true}
name="allowedCount"> name="allowedCount">
<input type="number" value="${first(this.policy?.allowedCount, 0)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.allowedCount, 0)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Allow up to N occurrences in the HIBP database.`}</p> <p class="pf-c-form__helper-text">${t`Allow up to N occurrences in the HIBP database.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -1,30 +1,25 @@
import { PasswordPolicy, PoliciesApi } from "authentik-api"; import { PasswordPolicy, PoliciesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-policy-password-form") @customElement("ak-policy-password-form")
export class PasswordPolicyForm extends Form<PasswordPolicy> { export class PasswordPolicyForm extends ModelForm<PasswordPolicy, string> {
set policyUUID(value: string) { loadInstance(pk: string): Promise<PasswordPolicy> {
new PoliciesApi(DEFAULT_CONFIG).policiesPasswordRead({ return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordRead({
policyUuid: value, policyUuid: pk,
}).then(policy => {
this.policy = policy;
}); });
} }
@property({attribute: false})
policy?: PasswordPolicy;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.instance) {
return t`Successfully updated policy.`; return t`Successfully updated policy.`;
} else { } else {
return t`Successfully created policy.`; return t`Successfully created policy.`;
@ -32,9 +27,9 @@ export class PasswordPolicyForm extends Form<PasswordPolicy> {
} }
send = (data: PasswordPolicy): Promise<PasswordPolicy> => { send = (data: PasswordPolicy): Promise<PasswordPolicy> => {
if (this.policy) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordUpdate({
policyUuid: this.policy.pk || "", policyUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -53,11 +48,11 @@ export class PasswordPolicyForm extends Form<PasswordPolicy> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging"> <ak-form-element-horizontal name="executionLogging">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.executionLogging, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.executionLogging, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Execution logging`} ${t`Execution logging`}
</label> </label>
@ -75,7 +70,7 @@ export class PasswordPolicyForm extends Form<PasswordPolicy> {
label=${t`Password field`} label=${t`Password field`}
?required=${true} ?required=${true}
name="passwordField"> name="passwordField">
<input type="text" value="${ifDefined(this.policy?.passwordField || "password")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.passwordField || "password")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Field key to check, field keys defined in Prompt stages are available.`}</p> <p class="pf-c-form__helper-text">${t`Field key to check, field keys defined in Prompt stages are available.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -83,31 +78,31 @@ export class PasswordPolicyForm extends Form<PasswordPolicy> {
label=${t`Minimum length`} label=${t`Minimum length`}
?required=${true} ?required=${true}
name="lengthMin"> name="lengthMin">
<input type="number" value="${first(this.policy?.lengthMin, 10)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.lengthMin, 10)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum amount of Uppercase Characters`} label=${t`Minimum amount of Uppercase Characters`}
?required=${true} ?required=${true}
name="amountUppercase"> name="amountUppercase">
<input type="number" value="${first(this.policy?.amountUppercase, 2)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.amountUppercase, 2)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum amount of Lowercase Characters`} label=${t`Minimum amount of Lowercase Characters`}
?required=${true} ?required=${true}
name="amountLowercase"> name="amountLowercase">
<input type="number" value="${first(this.policy?.amountLowercase, 2)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.amountLowercase, 2)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Minimum amount of Symbols Characters`} label=${t`Minimum amount of Symbols Characters`}
?required=${true} ?required=${true}
name="amountSymbols"> name="amountSymbols">
<input type="number" value="${first(this.policy?.amountSymbols, 2)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.amountSymbols, 2)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Error message`} label=${t`Error message`}
?required=${true} ?required=${true}
name="errorMessage"> name="errorMessage">
<input type="text" value="${ifDefined(this.policy?.errorMessage)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.errorMessage)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>
@ -120,7 +115,7 @@ export class PasswordPolicyForm extends Form<PasswordPolicy> {
label=${t`Symbol charset`} label=${t`Symbol charset`}
?required=${true} ?required=${true}
name="symbolCharset"> name="symbolCharset">
<input type="text" value="${ifDefined(this.policy?.symbolCharset || "!\\\"#$%&'()*+,-./:;<=>?@[]^_`{|}~ ")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.symbolCharset || "!\\\"#$%&'()*+,-./:;<=>?@[]^_`{|}~ ")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Characters which are considered as symbols.`}</p> <p class="pf-c-form__helper-text">${t`Characters which are considered as symbols.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -1,30 +1,25 @@
import { ReputationPolicy, PoliciesApi } from "authentik-api"; import { ReputationPolicy, PoliciesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-policy-reputation-form") @customElement("ak-policy-reputation-form")
export class ReputationPolicyForm extends Form<ReputationPolicy> { export class ReputationPolicyForm extends ModelForm<ReputationPolicy, string> {
set policyUUID(value: string) { loadInstance(pk: string): Promise<ReputationPolicy> {
new PoliciesApi(DEFAULT_CONFIG).policiesReputationRead({ return new PoliciesApi(DEFAULT_CONFIG).policiesReputationRead({
policyUuid: value, policyUuid: pk,
}).then(policy => {
this.policy = policy;
}); });
} }
@property({attribute: false})
policy?: ReputationPolicy;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.instance) {
return t`Successfully updated policy.`; return t`Successfully updated policy.`;
} else { } else {
return t`Successfully created policy.`; return t`Successfully created policy.`;
@ -32,9 +27,9 @@ export class ReputationPolicyForm extends Form<ReputationPolicy> {
} }
send = (data: ReputationPolicy): Promise<ReputationPolicy> => { send = (data: ReputationPolicy): Promise<ReputationPolicy> => {
if (this.policy) { if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUpdate({ return new PoliciesApi(DEFAULT_CONFIG).policiesReputationUpdate({
policyUuid: this.policy.pk || "", policyUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -53,11 +48,11 @@ export class ReputationPolicyForm extends Form<ReputationPolicy> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="executionLogging"> <ak-form-element-horizontal name="executionLogging">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.executionLogging, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.executionLogging, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Execution logging`} ${t`Execution logging`}
</label> </label>
@ -73,7 +68,7 @@ export class ReputationPolicyForm extends Form<ReputationPolicy> {
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="checkIp"> <ak-form-element-horizontal name="checkIp">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.checkIp, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.checkIp, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Check IP`} ${t`Check IP`}
</label> </label>
@ -81,7 +76,7 @@ export class ReputationPolicyForm extends Form<ReputationPolicy> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="checkUsername"> <ak-form-element-horizontal name="checkUsername">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.policy?.checkUsername, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.checkUsername, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Check Username`} ${t`Check Username`}
</label> </label>
@ -91,7 +86,7 @@ export class ReputationPolicyForm extends Form<ReputationPolicy> {
label=${t`Threshold`} label=${t`Threshold`}
?required=${true} ?required=${true}
name="threshold"> name="threshold">
<input type="number" value="${ifDefined(this.policy?.threshold || -5)}" class="pf-c-form-control" required> <input type="number" value="${ifDefined(this.instance?.threshold || -5)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>

View File

@ -1,29 +1,24 @@
import { LDAPPropertyMapping, PropertymappingsApi } from "authentik-api"; import { LDAPPropertyMapping, PropertymappingsApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror"; import "../../elements/CodeMirror";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-property-mapping-ldap-form") @customElement("ak-property-mapping-ldap-form")
export class PropertyMappingLDAPForm extends Form<LDAPPropertyMapping> { export class PropertyMappingLDAPForm extends ModelForm<LDAPPropertyMapping, string> {
set mappingUUID(value: string) { loadInstance(pk: string): Promise<LDAPPropertyMapping> {
new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsLdapRead({ return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsLdapRead({
pmUuid: value, pmUuid: pk,
}).then(mapping => {
this.mapping = mapping;
}); });
} }
@property({attribute: false})
mapping?: LDAPPropertyMapping;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.mapping) { if (this.instance) {
return t`Successfully updated mapping.`; return t`Successfully updated mapping.`;
} else { } else {
return t`Successfully created mapping.`; return t`Successfully created mapping.`;
@ -31,9 +26,9 @@ export class PropertyMappingLDAPForm extends Form<LDAPPropertyMapping> {
} }
send = (data: LDAPPropertyMapping): Promise<LDAPPropertyMapping> => { send = (data: LDAPPropertyMapping): Promise<LDAPPropertyMapping> => {
if (this.mapping) { if (this.instance) {
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsLdapUpdate({ return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsLdapUpdate({
pmUuid: this.mapping.pk || "", pmUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -49,20 +44,20 @@ export class PropertyMappingLDAPForm extends Form<LDAPPropertyMapping> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.mapping?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Object field`} label=${t`Object field`}
?required=${true} ?required=${true}
name="objectField"> name="objectField">
<input type="text" value="${ifDefined(this.mapping?.objectField)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.objectField)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Field of the user object this value is written to.`}</p> <p class="pf-c-form__helper-text">${t`Field of the user object this value is written to.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Expression`} label=${t`Expression`}
?required=${true} ?required=${true}
name="expression"> name="expression">
<ak-codemirror mode="python" value="${ifDefined(this.mapping?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${t`Expression using Python.`}

View File

@ -1,29 +1,23 @@
import { SAMLPropertyMapping, PropertymappingsApi } from "authentik-api"; import { SAMLPropertyMapping, PropertymappingsApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror"; import "../../elements/CodeMirror";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-property-mapping-saml-form") @customElement("ak-property-mapping-saml-form")
export class PropertyMappingLDAPForm extends Form<SAMLPropertyMapping> { export class PropertyMappingLDAPForm extends ModelForm<SAMLPropertyMapping, string> {
loadInstance(pk: string): Promise<SAMLPropertyMapping> {
set mappingUUID(value: string) { return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlRead({
new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlRead({ pmUuid: pk,
pmUuid: value,
}).then(mapping => {
this.mapping = mapping;
}); });
} }
@property({attribute: false})
mapping?: SAMLPropertyMapping;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.mapping) { if (this.instance) {
return t`Successfully updated mapping.`; return t`Successfully updated mapping.`;
} else { } else {
return t`Successfully created mapping.`; return t`Successfully created mapping.`;
@ -31,9 +25,9 @@ export class PropertyMappingLDAPForm extends Form<SAMLPropertyMapping> {
} }
send = (data: SAMLPropertyMapping): Promise<SAMLPropertyMapping> => { send = (data: SAMLPropertyMapping): Promise<SAMLPropertyMapping> => {
if (this.mapping) { if (this.instance) {
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlUpdate({ return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlUpdate({
pmUuid: this.mapping.pk || "", pmUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -49,13 +43,13 @@ export class PropertyMappingLDAPForm extends Form<SAMLPropertyMapping> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.mapping?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`SAML Attribute Name`} label=${t`SAML Attribute Name`}
?required=${true} ?required=${true}
name="samlName"> name="samlName">
<input type="text" value="${ifDefined(this.mapping?.samlName)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.samlName)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded.`} ${t`Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded.`}
</p> </p>
@ -63,7 +57,7 @@ export class PropertyMappingLDAPForm extends Form<SAMLPropertyMapping> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Friendly Name`} label=${t`Friendly Name`}
name="friendlyName"> name="friendlyName">
<input type="text" value="${ifDefined(this.mapping?.friendlyName || "")}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.friendlyName || "")}" class="pf-c-form-control">
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Optionally set the 'FriendlyName' value of the Assertion attribute.`} ${t`Optionally set the 'FriendlyName' value of the Assertion attribute.`}
</p> </p>
@ -72,7 +66,7 @@ export class PropertyMappingLDAPForm extends Form<SAMLPropertyMapping> {
label=${t`Expression`} label=${t`Expression`}
?required=${true} ?required=${true}
name="expression"> name="expression">
<ak-codemirror mode="python" value="${ifDefined(this.mapping?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${t`Expression using Python.`}

View File

@ -1,29 +1,24 @@
import { ScopeMapping, PropertymappingsApi } from "authentik-api"; import { ScopeMapping, PropertymappingsApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form"; import { ModelForm } from "../../elements/forms/ModelForm";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror"; import "../../elements/CodeMirror";
@customElement("ak-property-mapping-scope-form") @customElement("ak-property-mapping-scope-form")
export class PropertyMappingScopeForm extends Form<ScopeMapping> { export class PropertyMappingScopeForm extends ModelForm<ScopeMapping, string> {
set mappingUUID(value: string) { loadInstance(pk: string): Promise<ScopeMapping> {
new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsScopeRead({ return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsScopeRead({
pmUuid: value, pmUuid: pk,
}).then(mapping => {
this.mapping = mapping;
}); });
} }
@property({attribute: false})
mapping?: ScopeMapping;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.mapping) { if (this.instance) {
return t`Successfully updated mapping.`; return t`Successfully updated mapping.`;
} else { } else {
return t`Successfully created mapping.`; return t`Successfully created mapping.`;
@ -31,9 +26,9 @@ export class PropertyMappingScopeForm extends Form<ScopeMapping> {
} }
send = (data: ScopeMapping): Promise<ScopeMapping> => { send = (data: ScopeMapping): Promise<ScopeMapping> => {
if (this.mapping) { if (this.instance) {
return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsScopeUpdate({ return new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsScopeUpdate({
pmUuid: this.mapping.pk || "", pmUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -49,27 +44,27 @@ export class PropertyMappingScopeForm extends Form<ScopeMapping> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.mapping?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Scope name`} label=${t`Scope name`}
?required=${true} ?required=${true}
name="scopeName"> name="scopeName">
<input type="text" value="${ifDefined(this.mapping?.scopeName)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.scopeName)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Scope which the client can specify to access these properties.`}</p> <p class="pf-c-form__helper-text">${t`Scope which the client can specify to access these properties.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Description`} label=${t`Description`}
?required=${true} ?required=${true}
name="description"> name="description">
<input type="text" value="${ifDefined(this.mapping?.description)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.description)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Description shown to the user when consenting. If left empty, the user won't be informed.`}</p> <p class="pf-c-form__helper-text">${t`Description shown to the user when consenting. If left empty, the user won't be informed.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Expression`} label=${t`Expression`}
?required=${true} ?required=${true}
name="expression"> name="expression">
<ak-codemirror mode="python" value="${ifDefined(this.mapping?.expression)}"> <ak-codemirror mode="python" value="${ifDefined(this.instance?.expression)}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Expression using Python.`} ${t`Expression using Python.`}

View File

@ -79,7 +79,7 @@ export class ProviderListPage extends TablePage<Provider> {
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
"providerUUID": item.pk "instancePk": item.pk
}} }}
type=${ifDefined(item.component)}> type=${ifDefined(item.component)}>
</ak-proxy-form> </ak-proxy-form>

View File

@ -1,9 +1,9 @@
import { FlowDesignationEnum, FlowsApi, ProvidersApi, LDAPProvider, CoreApi } from "authentik-api"; import { FlowDesignationEnum, FlowsApi, ProvidersApi, LDAPProvider, CoreApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form"; import { ModelForm } from "../../../elements/forms/ModelForm";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
@ -11,21 +11,16 @@ import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
@customElement("ak-provider-ldap-form") @customElement("ak-provider-ldap-form")
export class LDAPProviderFormPage extends Form<LDAPProvider> { export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
set providerUUID(value: number) { loadInstance(pk: number): Promise<LDAPProvider> {
new ProvidersApi(DEFAULT_CONFIG).providersLdapRead({ return new ProvidersApi(DEFAULT_CONFIG).providersLdapRead({
id: value, id: pk,
}).then(provider => {
this.provider = provider;
}); });
} }
@property({attribute: false})
provider?: LDAPProvider;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.provider) { if (this.instance) {
return t`Successfully updated provider.`; return t`Successfully updated provider.`;
} else { } else {
return t`Successfully created provider.`; return t`Successfully created provider.`;
@ -33,9 +28,9 @@ export class LDAPProviderFormPage extends Form<LDAPProvider> {
} }
send = (data: LDAPProvider): Promise<LDAPProvider> => { send = (data: LDAPProvider): Promise<LDAPProvider> => {
if (this.provider) { if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersLdapUpdate({ return new ProvidersApi(DEFAULT_CONFIG).providersLdapUpdate({
id: this.provider.pk || 0, id: this.instance.pk || 0,
data: data data: data
}); });
} else { } else {
@ -51,7 +46,7 @@ export class LDAPProviderFormPage extends Form<LDAPProvider> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.provider?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Bind flow`} label=${t`Bind flow`}
@ -63,7 +58,7 @@ export class LDAPProviderFormPage extends Form<LDAPProvider> {
designation: FlowDesignationEnum.Authentication, designation: FlowDesignationEnum.Authentication,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
return html`<option value=${ifDefined(flow.pk)} ?selected=${this.provider?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${this.instance?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -73,10 +68,10 @@ export class LDAPProviderFormPage extends Form<LDAPProvider> {
label=${t`Group`} label=${t`Group`}
name="searchGroup"> name="searchGroup">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.provider?.searchGroup === undefined}>---------</option> <option value="" ?selected=${this.instance?.searchGroup === undefined}>---------</option>
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => { ${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => {
return groups.results.map(group => { return groups.results.map(group => {
return html`<option value=${ifDefined(group.pk)} ?selected=${this.provider?.searchGroup === group.pk}>${group.name}</option>`; return html`<option value=${ifDefined(group.pk)} ?selected=${this.instance?.searchGroup === group.pk}>${group.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -92,7 +87,7 @@ export class LDAPProviderFormPage extends Form<LDAPProvider> {
label=${t`Base DN`} label=${t`Base DN`}
?required=${true} ?required=${true}
name="baseDn"> name="baseDn">
<input type="text" value="${first(this.provider?.baseDn, "DC=ldap,DC=goauthentik,DC=io")}" class="pf-c-form-control" required> <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> <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>
</div> </div>

View File

@ -102,7 +102,7 @@ export class LDAPProviderViewPage extends LitElement {
</span> </span>
<ak-provider-ldap-form <ak-provider-ldap-form
slot="form" slot="form"
.providerUUID=${this.provider.pk || 0}> .instancePk=${this.provider.pk || 0}>
</ak-provider-ldap-form> </ak-provider-ldap-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -3,7 +3,7 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form"; import { ModelForm } from "../../../elements/forms/ModelForm";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
@ -11,25 +11,22 @@ import "../../../elements/forms/FormGroup";
import { first, randomString } from "../../../utils"; import { first, randomString } from "../../../utils";
@customElement("ak-provider-oauth2-form") @customElement("ak-provider-oauth2-form")
export class OAuth2ProviderFormPage extends Form<OAuth2Provider> { export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
set providerUUID(value: number) { loadInstance(pk: number): Promise<OAuth2Provider> {
new ProvidersApi(DEFAULT_CONFIG).providersOauth2Read({ return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Read({
id: value, id: pk,
}).then(provider => { }).then(provider => {
this.provider = provider;
this.showClientSecret = provider.clientType === OAuth2ProviderClientTypeEnum.Confidential; this.showClientSecret = provider.clientType === OAuth2ProviderClientTypeEnum.Confidential;
return provider;
}); });
} }
@property({attribute: false})
provider?: OAuth2Provider;
@property({type: Boolean}) @property({type: Boolean})
showClientSecret = true; showClientSecret = true;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.provider) { if (this.instance) {
return t`Successfully updated provider.`; return t`Successfully updated provider.`;
} else { } else {
return t`Successfully created provider.`; return t`Successfully created provider.`;
@ -37,9 +34,9 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
} }
send = (data: OAuth2Provider): Promise<OAuth2Provider> => { send = (data: OAuth2Provider): Promise<OAuth2Provider> => {
if (this.provider) { if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Update({ return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Update({
id: this.provider.pk || 0, id: this.instance.pk || 0,
data: data data: data
}); });
} else { } else {
@ -55,7 +52,7 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.provider?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authorization flow`} label=${t`Authorization flow`}
@ -67,7 +64,7 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
designation: FlowDesignationEnum.Authorization, designation: FlowDesignationEnum.Authorization,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
return html`<option value=${ifDefined(flow.pk)} ?selected=${this.provider?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${this.instance?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -91,10 +88,10 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
this.showClientSecret = true; this.showClientSecret = true;
} }
}}> }}>
<option value=${OAuth2ProviderClientTypeEnum.Confidential} ?selected=${this.provider?.clientType === OAuth2ProviderClientTypeEnum.Confidential}> <option value=${OAuth2ProviderClientTypeEnum.Confidential} ?selected=${this.instance?.clientType === OAuth2ProviderClientTypeEnum.Confidential}>
${t`Confidential`} ${t`Confidential`}
</option> </option>
<option value=${OAuth2ProviderClientTypeEnum.Public} ?selected=${this.provider?.clientType === OAuth2ProviderClientTypeEnum.Public}> <option value=${OAuth2ProviderClientTypeEnum.Public} ?selected=${this.instance?.clientType === OAuth2ProviderClientTypeEnum.Public}>
${t`Public`} ${t`Public`}
</option> </option>
</select> </select>
@ -104,19 +101,19 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
label=${t`Client ID`} label=${t`Client ID`}
?required=${true} ?required=${true}
name="clientId"> name="clientId">
<input type="text" value="${first(this.provider?.clientId, randomString(40))}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.clientId, randomString(40))}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
?hidden=${!this.showClientSecret} ?hidden=${!this.showClientSecret}
label=${t`Client Secret`} label=${t`Client Secret`}
name="clientSecret"> name="clientSecret">
<input type="text" value="${first(this.provider?.clientSecret, randomString(128))}" class="pf-c-form-control"> <input type="text" value="${first(this.instance?.clientSecret, randomString(128))}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Redirect URIs/Origins`} label=${t`Redirect URIs/Origins`}
?required=${true} ?required=${true}
name="redirectUris"> name="redirectUris">
<textarea class="pf-c-form-control" required>${this.provider?.redirectUris}</textarea> <textarea class="pf-c-form-control" required>${this.instance?.redirectUris}</textarea>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.`} ${t`Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.`}
</p> </p>
@ -133,7 +130,7 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
label=${t`Access code validity`} label=${t`Access code validity`}
?required=${true} ?required=${true}
name="accessCodeValidity"> name="accessCodeValidity">
<input type="text" value="${first(this.provider?.accessCodeValidity, "minutes=1")}" class="pf-c-form-control" required> <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`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> <p class="pf-c-form__helper-text">${t`(Format: hours=-1;minutes=-2;seconds=-3).`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -141,7 +138,7 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
label=${t`Token validity`} label=${t`Token validity`}
?required=${true} ?required=${true}
name="tokenValidity"> name="tokenValidity">
<input type="text" value="${first(this.provider?.tokenValidity, "minutes=10")}" class="pf-c-form-control" required> <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`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> <p class="pf-c-form__helper-text">${t`(Format: hours=-1;minutes=-2;seconds=-3).`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -150,10 +147,10 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
?required=${true} ?required=${true}
name="jwtAlg"> name="jwtAlg">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${OAuth2ProviderJwtAlgEnum.Rs256} ?selected=${this.provider?.jwtAlg === OAuth2ProviderJwtAlgEnum.Rs256}> <option value=${OAuth2ProviderJwtAlgEnum.Rs256} ?selected=${this.instance?.jwtAlg === OAuth2ProviderJwtAlgEnum.Rs256}>
${t`RS256 (Asymmetric Encryption)`} ${t`RS256 (Asymmetric Encryption)`}
</option> </option>
<option value=${OAuth2ProviderJwtAlgEnum.Hs256} ?selected=${this.provider?.jwtAlg === OAuth2ProviderJwtAlgEnum.Hs256}> <option value=${OAuth2ProviderJwtAlgEnum.Hs256} ?selected=${this.instance?.jwtAlg === OAuth2ProviderJwtAlgEnum.Hs256}>
${t`HS256 (Symmetric Encryption)`} ${t`HS256 (Symmetric Encryption)`}
</option> </option>
</select> </select>
@ -168,10 +165,10 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
}).then(scopes => { }).then(scopes => {
return scopes.results.map(scope => { return scopes.results.map(scope => {
let selected = false; let selected = false;
if (!this.provider?.propertyMappings) { if (!this.instance?.propertyMappings) {
selected = scope.managed?.startsWith("goauthentik.io/providers/oauth2/scope-") || false; selected = scope.managed?.startsWith("goauthentik.io/providers/oauth2/scope-") || false;
} else { } else {
selected = Array.from(this.provider?.propertyMappings).some(su => { selected = Array.from(this.instance?.propertyMappings).some(su => {
return su == scope.pk; return su == scope.pk;
}); });
} }
@ -186,13 +183,13 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
label=${t`RSA Key`} label=${t`RSA Key`}
name="rsaKey"> name="rsaKey">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.provider?.rsaKey === undefined}>---------</option> <option value="" ?selected=${this.instance?.rsaKey === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({ ${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk", ordering: "pk",
hasKey: "true", hasKey: "true",
}).then(keys => { }).then(keys => {
return keys.results.map(key => { return keys.results.map(key => {
let selected = this.provider?.rsaKey === key.pk; let selected = this.instance?.rsaKey === key.pk;
if (keys.results.length === 1) { if (keys.results.length === 1) {
selected = true; selected = true;
} }
@ -207,16 +204,16 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
?required=${true} ?required=${true}
name="subMode"> name="subMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="${OAuth2ProviderSubModeEnum.HashedUserId}" ?selected=${this.provider?.subMode === OAuth2ProviderSubModeEnum.HashedUserId}> <option value="${OAuth2ProviderSubModeEnum.HashedUserId}" ?selected=${this.instance?.subMode === OAuth2ProviderSubModeEnum.HashedUserId}>
${t`Based on the Hashed User ID`} ${t`Based on the Hashed User ID`}
</option> </option>
<option value="${OAuth2ProviderSubModeEnum.UserUsername}" ?selected=${this.provider?.subMode === OAuth2ProviderSubModeEnum.UserUsername}> <option value="${OAuth2ProviderSubModeEnum.UserUsername}" ?selected=${this.instance?.subMode === OAuth2ProviderSubModeEnum.UserUsername}>
${t`Based on the username`} ${t`Based on the username`}
</option> </option>
<option value="${OAuth2ProviderSubModeEnum.UserEmail}" ?selected=${this.provider?.subMode === OAuth2ProviderSubModeEnum.UserEmail}> <option value="${OAuth2ProviderSubModeEnum.UserEmail}" ?selected=${this.instance?.subMode === OAuth2ProviderSubModeEnum.UserEmail}>
${t`Based on the User's Email. This is recommended over the UPN method.`} ${t`Based on the User's Email. This is recommended over the UPN method.`}
</option> </option>
<option value="${OAuth2ProviderSubModeEnum.UserUpn}" ?selected=${this.provider?.subMode === OAuth2ProviderSubModeEnum.UserUpn}> <option value="${OAuth2ProviderSubModeEnum.UserUpn}" ?selected=${this.instance?.subMode === OAuth2ProviderSubModeEnum.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.`} ${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> </option>
</select> </select>
@ -226,7 +223,7 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="includeClaimsInIdToken"> <ak-form-element-horizontal name="includeClaimsInIdToken">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.provider?.includeClaimsInIdToken, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.includeClaimsInIdToken, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Include claims in id_token`} ${t`Include claims in id_token`}
</label> </label>
@ -238,10 +235,10 @@ export class OAuth2ProviderFormPage extends Form<OAuth2Provider> {
?required=${true} ?required=${true}
name="issuerMode"> name="issuerMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="${OAuth2ProviderIssuerModeEnum.PerProvider}" ?selected=${this.provider?.issuerMode === OAuth2ProviderIssuerModeEnum.PerProvider}> <option value="${OAuth2ProviderIssuerModeEnum.PerProvider}" ?selected=${this.instance?.issuerMode === OAuth2ProviderIssuerModeEnum.PerProvider}>
${t`Each provider has a different issuer, based on the application slug.`} ${t`Each provider has a different issuer, based on the application slug.`}
</option> </option>
<option value="${OAuth2ProviderIssuerModeEnum.Global}" ?selected=${this.provider?.issuerMode === OAuth2ProviderIssuerModeEnum.Global}> <option value="${OAuth2ProviderIssuerModeEnum.Global}" ?selected=${this.instance?.issuerMode === OAuth2ProviderIssuerModeEnum.Global}>
${t`Same identifier is used for all providers`} ${t`Same identifier is used for all providers`}
</option> </option>
</select> </select>

View File

@ -127,7 +127,7 @@ export class OAuth2ProviderViewPage extends LitElement {
</span> </span>
<ak-provider-oauth2-form <ak-provider-oauth2-form
slot="form" slot="form"
.providerUUID=${this.provider.pk || 0}> .instancePk=${this.provider.pk || 0}>
</ak-provider-oauth2-form> </ak-provider-oauth2-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -3,7 +3,7 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form"; import { ModelForm } from "../../../elements/forms/ModelForm";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
@ -11,21 +11,18 @@ import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
@customElement("ak-provider-proxy-form") @customElement("ak-provider-proxy-form")
export class ProxyProviderFormPage extends Form<ProxyProvider> { export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
set providerUUID(value: number) { loadInstance(pk: number): Promise<ProxyProvider> {
new ProvidersApi(DEFAULT_CONFIG).providersProxyRead({ return new ProvidersApi(DEFAULT_CONFIG).providersProxyRead({
id: value, id: pk,
}).then(provider => { }).then(provider => {
this.provider = provider;
this.showHttpBasic = first(provider.basicAuthEnabled, true); this.showHttpBasic = first(provider.basicAuthEnabled, true);
this.showInternalServer = first(!provider.forwardAuthMode, true); this.showInternalServer = first(!provider.forwardAuthMode, true);
return provider;
}); });
} }
@property({attribute: false})
provider?: ProxyProvider;
@property({type: Boolean}) @property({type: Boolean})
showHttpBasic = true; showHttpBasic = true;
@ -33,7 +30,7 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
showInternalServer = true; showInternalServer = true;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.provider) { if (this.instance) {
return t`Successfully updated provider.`; return t`Successfully updated provider.`;
} else { } else {
return t`Successfully created provider.`; return t`Successfully created provider.`;
@ -41,9 +38,9 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
} }
send = (data: ProxyProvider): Promise<ProxyProvider> => { send = (data: ProxyProvider): Promise<ProxyProvider> => {
if (this.provider) { if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersProxyUpdate({ return new ProvidersApi(DEFAULT_CONFIG).providersProxyUpdate({
id: this.provider.pk || 0, id: this.instance.pk || 0,
data: data data: data
}); });
} else { } else {
@ -60,13 +57,13 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
return html`<ak-form-element-horizontal return html`<ak-form-element-horizontal
label=${t`HTTP-Basic Username Key`} label=${t`HTTP-Basic Username Key`}
name="basicAuthUserAttribute"> name="basicAuthUserAttribute">
<input type="text" value="${ifDefined(this.provider?.basicAuthUserAttribute)}" class="pf-c-form-control"> <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> <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>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`HTTP-Basic Password Key`} label=${t`HTTP-Basic Password Key`}
name="basicAuthPasswordAttribute"> name="basicAuthPasswordAttribute">
<input type="text" value="${ifDefined(this.provider?.basicAuthPasswordAttribute)}" class="pf-c-form-control"> <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> <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>`; </ak-form-element-horizontal>`;
} }
@ -79,12 +76,12 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
label=${t`Internal host`} label=${t`Internal host`}
?required=${true} ?required=${true}
name="internalHost"> name="internalHost">
<input type="text" value="${ifDefined(this.provider?.internalHost)}" class="pf-c-form-control" required> <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> <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>
<ak-form-element-horizontal name="internalHostSslValidation"> <ak-form-element-horizontal name="internalHostSslValidation">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.provider?.internalHostSslValidation, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.internalHostSslValidation, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Internal host SSL Validation`} ${t`Internal host SSL Validation`}
</label> </label>
@ -99,7 +96,7 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.provider?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authorization flow`} label=${t`Authorization flow`}
@ -111,7 +108,7 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
designation: FlowDesignationEnum.Authorization, designation: FlowDesignationEnum.Authorization,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
return html`<option value=${ifDefined(flow.pk)} ?selected=${this.provider?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${this.instance?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -127,12 +124,12 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
label=${t`External host`} label=${t`External host`}
?required=${true} ?required=${true}
name="externalHost"> name="externalHost">
<input type="text" value="${ifDefined(this.provider?.externalHost)}" class="pf-c-form-control" required> <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 outpost at.`}</p> <p class="pf-c-form__helper-text">${t`The external URL you'll access the outpost at.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="forwardAuthMode"> <ak-form-element-horizontal name="forwardAuthMode">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.provider?.forwardAuthMode, false)} @change=${(ev: Event) => { <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.forwardAuthMode, false)} @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showInternalServer = !el.checked; this.showInternalServer = !el.checked;
}}> }}>
@ -162,7 +159,7 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
hasKey: "true", hasKey: "true",
}).then(keys => { }).then(keys => {
return keys.results.map(key => { return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.provider?.certificate === key.pk}>${key.name}</option>`; return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.certificate === key.pk}>${key.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -171,13 +168,13 @@ export class ProxyProviderFormPage extends Form<ProxyProvider> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Skip path regex`} label=${t`Skip path regex`}
name="skipPathRegex"> name="skipPathRegex">
<textarea class="pf-c-form-control">${this.provider?.skipPathRegex}</textarea> <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> <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>
<ak-form-element-horizontal name="basicAuthEnabled"> <ak-form-element-horizontal name="basicAuthEnabled">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.provider?.basicAuthEnabled, false)} @change=${(ev: Event) => { <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.basicAuthEnabled, false)} @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showHttpBasic = el.checked; this.showHttpBasic = el.checked;
}}> }}>

View File

@ -127,7 +127,7 @@ export class ProxyProviderViewPage extends LitElement {
</span> </span>
<ak-provider-proxy-form <ak-provider-proxy-form
slot="form" slot="form"
.providerUUID=${this.provider.pk || 0}> .instancePk=${this.provider.pk || 0}>
</ak-provider-proxy-form> </ak-provider-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -1,30 +1,26 @@
import { CryptoApi, FlowDesignationEnum, FlowsApi, SAMLProvider, ProvidersApi, PropertymappingsApi, SAMLProviderSpBindingEnum, SAMLProviderDigestAlgorithmEnum, SAMLProviderSignatureAlgorithmEnum } from "authentik-api"; import { CryptoApi, FlowDesignationEnum, FlowsApi, SAMLProvider, ProvidersApi, PropertymappingsApi, SAMLProviderSpBindingEnum, SAMLProviderDigestAlgorithmEnum, SAMLProviderSignatureAlgorithmEnum } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form"; import { ModelForm } from "../../../elements/forms/ModelForm";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
@customElement("ak-provider-saml-form") @customElement("ak-provider-saml-form")
export class SAMLProviderFormPage extends Form<SAMLProvider> { export class SAMLProviderFormPage extends ModelForm<SAMLProvider, number> {
set providerUUID(value: number) { loadInstance(pk: number): Promise<SAMLProvider> {
new ProvidersApi(DEFAULT_CONFIG).providersSamlRead({ console.log("reading saml provider");
id: value, return new ProvidersApi(DEFAULT_CONFIG).providersSamlRead({
}).then(provider => { id: pk,
this.provider = provider;
}); });
} }
@property({attribute: false})
provider?: SAMLProvider;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.provider) { if (this.instance) {
return t`Successfully updated provider.`; return t`Successfully updated provider.`;
} else { } else {
return t`Successfully created provider.`; return t`Successfully created provider.`;
@ -32,9 +28,9 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
} }
send = (data: SAMLProvider): Promise<SAMLProvider> => { send = (data: SAMLProvider): Promise<SAMLProvider> => {
if (this.provider) { if (this.instance) {
return new ProvidersApi(DEFAULT_CONFIG).providersSamlUpdate({ return new ProvidersApi(DEFAULT_CONFIG).providersSamlUpdate({
id: this.provider.pk || 0, id: this.instance.pk || 0,
data: data data: data
}); });
} else { } else {
@ -50,7 +46,7 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.provider?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Authorization flow`} label=${t`Authorization flow`}
@ -62,7 +58,7 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
designation: FlowDesignationEnum.Authorization, designation: FlowDesignationEnum.Authorization,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
return html`<option value=${ifDefined(flow.pk)} ?selected=${this.provider?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${this.instance?.authorizationFlow === flow.pk}>${flow.name} (${flow.slug})</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -78,23 +74,23 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
label=${t`ACS URL`} label=${t`ACS URL`}
?required=${true} ?required=${true}
name="acsUrl"> name="acsUrl">
<input type="text" value="${ifDefined(this.provider?.acsUrl)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.acsUrl)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Issuer`} label=${t`Issuer`}
?required=${true} ?required=${true}
name="issuer"> name="issuer">
<input type="text" value="${this.provider?.issuer || "authentik"}" class="pf-c-form-control" required> <input type="text" value="${this.instance?.issuer || "authentik"}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Service Provider Binding`} label=${t`Service Provider Binding`}
?required=${true} ?required=${true}
name="spBinding"> name="spBinding">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${SAMLProviderSpBindingEnum.Redirect} ?selected=${this.provider?.spBinding === SAMLProviderSpBindingEnum.Redirect}> <option value=${SAMLProviderSpBindingEnum.Redirect} ?selected=${this.instance?.spBinding === SAMLProviderSpBindingEnum.Redirect}>
${t`Redirect`} ${t`Redirect`}
</option> </option>
<option value=${SAMLProviderSpBindingEnum.Post} ?selected=${this.provider?.spBinding === SAMLProviderSpBindingEnum.Post}> <option value=${SAMLProviderSpBindingEnum.Post} ?selected=${this.instance?.spBinding === SAMLProviderSpBindingEnum.Post}>
${t`Post`} ${t`Post`}
</option> </option>
</select> </select>
@ -103,7 +99,7 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Audience`} label=${t`Audience`}
name="audience"> name="audience">
<input type="text" value="${ifDefined(this.provider?.audience)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.audience)}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>
@ -117,13 +113,13 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
label=${t`Signing Certificate`} label=${t`Signing Certificate`}
name="signingKp"> name="signingKp">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.provider?.signingKp === undefined}>---------</option> <option value="" ?selected=${this.instance?.signingKp === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({ ${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk", ordering: "pk",
hasKey: "true", hasKey: "true",
}).then(keys => { }).then(keys => {
return keys.results.map(key => { return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.provider?.signingKp === key.pk}>${key.name}</option>`; return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.signingKp === key.pk}>${key.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -133,12 +129,12 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
label=${t`Verification Certificate`} label=${t`Verification Certificate`}
name="verificationKp"> name="verificationKp">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.provider?.verificationKp === undefined}>---------</option> <option value="" ?selected=${this.instance?.verificationKp === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({ ${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk", ordering: "pk",
}).then(keys => { }).then(keys => {
return keys.results.map(key => { return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.provider?.verificationKp === key.pk}>${key.name}</option>`; return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.verificationKp === key.pk}>${key.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -155,10 +151,10 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
}).then(mappings => { }).then(mappings => {
return mappings.results.map(mapping => { return mappings.results.map(mapping => {
let selected = false; let selected = false;
if (!this.provider?.propertyMappings) { if (!this.instance?.propertyMappings) {
selected = mapping.managed?.startsWith("goauthentik.io/providers/saml") || false; selected = mapping.managed?.startsWith("goauthentik.io/providers/saml") || false;
} else { } else {
selected = Array.from(this.provider?.propertyMappings).some(su => { selected = Array.from(this.instance?.propertyMappings).some(su => {
return su == mapping.pk; return su == mapping.pk;
}); });
} }
@ -172,12 +168,12 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
label=${t`NameID Property Mapping`} label=${t`NameID Property Mapping`}
name="nameIdMapping"> name="nameIdMapping">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.provider?.nameIdMapping === undefined}>---------</option> <option value="" ?selected=${this.instance?.nameIdMapping === undefined}>---------</option>
${until(new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlList({ ${until(new PropertymappingsApi(DEFAULT_CONFIG).propertymappingsSamlList({
ordering: "saml_name" ordering: "saml_name"
}).then(mappings => { }).then(mappings => {
return mappings.results.map(mapping => { return mappings.results.map(mapping => {
return html`<option value=${ifDefined(mapping.pk)} ?selected=${this.provider?.nameIdMapping === mapping.pk}>${mapping.name}</option>`; return html`<option value=${ifDefined(mapping.pk)} ?selected=${this.instance?.nameIdMapping === mapping.pk}>${mapping.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -188,7 +184,7 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
label=${t`Assertion valid not before`} label=${t`Assertion valid not before`}
?required=${true} ?required=${true}
name="assertionValidNotBefore"> name="assertionValidNotBefore">
<input type="text" value="${this.provider?.assertionValidNotBefore || "minutes=-5"}" class="pf-c-form-control" required> <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`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> <p class="pf-c-form__helper-text">${t`(Format: hours=-1;minutes=-2;seconds=-3).`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -196,14 +192,14 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
label=${t`Assertion valid not on or after`} label=${t`Assertion valid not on or after`}
?required=${true} ?required=${true}
name="assertionValidNotOnOrAfter"> name="assertionValidNotOnOrAfter">
<input type="text" value="${this.provider?.assertionValidNotOnOrAfter || "minutes=5"}" class="pf-c-form-control" required> <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> <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>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Session valid not on or after`} label=${t`Session valid not on or after`}
?required=${true} ?required=${true}
name="sessionValidNotOnOrAfter"> name="sessionValidNotOnOrAfter">
<input type="text" value="${this.provider?.sessionValidNotOnOrAfter || "minutes=86400"}" class="pf-c-form-control" required> <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> <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>
@ -212,16 +208,16 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
?required=${true} ?required=${true}
name="digestAlgorithm"> name="digestAlgorithm">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${SAMLProviderDigestAlgorithmEnum._200009Xmldsigsha1} ?selected=${this.provider?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200009Xmldsigsha1}> <option value=${SAMLProviderDigestAlgorithmEnum._200009Xmldsigsha1} ?selected=${this.instance?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200009Xmldsigsha1}>
${t`SHA1`} ${t`SHA1`}
</option> </option>
<option value=${SAMLProviderDigestAlgorithmEnum._200104Xmlencsha256} ?selected=${this.provider?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200104Xmlencsha256 || this.provider?.digestAlgorithm === undefined}> <option value=${SAMLProviderDigestAlgorithmEnum._200104Xmlencsha256} ?selected=${this.instance?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200104Xmlencsha256 || this.instance?.digestAlgorithm === undefined}>
${t`SHA256`} ${t`SHA256`}
</option> </option>
<option value=${SAMLProviderDigestAlgorithmEnum._200104XmldsigMoresha384} ?selected=${this.provider?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200104XmldsigMoresha384}> <option value=${SAMLProviderDigestAlgorithmEnum._200104XmldsigMoresha384} ?selected=${this.instance?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200104XmldsigMoresha384}>
${t`SHA384`} ${t`SHA384`}
</option> </option>
<option value=${SAMLProviderDigestAlgorithmEnum._200104Xmlencsha512} ?selected=${this.provider?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200104Xmlencsha512}> <option value=${SAMLProviderDigestAlgorithmEnum._200104Xmlencsha512} ?selected=${this.instance?.digestAlgorithm === SAMLProviderDigestAlgorithmEnum._200104Xmlencsha512}>
${t`SHA512`} ${t`SHA512`}
</option> </option>
</select> </select>
@ -231,19 +227,19 @@ export class SAMLProviderFormPage extends Form<SAMLProvider> {
?required=${true} ?required=${true}
name="signatureAlgorithm"> name="signatureAlgorithm">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${SAMLProviderSignatureAlgorithmEnum._200009XmldsigrsaSha1} ?selected=${this.provider?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200009XmldsigrsaSha1}> <option value=${SAMLProviderSignatureAlgorithmEnum._200009XmldsigrsaSha1} ?selected=${this.instance?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200009XmldsigrsaSha1}>
${t`RSA-SHA1`} ${t`RSA-SHA1`}
</option> </option>
<option value=${SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha256} ?selected=${this.provider?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha256 || this.provider?.signatureAlgorithm === undefined}> <option value=${SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha256} ?selected=${this.instance?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha256 || this.instance?.signatureAlgorithm === undefined}>
${t`RSA-SHA256`} ${t`RSA-SHA256`}
</option> </option>
<option value=${SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha384} ?selected=${this.provider?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha384}> <option value=${SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha384} ?selected=${this.instance?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha384}>
${t`RSA-SHA384`} ${t`RSA-SHA384`}
</option> </option>
<option value=${SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha512} ?selected=${this.provider?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha512}> <option value=${SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha512} ?selected=${this.instance?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200104XmldsigMorersaSha512}>
${t`RSA-SHA512`} ${t`RSA-SHA512`}
</option> </option>
<option value=${SAMLProviderSignatureAlgorithmEnum._200009XmldsigdsaSha1} ?selected=${this.provider?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200009XmldsigdsaSha1}> <option value=${SAMLProviderSignatureAlgorithmEnum._200009XmldsigdsaSha1} ?selected=${this.instance?.signatureAlgorithm === SAMLProviderSignatureAlgorithmEnum._200009XmldsigdsaSha1}>
${t`DSA-SHA1`} ${t`DSA-SHA1`}
</option> </option>
</select> </select>

View File

@ -121,7 +121,7 @@ export class SAMLProviderViewPage extends LitElement {
</span> </span>
<ak-provider-saml-form <ak-provider-saml-form
slot="form" slot="form"
.providerUUID=${this.provider.pk || 0}> .instancePk=${this.provider.pk || 0}>
</ak-provider-saml-form> </ak-provider-saml-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -75,7 +75,7 @@ export class SourceListPage extends TablePage<Source> {
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
"sourceSlug": item.slug "instancePk": item.slug
}} }}
type=${ifDefined(item.component)}> type=${ifDefined(item.component)}>
</ak-proxy-form> </ak-proxy-form>

View File

@ -1,31 +1,26 @@
import { LDAPSource, SourcesApi, PropertymappingsApi } from "authentik-api"; import { LDAPSource, SourcesApi, PropertymappingsApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-source-ldap-form") @customElement("ak-source-ldap-form")
export class LDAPSourceForm extends Form<LDAPSource> { export class LDAPSourceForm extends ModelForm<LDAPSource, string> {
set sourceSlug(value: string) { loadInstance(pk: string): Promise<LDAPSource> {
new SourcesApi(DEFAULT_CONFIG).sourcesLdapRead({ return new SourcesApi(DEFAULT_CONFIG).sourcesLdapRead({
slug: value, slug: pk,
}).then(source => {
this.source = source;
}); });
} }
@property({attribute: false})
source?: LDAPSource;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.source) { if (this.instance) {
return t`Successfully updated source.`; return t`Successfully updated source.`;
} else { } else {
return t`Successfully created source.`; return t`Successfully created source.`;
@ -33,9 +28,9 @@ export class LDAPSourceForm extends Form<LDAPSource> {
} }
send = (data: LDAPSource): Promise<LDAPSource> => { send = (data: LDAPSource): Promise<LDAPSource> => {
if (this.source) { if (this.instance) {
return new SourcesApi(DEFAULT_CONFIG).sourcesLdapPartialUpdate({ return new SourcesApi(DEFAULT_CONFIG).sourcesLdapPartialUpdate({
slug: this.source.slug, slug: this.instance.slug,
data: data data: data
}); });
} else { } else {
@ -51,17 +46,17 @@ export class LDAPSourceForm extends Form<LDAPSource> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.source?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Slug`} label=${t`Slug`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.source?.slug)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="enabled"> <ak-form-element-horizontal name="enabled">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.enabled, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.enabled, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Enabled`} ${t`Enabled`}
</label> </label>
@ -69,7 +64,7 @@ export class LDAPSourceForm extends Form<LDAPSource> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="syncUsers"> <ak-form-element-horizontal name="syncUsers">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.syncUsers, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.syncUsers, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Sync users`} ${t`Sync users`}
</label> </label>
@ -77,7 +72,7 @@ export class LDAPSourceForm extends Form<LDAPSource> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="syncUsersPassword"> <ak-form-element-horizontal name="syncUsersPassword">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.syncUsersPassword, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.syncUsersPassword, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`User password writeback`} ${t`User password writeback`}
</label> </label>
@ -86,7 +81,7 @@ export class LDAPSourceForm extends Form<LDAPSource> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="syncGroups"> <ak-form-element-horizontal name="syncGroups">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.syncGroups, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.syncGroups, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Sync groups`} ${t`Sync groups`}
</label> </label>
@ -101,11 +96,11 @@ export class LDAPSourceForm extends Form<LDAPSource> {
label=${t`Server URI`} label=${t`Server URI`}
?required=${true} ?required=${true}
name="serverUri"> name="serverUri">
<input type="text" value="${ifDefined(this.source?.serverUri)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.serverUri)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="startTls"> <ak-form-element-horizontal name="startTls">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.startTls, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.startTls, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Enable StartTLS`} ${t`Enable StartTLS`}
</label> </label>
@ -115,20 +110,20 @@ export class LDAPSourceForm extends Form<LDAPSource> {
label=${t`Bind CN`} label=${t`Bind CN`}
?required=${true} ?required=${true}
name="bindCn"> name="bindCn">
<input type="text" value="${ifDefined(this.source?.bindCn)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.bindCn)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Bind Password`} label=${t`Bind Password`}
?required=${true} ?required=${true}
?writeOnly=${this.source !== undefined} ?writeOnly=${this.instance !== undefined}
name="bindPassword"> name="bindPassword">
<input type="text" value="${ifDefined(this.source?.bindPassword)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.bindPassword)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Base DN`} label=${t`Base DN`}
?required=${true} ?required=${true}
name="baseDn"> name="baseDn">
<input type="text" value="${ifDefined(this.source?.baseDn)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.baseDn)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group> </ak-form-group>
@ -147,10 +142,10 @@ export class LDAPSourceForm extends Form<LDAPSource> {
}).then(mappings => { }).then(mappings => {
return mappings.results.map(mapping => { return mappings.results.map(mapping => {
let selected = false; let selected = false;
if (!this.source?.propertyMappings) { if (!this.instance?.propertyMappings) {
selected = mapping.managed?.startsWith("goauthentik.io/sources/ldap/default") || mapping.managed?.startsWith("goauthentik.io/sources/ldap/ms") || false; selected = mapping.managed?.startsWith("goauthentik.io/sources/ldap/default") || mapping.managed?.startsWith("goauthentik.io/sources/ldap/ms") || false;
} else { } else {
selected = Array.from(this.source?.propertyMappings).some(su => { selected = Array.from(this.instance?.propertyMappings).some(su => {
return su == mapping.pk; return su == mapping.pk;
}); });
} }
@ -171,10 +166,10 @@ export class LDAPSourceForm extends Form<LDAPSource> {
}).then(mappings => { }).then(mappings => {
return mappings.results.map(mapping => { return mappings.results.map(mapping => {
let selected = false; let selected = false;
if (!this.source?.propertyMappingsGroup) { if (!this.instance?.propertyMappingsGroup) {
selected = mapping.managed === "goauthentik.io/sources/ldap/default-name"; selected = mapping.managed === "goauthentik.io/sources/ldap/default-name";
} else { } else {
selected = Array.from(this.source?.propertyMappingsGroup).some(su => { selected = Array.from(this.instance?.propertyMappingsGroup).some(su => {
return su == mapping.pk; return su == mapping.pk;
}); });
} }
@ -188,41 +183,41 @@ export class LDAPSourceForm extends Form<LDAPSource> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Addition User DN`} label=${t`Addition User DN`}
name="additionalUserDn"> name="additionalUserDn">
<input type="text" value="${ifDefined(this.source?.additionalUserDn)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.additionalUserDn)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`Additional user DN, prepended to the Base DN.`}</p> <p class="pf-c-form__helper-text">${t`Additional user DN, prepended to the Base DN.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Addition Group DN`} label=${t`Addition Group DN`}
name="additionalGroupDn"> name="additionalGroupDn">
<input type="text" value="${ifDefined(this.source?.additionalGroupDn)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.additionalGroupDn)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`Additional group DN, prepended to the Base DN.`}</p> <p class="pf-c-form__helper-text">${t`Additional group DN, prepended to the Base DN.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`User object filter`} label=${t`User object filter`}
?required=${true} ?required=${true}
name="userObjectFilter"> name="userObjectFilter">
<input type="text" value="${this.source?.userObjectFilter || "(objectClass=person)"}" class="pf-c-form-control" required> <input type="text" value="${this.instance?.userObjectFilter || "(objectClass=person)"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Consider Objects matching this filter to be Users.`}</p> <p class="pf-c-form__helper-text">${t`Consider Objects matching this filter to be Users.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Group object filter`} label=${t`Group object filter`}
?required=${true} ?required=${true}
name="groupObjectFilter"> name="groupObjectFilter">
<input type="text" value="${this.source?.groupObjectFilter || "(objectClass=group)"}" class="pf-c-form-control" required> <input type="text" value="${this.instance?.groupObjectFilter || "(objectClass=group)"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Consider Objects matching this filter to be Groups.`}</p> <p class="pf-c-form__helper-text">${t`Consider Objects matching this filter to be Groups.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Group membership field`} label=${t`Group membership field`}
?required=${true} ?required=${true}
name="groupMembershipField"> name="groupMembershipField">
<input type="text" value="${this.source?.groupMembershipField || "member"}" class="pf-c-form-control" required> <input type="text" value="${this.instance?.groupMembershipField || "member"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Field which contains members of a group.`}</p> <p class="pf-c-form__helper-text">${t`Field which contains members of a group.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Object uniqueness field`} label=${t`Object uniqueness field`}
?required=${true} ?required=${true}
name="objectUniquenessField"> name="objectUniquenessField">
<input type="text" value="${this.source?.objectUniquenessField || "objectSid"}" class="pf-c-form-control" required> <input type="text" value="${this.instance?.objectUniquenessField || "objectSid"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Field which contains a unique Identifier.`}</p> <p class="pf-c-form__helper-text">${t`Field which contains a unique Identifier.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -103,7 +103,7 @@ export class LDAPSourceViewPage extends LitElement {
</span> </span>
<ak-source-ldap-form <ak-source-ldap-form
slot="form" slot="form"
.sourceSlug=${this.source.slug}> .instancePk=${this.source.slug}>
</ak-source-ldap-form> </ak-source-ldap-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -3,32 +3,29 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { AppURLManager } from "../../../api/legacy"; import { AppURLManager } from "../../../api/legacy";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-source-oauth-form") @customElement("ak-source-oauth-form")
export class OAuthSourceForm extends Form<OAuthSource> { export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
set sourceSlug(value: string) { loadInstance(pk: string): Promise<OAuthSource> {
new SourcesApi(DEFAULT_CONFIG).sourcesOauthRead({ return new SourcesApi(DEFAULT_CONFIG).sourcesOauthRead({
slug: value, slug: pk,
}).then(source => { }).then(source => {
this.source = source;
this.showUrlOptions = first(source.type?.urlsCustomizable, false); this.showUrlOptions = first(source.type?.urlsCustomizable, false);
return source;
}); });
} }
@property() @property()
modelName?: string; modelName?: string;
@property({attribute: false})
source?: OAuthSource;
@property({type: Boolean}) @property({type: Boolean})
showUrlOptions = false; showUrlOptions = false;
@ -36,7 +33,7 @@ export class OAuthSourceForm extends Form<OAuthSource> {
showRequestTokenURL = false; showRequestTokenURL = false;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.source) { if (this.instance) {
return t`Successfully updated source.`; return t`Successfully updated source.`;
} else { } else {
return t`Successfully created source.`; return t`Successfully created source.`;
@ -44,9 +41,9 @@ export class OAuthSourceForm extends Form<OAuthSource> {
} }
send = (data: OAuthSource): Promise<OAuthSource> => { send = (data: OAuthSource): Promise<OAuthSource> => {
if (this.source) { if (this.instance) {
return new SourcesApi(DEFAULT_CONFIG).sourcesOauthUpdate({ return new SourcesApi(DEFAULT_CONFIG).sourcesOauthPartialUpdate({
slug: this.source.slug, slug: this.instance.slug,
data: data data: data
}); });
} else { } else {
@ -70,27 +67,27 @@ export class OAuthSourceForm extends Form<OAuthSource> {
label=${t`Authorization URL`} label=${t`Authorization URL`}
?required=${true} ?required=${true}
name="authorizationUrl"> name="authorizationUrl">
<input type="text" value="${first(this.source?.authorizationUrl, "")}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.authorizationUrl, "")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`URL the user is redirect to to consent the authorization.`}</p> <p class="pf-c-form__helper-text">${t`URL the user is redirect to to consent the authorization.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Access token URL`} label=${t`Access token URL`}
?required=${true} ?required=${true}
name="accessTokenUrl"> name="accessTokenUrl">
<input type="text" value="${first(this.source?.accessTokenUrl, "")}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.accessTokenUrl, "")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`URL used by authentik to retrieve tokens.`}</p> <p class="pf-c-form__helper-text">${t`URL used by authentik to retrieve tokens.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Profile URL`} label=${t`Profile URL`}
?required=${true} ?required=${true}
name="profileUrl"> name="profileUrl">
<input type="text" value="${first(this.source?.profileUrl, "")}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.profileUrl, "")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`URL used by authentik to get user information.`}</p> <p class="pf-c-form__helper-text">${t`URL used by authentik to get user information.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${this.showRequestTokenURL ? html`<ak-form-element-horizontal ${this.showRequestTokenURL ? html`<ak-form-element-horizontal
label=${t`Request token URL`} label=${t`Request token URL`}
name="requestTokenUrl"> name="requestTokenUrl">
<input type="text" value="${first(this.source?.requestTokenUrl, "")}" class="pf-c-form-control"> <input type="text" value="${first(this.instance?.requestTokenUrl, "")}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`URL used to request the initial token. This URL is only required for OAuth 1.`}</p> <p class="pf-c-form__helper-text">${t`URL used to request the initial token. This URL is only required for OAuth 1.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
` : html``} ` : html``}
@ -112,13 +109,13 @@ export class OAuthSourceForm extends Form<OAuthSource> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.source?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Slug`} label=${t`Slug`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.source?.slug)}" class="pf-c-form-control" required @input=${(ev: Event) => { <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required @input=${(ev: Event) => {
const current = (ev.target as HTMLInputElement).value; const current = (ev.target as HTMLInputElement).value;
const label = this.shadowRoot?.querySelector<HTMLSpanElement>("#callback-url"); const label = this.shadowRoot?.querySelector<HTMLSpanElement>("#callback-url");
if (!label) return; if (!label) return;
@ -126,12 +123,12 @@ export class OAuthSourceForm extends Form<OAuthSource> {
}}> }}>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${t`Use this redirect URL:`} ${t`Use this redirect URL:`}
<span id="callback-url">${this.getRedirectURI(this.source?.slug)}</span> <span id="callback-url">${this.getRedirectURI(this.instance?.slug)}</span>
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="enabled"> <ak-form-element-horizontal name="enabled">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.enabled, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.enabled, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Enabled`} ${t`Enabled`}
</label> </label>
@ -142,19 +139,19 @@ export class OAuthSourceForm extends Form<OAuthSource> {
?required=${true} ?required=${true}
name="userMatchingMode"> name="userMatchingMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${OAuthSourceUserMatchingModeEnum.Identifier} ?selected=${this.source?.userMatchingMode === OAuthSourceUserMatchingModeEnum.Identifier}> <option value=${OAuthSourceUserMatchingModeEnum.Identifier} ?selected=${this.instance?.userMatchingMode === OAuthSourceUserMatchingModeEnum.Identifier}>
${t`Link users on unique identifier`} ${t`Link users on unique identifier`}
</option> </option>
<option value=${OAuthSourceUserMatchingModeEnum.UsernameLink} ?selected=${this.source?.userMatchingMode === OAuthSourceUserMatchingModeEnum.UsernameLink}> <option value=${OAuthSourceUserMatchingModeEnum.UsernameLink} ?selected=${this.instance?.userMatchingMode === OAuthSourceUserMatchingModeEnum.UsernameLink}>
${t`Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses`} ${t`Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses`}
</option> </option>
<option value=${OAuthSourceUserMatchingModeEnum.UsernameDeny} ?selected=${this.source?.userMatchingMode === OAuthSourceUserMatchingModeEnum.UsernameDeny}> <option value=${OAuthSourceUserMatchingModeEnum.UsernameDeny} ?selected=${this.instance?.userMatchingMode === OAuthSourceUserMatchingModeEnum.UsernameDeny}>
${t`Use the user's email address, but deny enrollment when the email address already exists.`} ${t`Use the user's email address, but deny enrollment when the email address already exists.`}
</option> </option>
<option value=${OAuthSourceUserMatchingModeEnum.EmailLink} ?selected=${this.source?.userMatchingMode === OAuthSourceUserMatchingModeEnum.EmailLink}> <option value=${OAuthSourceUserMatchingModeEnum.EmailLink} ?selected=${this.instance?.userMatchingMode === OAuthSourceUserMatchingModeEnum.EmailLink}>
${t`Link to a user with identical username address. Can have security implications when a username is used with another source.`} ${t`Link to a user with identical username address. Can have security implications when a username is used with another source.`}
</option> </option>
<option value=${OAuthSourceUserMatchingModeEnum.EmailDeny} ?selected=${this.source?.userMatchingMode === OAuthSourceUserMatchingModeEnum.EmailDeny}> <option value=${OAuthSourceUserMatchingModeEnum.EmailDeny} ?selected=${this.instance?.userMatchingMode === OAuthSourceUserMatchingModeEnum.EmailDeny}>
${t`Use the user's username, but deny enrollment when the username already exists.`} ${t`Use the user's username, but deny enrollment when the username already exists.`}
</option> </option>
</select> </select>
@ -169,14 +166,14 @@ export class OAuthSourceForm extends Form<OAuthSource> {
label=${t`Consumer key`} label=${t`Consumer key`}
?required=${true} ?required=${true}
name="consumerKey"> name="consumerKey">
<input type="text" value="${ifDefined(this.source?.consumerKey)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.consumerKey)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Consumer secret`} label=${t`Consumer secret`}
?required=${true} ?required=${true}
?writeOnly=${this.source !== undefined} ?writeOnly=${this.instance !== undefined}
name="consumerSecret"> name="consumerSecret">
<input type="text" value="${ifDefined(this.source?.consumerSecret)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.consumerSecret)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Provider type`} label=${t`Provider type`}
@ -194,15 +191,15 @@ export class OAuthSourceForm extends Form<OAuthSource> {
} else { } else {
this.showRequestTokenURL = false; this.showRequestTokenURL = false;
} }
if (!this.source) { if (!this.instance) {
this.source = {} as OAuthSource; this.instance = {} as OAuthSource;
} }
this.source.providerType = selected.value; this.instance.providerType = selected.value;
}}> }}>
${until(new SourcesApi(DEFAULT_CONFIG).sourcesOauthSourceTypes().then(types => { ${until(new SourcesApi(DEFAULT_CONFIG).sourcesOauthSourceTypes().then(types => {
return types.map(type => { return types.map(type => {
let selected = this.source?.providerType === type.slug; let selected = this.instance?.providerType === type.slug;
if (!this.source?.pk) { if (!this.instance?.pk) {
if (this.modelName?.replace("oauthsource", "") === type.slug) { if (this.modelName?.replace("oauthsource", "") === type.slug) {
selected = true; selected = true;
} }
@ -236,8 +233,8 @@ export class OAuthSourceForm extends Form<OAuthSource> {
designation: FlowDesignationEnum.Authentication, designation: FlowDesignationEnum.Authentication,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.source?.authenticationFlow === flow.pk; let selected = this.instance?.authenticationFlow === flow.pk;
if (!this.source?.pk && !this.source?.authenticationFlow && flow.slug === "default-source-authentication") { if (!this.instance?.pk && !this.instance?.authenticationFlow && flow.slug === "default-source-authentication") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
@ -256,8 +253,8 @@ export class OAuthSourceForm extends Form<OAuthSource> {
designation: FlowDesignationEnum.Enrollment, designation: FlowDesignationEnum.Enrollment,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.source?.enrollmentFlow === flow.pk; let selected = this.instance?.enrollmentFlow === flow.pk;
if (!this.source?.pk && !this.source?.enrollmentFlow && flow.slug === "default-source-enrollment") { if (!this.instance?.pk && !this.instance?.enrollmentFlow && flow.slug === "default-source-enrollment") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;

View File

@ -122,7 +122,7 @@ export class OAuthSourceViewPage extends LitElement {
</span> </span>
<ak-source-oauth-form <ak-source-oauth-form
slot="form" slot="form"
.sourceSlug=${this.source.slug}> .instancePk=${this.source.slug}>
</ak-source-oauth-form> </ak-source-oauth-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -3,41 +3,42 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first, randomString } from "../../../utils"; import { first, randomString } from "../../../utils";
import { PlexAPIClient, PlexResource, popupCenterScreen} from "../../../flows/sources/plex/API"; import { PlexAPIClient, PlexResource, popupCenterScreen} from "../../../flows/sources/plex/API";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-source-plex-form") @customElement("ak-source-plex-form")
export class PlexSourceForm extends Form<PlexSource> { export class PlexSourceForm extends ModelForm<PlexSource, string> {
set sourceSlug(value: string) { loadInstance(pk: string): Promise<PlexSource> {
new SourcesApi(DEFAULT_CONFIG).sourcesPlexRead({ return new SourcesApi(DEFAULT_CONFIG).sourcesPlexRead({
slug: value, slug: pk,
}).then(source => { }).then(source => {
this.source = source;
this.plexToken = source.plexToken; this.plexToken = source.plexToken;
this.loadServers(); this.loadServers();
return source;
}); });
} }
@property({attribute: false})
source: PlexSource = {
clientId: randomString(40)
} as PlexSource;
@property() @property()
plexToken?: string; plexToken?: string;
@property({attribute: false}) @property({attribute: false})
plexResources?: PlexResource[]; plexResources?: PlexResource[];
get defaultInstance(): PlexSource | undefined {
return {
clientId: randomString(40)
} as PlexSource;
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.source) { if (this.instance) {
return t`Successfully updated source.`; return t`Successfully updated source.`;
} else { } else {
return t`Successfully created source.`; return t`Successfully created source.`;
@ -46,9 +47,9 @@ export class PlexSourceForm extends Form<PlexSource> {
send = (data: PlexSource): Promise<PlexSource> => { send = (data: PlexSource): Promise<PlexSource> => {
data.plexToken = this.plexToken; data.plexToken = this.plexToken;
if (this.source.slug) { if (this.instance?.slug) {
return new SourcesApi(DEFAULT_CONFIG).sourcesPlexUpdate({ return new SourcesApi(DEFAULT_CONFIG).sourcesPlexUpdate({
slug: this.source.slug, slug: this.instance.slug,
data: data data: data
}); });
} else { } else {
@ -59,9 +60,9 @@ export class PlexSourceForm extends Form<PlexSource> {
}; };
async doAuth(): Promise<void> { async doAuth(): Promise<void> {
const authInfo = await PlexAPIClient.getPin(this.source?.clientId || ""); const authInfo = await PlexAPIClient.getPin(this.instance?.clientId || "");
const authWindow = popupCenterScreen(authInfo.authUrl, "plex auth", 550, 700); const authWindow = popupCenterScreen(authInfo.authUrl, "plex auth", 550, 700);
PlexAPIClient.pinPoll(this.source?.clientId || "", authInfo.pin.id).then(token => { PlexAPIClient.pinPoll(this.instance?.clientId || "", authInfo.pin.id).then(token => {
authWindow?.close(); authWindow?.close();
this.plexToken = token; this.plexToken = token;
this.loadServers(); this.loadServers();
@ -81,17 +82,17 @@ export class PlexSourceForm extends Form<PlexSource> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.source?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Slug`} label=${t`Slug`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.source?.slug)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="enabled"> <ak-form-element-horizontal name="enabled">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.enabled, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.enabled, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Enabled`} ${t`Enabled`}
</label> </label>
@ -102,19 +103,19 @@ export class PlexSourceForm extends Form<PlexSource> {
?required=${true} ?required=${true}
name="userMatchingMode"> name="userMatchingMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${PlexSourceUserMatchingModeEnum.Identifier} ?selected=${this.source?.userMatchingMode === PlexSourceUserMatchingModeEnum.Identifier}> <option value=${PlexSourceUserMatchingModeEnum.Identifier} ?selected=${this.instance?.userMatchingMode === PlexSourceUserMatchingModeEnum.Identifier}>
${t`Link users on unique identifier`} ${t`Link users on unique identifier`}
</option> </option>
<option value=${PlexSourceUserMatchingModeEnum.UsernameLink} ?selected=${this.source?.userMatchingMode === PlexSourceUserMatchingModeEnum.UsernameLink}> <option value=${PlexSourceUserMatchingModeEnum.UsernameLink} ?selected=${this.instance?.userMatchingMode === PlexSourceUserMatchingModeEnum.UsernameLink}>
${t`Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses`} ${t`Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses`}
</option> </option>
<option value=${PlexSourceUserMatchingModeEnum.UsernameDeny} ?selected=${this.source?.userMatchingMode === PlexSourceUserMatchingModeEnum.UsernameDeny}> <option value=${PlexSourceUserMatchingModeEnum.UsernameDeny} ?selected=${this.instance?.userMatchingMode === PlexSourceUserMatchingModeEnum.UsernameDeny}>
${t`Use the user's email address, but deny enrollment when the email address already exists.`} ${t`Use the user's email address, but deny enrollment when the email address already exists.`}
</option> </option>
<option value=${PlexSourceUserMatchingModeEnum.EmailLink} ?selected=${this.source?.userMatchingMode === PlexSourceUserMatchingModeEnum.EmailLink}> <option value=${PlexSourceUserMatchingModeEnum.EmailLink} ?selected=${this.instance?.userMatchingMode === PlexSourceUserMatchingModeEnum.EmailLink}>
${t`Link to a user with identical username address. Can have security implications when a username is used with another source.`} ${t`Link to a user with identical username address. Can have security implications when a username is used with another source.`}
</option> </option>
<option value=${PlexSourceUserMatchingModeEnum.EmailDeny} ?selected=${this.source?.userMatchingMode === PlexSourceUserMatchingModeEnum.EmailDeny}> <option value=${PlexSourceUserMatchingModeEnum.EmailDeny} ?selected=${this.instance?.userMatchingMode === PlexSourceUserMatchingModeEnum.EmailDeny}>
${t`Use the user's username, but deny enrollment when the username already exists.`} ${t`Use the user's username, but deny enrollment when the username already exists.`}
</option> </option>
</select> </select>
@ -129,11 +130,11 @@ export class PlexSourceForm extends Form<PlexSource> {
label=${t`Client ID`} label=${t`Client ID`}
?required=${true} ?required=${true}
name="clientId"> name="clientId">
<input type="text" value="${first(this.source?.clientId)}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.clientId)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="allowFriends"> <ak-form-element-horizontal name="allowFriends">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.allowFriends, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.allowFriends, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Allow friends to authenticate via Plex, even if you don't share any servers`} ${t`Allow friends to authenticate via Plex, even if you don't share any servers`}
</label> </label>
@ -145,7 +146,7 @@ export class PlexSourceForm extends Form<PlexSource> {
name="allowedServers"> name="allowedServers">
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
${this.plexResources?.map(r => { ${this.plexResources?.map(r => {
const selected = Array.from(this.source?.allowedServers || []).some(server => { const selected = Array.from(this.instance?.allowedServers || []).some(server => {
return server == r.clientIdentifier; return server == r.clientIdentifier;
}); });
return html`<option value=${r.clientIdentifier} ?selected=${selected}>${r.name}</option>`; return html`<option value=${r.clientIdentifier} ?selected=${selected}>${r.name}</option>`;
@ -178,8 +179,8 @@ export class PlexSourceForm extends Form<PlexSource> {
designation: FlowDesignationEnum.Authentication, designation: FlowDesignationEnum.Authentication,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.source?.authenticationFlow === flow.pk; let selected = this.instance?.authenticationFlow === flow.pk;
if (!this.source?.pk && !this.source?.authenticationFlow && flow.slug === "default-source-authentication") { if (!this.instance?.pk && !this.instance?.authenticationFlow && flow.slug === "default-source-authentication") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
@ -198,8 +199,8 @@ export class PlexSourceForm extends Form<PlexSource> {
designation: FlowDesignationEnum.Enrollment, designation: FlowDesignationEnum.Enrollment,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.source?.enrollmentFlow === flow.pk; let selected = this.instance?.enrollmentFlow === flow.pk;
if (!this.source?.pk && !this.source?.enrollmentFlow && flow.slug === "default-source-enrollment") { if (!this.instance?.pk && !this.instance?.enrollmentFlow && flow.slug === "default-source-enrollment") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;

View File

@ -82,7 +82,7 @@ export class PlexSourceViewPage extends LitElement {
</span> </span>
<ak-source-plex-form <ak-source-plex-form
slot="form" slot="form"
.sourceSlug=${this.source.slug}> .instancePk=${this.source.slug}>
</ak-source-plex-form> </ak-source-plex-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -1,31 +1,26 @@
import { SAMLSource, SourcesApi, SAMLSourceBindingTypeEnum, SAMLSourceNameIdPolicyEnum, CryptoApi, SAMLSourceDigestAlgorithmEnum, SAMLSourceSignatureAlgorithmEnum, FlowsApi, FlowDesignationEnum } from "authentik-api"; import { SAMLSource, SourcesApi, SAMLSourceBindingTypeEnum, SAMLSourceNameIdPolicyEnum, CryptoApi, SAMLSourceDigestAlgorithmEnum, SAMLSourceSignatureAlgorithmEnum, FlowsApi, FlowDesignationEnum } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-source-saml-form") @customElement("ak-source-saml-form")
export class SAMLSourceForm extends Form<SAMLSource> { export class SAMLSourceForm extends ModelForm<SAMLSource, string> {
set sourceSlug(value: string) { loadInstance(pk: string): Promise<SAMLSource> {
new SourcesApi(DEFAULT_CONFIG).sourcesSamlRead({ return new SourcesApi(DEFAULT_CONFIG).sourcesSamlRead({
slug: value, slug: pk,
}).then(source => {
this.source = source;
}); });
} }
@property({attribute: false})
source?: SAMLSource;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.source) { if (this.instance) {
return t`Successfully updated source.`; return t`Successfully updated source.`;
} else { } else {
return t`Successfully created source.`; return t`Successfully created source.`;
@ -33,9 +28,9 @@ export class SAMLSourceForm extends Form<SAMLSource> {
} }
send = (data: SAMLSource): Promise<SAMLSource> => { send = (data: SAMLSource): Promise<SAMLSource> => {
if (this.source) { if (this.instance) {
return new SourcesApi(DEFAULT_CONFIG).sourcesSamlUpdate({ return new SourcesApi(DEFAULT_CONFIG).sourcesSamlUpdate({
slug: this.source.slug, slug: this.instance.slug,
data: data data: data
}); });
} else { } else {
@ -51,17 +46,17 @@ export class SAMLSourceForm extends Form<SAMLSource> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.source?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Slug`} label=${t`Slug`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.source?.slug)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.slug)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="enabled"> <ak-form-element-horizontal name="enabled">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.enabled, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.enabled, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Enabled`} ${t`Enabled`}
</label> </label>
@ -77,19 +72,19 @@ export class SAMLSourceForm extends Form<SAMLSource> {
label=${t`SSO URL`} label=${t`SSO URL`}
?required=${true} ?required=${true}
name="ssoUrl"> name="ssoUrl">
<input type="text" value="${ifDefined(this.source?.ssoUrl)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.ssoUrl)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`URL that the initial Login request is sent to.`}</p> <p class="pf-c-form__helper-text">${t`URL that the initial Login request is sent to.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`SLO URL`} label=${t`SLO URL`}
name="sloUrl"> name="sloUrl">
<input type="text" value="${ifDefined(this.source?.sloUrl || "")}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.sloUrl || "")}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`Optional URL if the IDP supports Single-Logout.`}</p> <p class="pf-c-form__helper-text">${t`Optional URL if the IDP supports Single-Logout.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Issuer`} label=${t`Issuer`}
name="issuer"> name="issuer">
<input type="text" value="${ifDefined(this.source?.issuer)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.issuer)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${t`Also known as Entity ID. Defaults the Metadata URL.`}</p> <p class="pf-c-form__helper-text">${t`Also known as Entity ID. Defaults the Metadata URL.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
@ -97,13 +92,13 @@ export class SAMLSourceForm extends Form<SAMLSource> {
?required=${true} ?required=${true}
name="bindingType"> name="bindingType">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${SAMLSourceBindingTypeEnum.Redirect} ?selected=${this.source?.bindingType === SAMLSourceBindingTypeEnum.Redirect}> <option value=${SAMLSourceBindingTypeEnum.Redirect} ?selected=${this.instance?.bindingType === SAMLSourceBindingTypeEnum.Redirect}>
${t`Redirect binding`} ${t`Redirect binding`}
</option> </option>
<option value=${SAMLSourceBindingTypeEnum.PostAuto} ?selected=${this.source?.bindingType === SAMLSourceBindingTypeEnum.PostAuto}> <option value=${SAMLSourceBindingTypeEnum.PostAuto} ?selected=${this.instance?.bindingType === SAMLSourceBindingTypeEnum.PostAuto}>
${t`Post binding (auto-submit)`} ${t`Post binding (auto-submit)`}
</option> </option>
<option value=${SAMLSourceBindingTypeEnum.Post} ?selected=${this.source?.bindingType === SAMLSourceBindingTypeEnum.Post}> <option value=${SAMLSourceBindingTypeEnum.Post} ?selected=${this.instance?.bindingType === SAMLSourceBindingTypeEnum.Post}>
${t`Post binding`} ${t`Post binding`}
</option> </option>
</select> </select>
@ -112,12 +107,12 @@ export class SAMLSourceForm extends Form<SAMLSource> {
label=${t`Signing keypair`} label=${t`Signing keypair`}
name="signingKp"> name="signingKp">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.source?.signingKp === undefined}>---------</option> <option value="" ?selected=${this.instance?.signingKp === undefined}>---------</option>
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({ ${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
ordering: "pk", ordering: "pk",
}).then(keys => { }).then(keys => {
return keys.results.map(key => { return keys.results.map(key => {
return html`<option value=${ifDefined(key.pk)} ?selected=${this.source?.signingKp === key.pk}>${key.name}</option>`; return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.signingKp === key.pk}>${key.name}</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
</select> </select>
@ -132,7 +127,7 @@ export class SAMLSourceForm extends Form<SAMLSource> {
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="allowIdpInitiated"> <ak-form-element-horizontal name="allowIdpInitiated">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.source?.allowIdpInitiated, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.allowIdpInitiated, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t` Allow IDP-initiated logins`} ${t` Allow IDP-initiated logins`}
</label> </label>
@ -144,19 +139,19 @@ export class SAMLSourceForm extends Form<SAMLSource> {
?required=${true} ?required=${true}
name="nameIdPolicy"> name="nameIdPolicy">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${SAMLSourceNameIdPolicyEnum._20nameidFormatpersistent} ?selected=${this.source?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormatpersistent}> <option value=${SAMLSourceNameIdPolicyEnum._20nameidFormatpersistent} ?selected=${this.instance?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormatpersistent}>
${t`Persistent`} ${t`Persistent`}
</option> </option>
<option value=${SAMLSourceNameIdPolicyEnum._11nameidFormatemailAddress} ?selected=${this.source?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._11nameidFormatemailAddress}> <option value=${SAMLSourceNameIdPolicyEnum._11nameidFormatemailAddress} ?selected=${this.instance?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._11nameidFormatemailAddress}>
${t`Email address`} ${t`Email address`}
</option> </option>
<option value=${SAMLSourceNameIdPolicyEnum._20nameidFormatWindowsDomainQualifiedName} ?selected=${this.source?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormatWindowsDomainQualifiedName}> <option value=${SAMLSourceNameIdPolicyEnum._20nameidFormatWindowsDomainQualifiedName} ?selected=${this.instance?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormatWindowsDomainQualifiedName}>
${t`Windows`} ${t`Windows`}
</option> </option>
<option value=${SAMLSourceNameIdPolicyEnum._20nameidFormatX509SubjectName} ?selected=${this.source?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormatX509SubjectName}> <option value=${SAMLSourceNameIdPolicyEnum._20nameidFormatX509SubjectName} ?selected=${this.instance?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormatX509SubjectName}>
${t`X509 Subject`} ${t`X509 Subject`}
</option> </option>
<option value=${SAMLSourceNameIdPolicyEnum._20nameidFormattransient} ?selected=${this.source?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormattransient}> <option value=${SAMLSourceNameIdPolicyEnum._20nameidFormattransient} ?selected=${this.instance?.nameIdPolicy === SAMLSourceNameIdPolicyEnum._20nameidFormattransient}>
${t`Transient`} ${t`Transient`}
</option> </option>
</select> </select>
@ -165,7 +160,7 @@ export class SAMLSourceForm extends Form<SAMLSource> {
label=${t`Delete temporary users after`} label=${t`Delete temporary users after`}
?required=${true} ?required=${true}
name="temporaryUserDeleteAfter"> name="temporaryUserDeleteAfter">
<input type="text" value="${this.source?.temporaryUserDeleteAfter || "days=1"}" class="pf-c-form-control" required> <input type="text" value="${this.instance?.temporaryUserDeleteAfter || "days=1"}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3).`}</p> <p class="pf-c-form__helper-text">${t`Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually. (Format: hours=1;minutes=2;seconds=3).`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
@ -173,16 +168,16 @@ export class SAMLSourceForm extends Form<SAMLSource> {
?required=${true} ?required=${true}
name="digestAlgorithm"> name="digestAlgorithm">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${SAMLSourceDigestAlgorithmEnum._200009Xmldsigsha1} ?selected=${this.source?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200009Xmldsigsha1}> <option value=${SAMLSourceDigestAlgorithmEnum._200009Xmldsigsha1} ?selected=${this.instance?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200009Xmldsigsha1}>
${t`SHA1`} ${t`SHA1`}
</option> </option>
<option value=${SAMLSourceDigestAlgorithmEnum._200104Xmlencsha256} ?selected=${this.source?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200104Xmlencsha256 || this.source?.digestAlgorithm === undefined}> <option value=${SAMLSourceDigestAlgorithmEnum._200104Xmlencsha256} ?selected=${this.instance?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200104Xmlencsha256 || this.instance?.digestAlgorithm === undefined}>
${t`SHA256`} ${t`SHA256`}
</option> </option>
<option value=${SAMLSourceDigestAlgorithmEnum._200104XmldsigMoresha384} ?selected=${this.source?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200104XmldsigMoresha384}> <option value=${SAMLSourceDigestAlgorithmEnum._200104XmldsigMoresha384} ?selected=${this.instance?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200104XmldsigMoresha384}>
${t`SHA384`} ${t`SHA384`}
</option> </option>
<option value=${SAMLSourceDigestAlgorithmEnum._200104Xmlencsha512} ?selected=${this.source?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200104Xmlencsha512}> <option value=${SAMLSourceDigestAlgorithmEnum._200104Xmlencsha512} ?selected=${this.instance?.digestAlgorithm === SAMLSourceDigestAlgorithmEnum._200104Xmlencsha512}>
${t`SHA512`} ${t`SHA512`}
</option> </option>
</select> </select>
@ -192,19 +187,19 @@ export class SAMLSourceForm extends Form<SAMLSource> {
?required=${true} ?required=${true}
name="signatureAlgorithm"> name="signatureAlgorithm">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${SAMLSourceSignatureAlgorithmEnum._200009XmldsigrsaSha1} ?selected=${this.source?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200009XmldsigrsaSha1}> <option value=${SAMLSourceSignatureAlgorithmEnum._200009XmldsigrsaSha1} ?selected=${this.instance?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200009XmldsigrsaSha1}>
${t`RSA-SHA1`} ${t`RSA-SHA1`}
</option> </option>
<option value=${SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha256} ?selected=${this.source?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha256 || this.source?.signatureAlgorithm === undefined}> <option value=${SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha256} ?selected=${this.instance?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha256 || this.instance?.signatureAlgorithm === undefined}>
${t`RSA-SHA256`} ${t`RSA-SHA256`}
</option> </option>
<option value=${SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha384} ?selected=${this.source?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha384}> <option value=${SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha384} ?selected=${this.instance?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha384}>
${t`RSA-SHA384`} ${t`RSA-SHA384`}
</option> </option>
<option value=${SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha512} ?selected=${this.source?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha512}> <option value=${SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha512} ?selected=${this.instance?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200104XmldsigMorersaSha512}>
${t`RSA-SHA512`} ${t`RSA-SHA512`}
</option> </option>
<option value=${SAMLSourceSignatureAlgorithmEnum._200009XmldsigdsaSha1} ?selected=${this.source?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200009XmldsigdsaSha1}> <option value=${SAMLSourceSignatureAlgorithmEnum._200009XmldsigdsaSha1} ?selected=${this.instance?.signatureAlgorithm === SAMLSourceSignatureAlgorithmEnum._200009XmldsigdsaSha1}>
${t`DSA-SHA1`} ${t`DSA-SHA1`}
</option> </option>
</select> </select>
@ -226,8 +221,8 @@ export class SAMLSourceForm extends Form<SAMLSource> {
designation: FlowDesignationEnum.StageConfiguration, designation: FlowDesignationEnum.StageConfiguration,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.source?.preAuthenticationFlow === flow.pk; let selected = this.instance?.preAuthenticationFlow === flow.pk;
if (!this.source?.pk && !this.source?.preAuthenticationFlow && flow.slug === "default-source-pre-authentication") { if (!this.instance?.pk && !this.instance?.preAuthenticationFlow && flow.slug === "default-source-pre-authentication") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
@ -246,8 +241,8 @@ export class SAMLSourceForm extends Form<SAMLSource> {
designation: FlowDesignationEnum.Authentication, designation: FlowDesignationEnum.Authentication,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.source?.authenticationFlow === flow.pk; let selected = this.instance?.authenticationFlow === flow.pk;
if (!this.source?.pk && !this.source?.authenticationFlow && flow.slug === "default-source-authentication") { if (!this.instance?.pk && !this.instance?.authenticationFlow && flow.slug === "default-source-authentication") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
@ -266,8 +261,8 @@ export class SAMLSourceForm extends Form<SAMLSource> {
designation: FlowDesignationEnum.Enrollment, designation: FlowDesignationEnum.Enrollment,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.source?.enrollmentFlow === flow.pk; let selected = this.instance?.enrollmentFlow === flow.pk;
if (!this.source?.pk && !this.source?.enrollmentFlow && flow.slug === "default-source-enrollment") { if (!this.instance?.pk && !this.instance?.enrollmentFlow && flow.slug === "default-source-enrollment") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;

View File

@ -109,7 +109,7 @@ export class SAMLSourceViewPage extends LitElement {
</span> </span>
<ak-source-saml-form <ak-source-saml-form
slot="form" slot="form"
.sourceSlug=${this.source.slug}> .instancePk=${this.source.slug}>
</ak-source-saml-form> </ak-source-saml-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${t`Edit`} ${t`Edit`}

View File

@ -90,7 +90,7 @@ export class StageListPage extends TablePage<Stage> {
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
.args=${{ .args=${{
"stageUUID": item.pk "instancePk": item.pk
}} }}
type=${ifDefined(item.component)}> type=${ifDefined(item.component)}>
</ak-proxy-form> </ak-proxy-form>

View File

@ -1,31 +1,26 @@
import { FlowDesignationEnum, FlowsApi, AuthenticatorStaticStage, StagesApi } from "authentik-api"; import { FlowDesignationEnum, FlowsApi, AuthenticatorStaticStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-authenticator-static-form") @customElement("ak-stage-authenticator-static-form")
export class AuthenticatorStaticStageForm extends Form<AuthenticatorStaticStage> { export class AuthenticatorStaticStageForm extends ModelForm<AuthenticatorStaticStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<AuthenticatorStaticStage> {
new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorStaticRead({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorStaticRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: AuthenticatorStaticStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -33,9 +28,9 @@ export class AuthenticatorStaticStageForm extends Form<AuthenticatorStaticStage>
} }
send = (data: AuthenticatorStaticStage): Promise<AuthenticatorStaticStage> => { send = (data: AuthenticatorStaticStage): Promise<AuthenticatorStaticStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorStaticUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorStaticUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -54,7 +49,7 @@ export class AuthenticatorStaticStageForm extends Form<AuthenticatorStaticStage>
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -65,20 +60,20 @@ export class AuthenticatorStaticStageForm extends Form<AuthenticatorStaticStage>
label=${t`Token count`} label=${t`Token count`}
?required=${true} ?required=${true}
name="tokenCount"> name="tokenCount">
<input type="text" value="${first(this.stage?.tokenCount, 6)}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.tokenCount, 6)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Configuration flow`} label=${t`Configuration flow`}
name="configureFlow"> name="configureFlow">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.stage?.configureFlow === undefined}>---------</option> <option value="" ?selected=${this.instance?.configureFlow === undefined}>---------</option>
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ ${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk", ordering: "pk",
designation: FlowDesignationEnum.StageConfiguration, designation: FlowDesignationEnum.StageConfiguration,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.stage?.configureFlow === flow.pk; let selected = this.instance?.configureFlow === flow.pk;
if (!this.stage?.pk && !this.stage?.configureFlow && flow.slug === "default-otp-time-configure") { if (!this.instance?.pk && !this.instance?.configureFlow && flow.slug === "default-otp-time-configure") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;

View File

@ -1,30 +1,25 @@
import { FlowDesignationEnum, FlowsApi, AuthenticatorTOTPStage, StagesApi } from "authentik-api"; import { FlowDesignationEnum, FlowsApi, AuthenticatorTOTPStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-authenticator-totp-form") @customElement("ak-stage-authenticator-totp-form")
export class AuthenticatorTOTPStageForm extends Form<AuthenticatorTOTPStage> { export class AuthenticatorTOTPStageForm extends ModelForm<AuthenticatorTOTPStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<AuthenticatorTOTPStage> {
new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorTotpRead({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorTotpRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: AuthenticatorTOTPStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -32,9 +27,9 @@ export class AuthenticatorTOTPStageForm extends Form<AuthenticatorTOTPStage> {
} }
send = (data: AuthenticatorTOTPStage): Promise<AuthenticatorTOTPStage> => { send = (data: AuthenticatorTOTPStage): Promise<AuthenticatorTOTPStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorTotpUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorTotpUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -53,7 +48,7 @@ export class AuthenticatorTOTPStageForm extends Form<AuthenticatorTOTPStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -65,10 +60,10 @@ export class AuthenticatorTOTPStageForm extends Form<AuthenticatorTOTPStage> {
?required=${true} ?required=${true}
name="digits"> name="digits">
<select name="users" class="pf-c-form-control"> <select name="users" class="pf-c-form-control">
<option value="6" ?selected=${this.stage?.digits === 6}> <option value="6" ?selected=${this.instance?.digits === 6}>
${t`6 digits, widely compatible`} ${t`6 digits, widely compatible`}
</option> </option>
<option value="8" ?selected=${this.stage?.digits === 8}> <option value="8" ?selected=${this.instance?.digits === 8}>
${t`8 digits, not compatible with apps like Google Authenticator`} ${t`8 digits, not compatible with apps like Google Authenticator`}
</option> </option>
</select> </select>
@ -77,14 +72,14 @@ export class AuthenticatorTOTPStageForm extends Form<AuthenticatorTOTPStage> {
label=${t`Configuration flow`} label=${t`Configuration flow`}
name="configureFlow"> name="configureFlow">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.stage?.configureFlow === undefined}>---------</option> <option value="" ?selected=${this.instance?.configureFlow === undefined}>---------</option>
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ ${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk", ordering: "pk",
designation: FlowDesignationEnum.StageConfiguration, designation: FlowDesignationEnum.StageConfiguration,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.stage?.configureFlow === flow.pk; let selected = this.instance?.configureFlow === flow.pk;
if (!this.stage?.pk && !this.stage?.configureFlow && flow.slug === "default-otp-time-configure") { if (!this.instance?.pk && !this.instance?.configureFlow && flow.slug === "default-otp-time-configure") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;

View File

@ -3,32 +3,29 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-authenticator-validate-form") @customElement("ak-stage-authenticator-validate-form")
export class AuthenticatorValidateStageForm extends Form<AuthenticatorValidateStage> { export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValidateStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<AuthenticatorValidateStage> {
new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorValidateRead({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorValidateRead({
stageUuid: value, stageUuid: pk,
}).then(stage => { }).then(stage => {
this.stage = stage;
this.showConfigureFlow = stage.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Configure; this.showConfigureFlow = stage.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Configure;
return stage;
}); });
} }
@property({attribute: false})
stage?: AuthenticatorValidateStage;
@property({ type: Boolean }) @property({ type: Boolean })
showConfigureFlow = false; showConfigureFlow = false;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -36,9 +33,9 @@ export class AuthenticatorValidateStageForm extends Form<AuthenticatorValidateSt
} }
send = (data: AuthenticatorValidateStage): Promise<AuthenticatorValidateStage> => { send = (data: AuthenticatorValidateStage): Promise<AuthenticatorValidateStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorValidateUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorValidateUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -49,7 +46,7 @@ export class AuthenticatorValidateStageForm extends Form<AuthenticatorValidateSt
}; };
isDeviceClassSelected(field: AuthenticatorValidateStageDeviceClassesEnum): boolean { isDeviceClassSelected(field: AuthenticatorValidateStageDeviceClassesEnum): boolean {
return (this.stage?.deviceClasses || []).filter(isField => { return (this.instance?.deviceClasses || []).filter(isField => {
return field === isField; return field === isField;
}).length > 0; }).length > 0;
} }
@ -63,7 +60,7 @@ export class AuthenticatorValidateStageForm extends Form<AuthenticatorValidateSt
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -82,13 +79,13 @@ export class AuthenticatorValidateStageForm extends Form<AuthenticatorValidateSt
this.showConfigureFlow = false; this.showConfigureFlow = false;
} }
}}> }}>
<option value=${AuthenticatorValidateStageNotConfiguredActionEnum.Configure} ?selected=${this.stage?.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Configure}> <option value=${AuthenticatorValidateStageNotConfiguredActionEnum.Configure} ?selected=${this.instance?.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Configure}>
${t`Force the user to configure an authenticator`} ${t`Force the user to configure an authenticator`}
</option> </option>
<option value=${AuthenticatorValidateStageNotConfiguredActionEnum.Deny} ?selected=${this.stage?.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Deny}> <option value=${AuthenticatorValidateStageNotConfiguredActionEnum.Deny} ?selected=${this.instance?.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Deny}>
${t`Deny the user access`} ${t`Deny the user access`}
</option> </option>
<option value=${AuthenticatorValidateStageNotConfiguredActionEnum.Skip} ?selected=${this.stage?.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Skip}> <option value=${AuthenticatorValidateStageNotConfiguredActionEnum.Skip} ?selected=${this.instance?.notConfiguredAction === AuthenticatorValidateStageNotConfiguredActionEnum.Skip}>
${t`Continue`} ${t`Continue`}
</option> </option>
</select> </select>
@ -117,12 +114,12 @@ export class AuthenticatorValidateStageForm extends Form<AuthenticatorValidateSt
?required=${true} ?required=${true}
name="configureFlow"> name="configureFlow">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.stage?.configurationStage === undefined}>---------</option> <option value="" ?selected=${this.instance?.configurationStage === undefined}>---------</option>
${until(new StagesApi(DEFAULT_CONFIG).stagesAllList({ ${until(new StagesApi(DEFAULT_CONFIG).stagesAllList({
ordering: "pk", ordering: "pk",
}).then(stages => { }).then(stages => {
return stages.results.map(stage => { return stages.results.map(stage => {
const selected = this.stage?.configurationStage === stage.pk; const selected = this.instance?.configurationStage === stage.pk;
return html`<option value=${ifDefined(stage.pk)} ?selected=${selected}>${stage.name} (${stage.verboseName})</option>`; return html`<option value=${ifDefined(stage.pk)} ?selected=${selected}>${stage.name} (${stage.verboseName})</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}

View File

@ -1,28 +1,23 @@
import { AuthenticateWebAuthnStage, StagesApi } from "authentik-api"; import { AuthenticateWebAuthnStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-authenticator-webauthn-form") @customElement("ak-stage-authenticator-webauthn-form")
export class AuthenticateWebAuthnStageForm extends Form<AuthenticateWebAuthnStage> { export class AuthenticateWebAuthnStageForm extends ModelForm<AuthenticateWebAuthnStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<AuthenticateWebAuthnStage> {
new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnRead({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: AuthenticateWebAuthnStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -30,9 +25,9 @@ export class AuthenticateWebAuthnStageForm extends Form<AuthenticateWebAuthnStag
} }
send = (data: AuthenticateWebAuthnStage): Promise<AuthenticateWebAuthnStage> => { send = (data: AuthenticateWebAuthnStage): Promise<AuthenticateWebAuthnStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -51,7 +46,7 @@ export class AuthenticateWebAuthnStageForm extends Form<AuthenticateWebAuthnStag
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,29 +1,24 @@
import { CaptchaStage, StagesApi } from "authentik-api"; import { CaptchaStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-captcha-form") @customElement("ak-stage-captcha-form")
export class CaptchaStageForm extends Form<CaptchaStage> { export class CaptchaStageForm extends ModelForm<CaptchaStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<CaptchaStage> {
new StagesApi(DEFAULT_CONFIG).stagesCaptchaRead({ return new StagesApi(DEFAULT_CONFIG).stagesCaptchaRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: CaptchaStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -31,9 +26,9 @@ export class CaptchaStageForm extends Form<CaptchaStage> {
} }
send = (data: CaptchaStage): Promise<CaptchaStage> => { send = (data: CaptchaStage): Promise<CaptchaStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesCaptchaPartialUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesCaptchaPartialUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -52,7 +47,7 @@ export class CaptchaStageForm extends Form<CaptchaStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -63,15 +58,15 @@ export class CaptchaStageForm extends Form<CaptchaStage> {
label=${t`Public Key`} label=${t`Public Key`}
?required=${true} ?required=${true}
name="publicKey"> name="publicKey">
<input type="text" value="${ifDefined(this.stage?.publicKey || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.publicKey || "")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Public key, acquired from https://www.google.com/recaptcha/intro/v3.html.`}</p> <p class="pf-c-form__helper-text">${t`Public key, acquired from https://www.google.com/recaptcha/intro/v3.html.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Private Key`} label=${t`Private Key`}
?required=${true} ?required=${true}
?writeOnly=${this.stage !== undefined} ?writeOnly=${this.instance !== undefined}
name="privateKey"> name="privateKey">
<input type="text" value="${ifDefined(this.stage?.privateKey || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.privateKey || "")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Private key, acquired from https://www.google.com/recaptcha/intro/v3.html.`}</p> <p class="pf-c-form__helper-text">${t`Private key, acquired from https://www.google.com/recaptcha/intro/v3.html.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -3,31 +3,28 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-consent-form") @customElement("ak-stage-consent-form")
export class ConsentStageForm extends Form<ConsentStage> { export class ConsentStageForm extends ModelForm<ConsentStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<ConsentStage> {
new StagesApi(DEFAULT_CONFIG).stagesConsentRead({ return new StagesApi(DEFAULT_CONFIG).stagesConsentRead({
stageUuid: value, stageUuid: pk,
}).then(stage => { }).then(stage => {
this.stage = stage;
this.showExpiresIn = stage.name === ConsentStageModeEnum.Expiring; this.showExpiresIn = stage.name === ConsentStageModeEnum.Expiring;
return stage;
}); });
} }
@property({attribute: false})
stage?: ConsentStage;
@property({type: Boolean}) @property({type: Boolean})
showExpiresIn = false; showExpiresIn = false;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -35,9 +32,9 @@ export class ConsentStageForm extends Form<ConsentStage> {
} }
send = (data: ConsentStage): Promise<ConsentStage> => { send = (data: ConsentStage): Promise<ConsentStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesConsentUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesConsentUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -56,7 +53,7 @@ export class ConsentStageForm extends Form<ConsentStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -75,13 +72,13 @@ export class ConsentStageForm extends Form<ConsentStage> {
this.showExpiresIn = false; this.showExpiresIn = false;
} }
}}> }}>
<option value=${ConsentStageModeEnum.AlwaysRequire} ?selected=${this.stage?.mode === ConsentStageModeEnum.AlwaysRequire}> <option value=${ConsentStageModeEnum.AlwaysRequire} ?selected=${this.instance?.mode === ConsentStageModeEnum.AlwaysRequire}>
${t`Always require consent`} ${t`Always require consent`}
</option> </option>
<option value=${ConsentStageModeEnum.Permanent} ?selected=${this.stage?.mode === ConsentStageModeEnum.Permanent}> <option value=${ConsentStageModeEnum.Permanent} ?selected=${this.instance?.mode === ConsentStageModeEnum.Permanent}>
${t`Consent given last indefinitely`} ${t`Consent given last indefinitely`}
</option> </option>
<option value=${ConsentStageModeEnum.Expiring} ?selected=${this.stage?.mode === ConsentStageModeEnum.Expiring}> <option value=${ConsentStageModeEnum.Expiring} ?selected=${this.instance?.mode === ConsentStageModeEnum.Expiring}>
${t`Consent expires.`} ${t`Consent expires.`}
</option> </option>
</select> </select>
@ -91,7 +88,7 @@ export class ConsentStageForm extends Form<ConsentStage> {
label=${t`Consent expires in`} label=${t`Consent expires in`}
?required=${true} ?required=${true}
name="consentExpireIn"> name="consentExpireIn">
<input type="text" value="${ifDefined(this.stage?.consentExpireIn || "weeks=4")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.consentExpireIn || "weeks=4")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3).`}</p> <p class="pf-c-form__helper-text">${t`Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3).`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -1,28 +1,23 @@
import { DenyStage, StagesApi } from "authentik-api"; import { DenyStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-deny-form") @customElement("ak-stage-deny-form")
export class DenyStageForm extends Form<DenyStage> { export class DenyStageForm extends ModelForm<DenyStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<DenyStage> {
new StagesApi(DEFAULT_CONFIG).stagesDenyRead({ return new StagesApi(DEFAULT_CONFIG).stagesDenyRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: DenyStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -30,9 +25,9 @@ export class DenyStageForm extends Form<DenyStage> {
} }
send = (data: DenyStage): Promise<DenyStage> => { send = (data: DenyStage): Promise<DenyStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesDenyUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesDenyUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -51,7 +46,7 @@ export class DenyStageForm extends Form<DenyStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,28 +1,23 @@
import { DummyStage, StagesApi } from "authentik-api"; import { DummyStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-dummy-form") @customElement("ak-stage-dummy-form")
export class DummyStageForm extends Form<DummyStage> { export class DummyStageForm extends ModelForm<DummyStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<DummyStage> {
new StagesApi(DEFAULT_CONFIG).stagesDummyRead({ return new StagesApi(DEFAULT_CONFIG).stagesDummyRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: DummyStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -30,9 +25,9 @@ export class DummyStageForm extends Form<DummyStage> {
} }
send = (data: DummyStage): Promise<DummyStage> => { send = (data: DummyStage): Promise<DummyStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesDummyUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesDummyUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -51,7 +46,7 @@ export class DummyStageForm extends Form<DummyStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -3,32 +3,30 @@ import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-email-form") @customElement("ak-stage-email-form")
export class EmailStageForm extends Form<EmailStage> { export class EmailStageForm extends ModelForm<EmailStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<EmailStage> {
new StagesApi(DEFAULT_CONFIG).stagesEmailRead({ return new StagesApi(DEFAULT_CONFIG).stagesEmailRead({
stageUuid: value, stageUuid: pk,
}).then(stage => { }).then(stage => {
this.stage = stage; this.showConnectionSettings = !stage.useGlobalSettings;
return stage;
}); });
} }
@property({attribute: false})
stage?: EmailStage;
@property({type: Boolean}) @property({type: Boolean})
showConnectionSettings = false; showConnectionSettings = false;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -36,9 +34,9 @@ export class EmailStageForm extends Form<EmailStage> {
} }
send = (data: EmailStage): Promise<EmailStage> => { send = (data: EmailStage): Promise<EmailStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesEmailPartialUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesEmailPartialUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -61,28 +59,28 @@ export class EmailStageForm extends Form<EmailStage> {
label=${t`SMTP Host`} label=${t`SMTP Host`}
?required=${true} ?required=${true}
name="host"> name="host">
<input type="text" value="${ifDefined(this.stage?.host || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.host || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`SMTP Port`} label=${t`SMTP Port`}
?required=${true} ?required=${true}
name="port"> name="port">
<input type="number" value="${first(this.stage?.port, 25)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.port, 25)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`SMTP Username`} label=${t`SMTP Username`}
name="username"> name="username">
<input type="text" value="${ifDefined(this.stage?.username || "")}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.username || "")}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`SMTP Password`} label=${t`SMTP Password`}
?writeOnly=${this.stage !== undefined} ?writeOnly=${this.instance !== undefined}
name="password"> name="password">
<input type="text" value="${ifDefined(this.stage?.password || "")}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.instance?.password || "")}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="useTls"> <ak-form-element-horizontal name="useTls">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.stage?.useTls, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.useTls, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Use TLS`} ${t`Use TLS`}
</label> </label>
@ -90,7 +88,7 @@ export class EmailStageForm extends Form<EmailStage> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="useSsl"> <ak-form-element-horizontal name="useSsl">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.stage?.useSsl, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.useSsl, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Use SSL`} ${t`Use SSL`}
</label> </label>
@ -100,13 +98,13 @@ export class EmailStageForm extends Form<EmailStage> {
label=${t`Timeout`} label=${t`Timeout`}
?required=${true} ?required=${true}
name="timeout"> name="timeout">
<input type="number" value="${first(this.stage?.timeout, 30)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.timeout, 30)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`From address`} label=${t`From address`}
?required=${true} ?required=${true}
name="fromAddress"> name="fromAddress">
<input type="text" value="${ifDefined(this.stage?.fromAddress || "system@authentik.local")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.fromAddress || "system@authentik.local")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>
</ak-form-group>`; </ak-form-group>`;
@ -121,7 +119,7 @@ export class EmailStageForm extends Form<EmailStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -130,7 +128,7 @@ export class EmailStageForm extends Form<EmailStage> {
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="useGlobalSettings"> <ak-form-element-horizontal name="useGlobalSettings">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.stage?.useGlobalSettings, true)} @change=${(ev: Event) => { <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.useGlobalSettings, true)} @change=${(ev: Event) => {
const target = ev.target as HTMLInputElement; const target = ev.target as HTMLInputElement;
this.showConnectionSettings = !target.checked; this.showConnectionSettings = !target.checked;
}}> }}>
@ -144,14 +142,14 @@ export class EmailStageForm extends Form<EmailStage> {
label=${t`Token expiry`} label=${t`Token expiry`}
?required=${true} ?required=${true}
name="tokenExpiry"> name="tokenExpiry">
<input type="number" value="${first(this.stage?.tokenExpiry, 30)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.tokenExpiry, 30)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Time in minutes the token sent is valid.`}</p> <p class="pf-c-form__helper-text">${t`Time in minutes the token sent is valid.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Subject`} label=${t`Subject`}
?required=${true} ?required=${true}
name="subject"> name="subject">
<input type="text" value="${first(this.stage?.subject, "authentik")}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.subject, "authentik")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Template`} label=${t`Template`}
@ -160,7 +158,7 @@ export class EmailStageForm extends Form<EmailStage> {
<select name="users" class="pf-c-form-control"> <select name="users" class="pf-c-form-control">
${until(new StagesApi(DEFAULT_CONFIG).stagesEmailTemplates().then(templates => { ${until(new StagesApi(DEFAULT_CONFIG).stagesEmailTemplates().then(templates => {
return templates.map(template => { return templates.map(template => {
const selected = this.stage?.template === template.name; const selected = this.instance?.template === template.name;
return html`<option value=${ifDefined(template.name)} ?selected=${selected}> return html`<option value=${ifDefined(template.name)} ?selected=${selected}>
${template.description} ${template.description}
</option>`; </option>`;

View File

@ -1,31 +1,26 @@
import { FlowDesignationEnum, FlowsApi, IdentificationStage, IdentificationStageUserFieldsEnum, StagesApi } from "authentik-api"; import { FlowDesignationEnum, FlowsApi, IdentificationStage, IdentificationStageUserFieldsEnum, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-identification-form") @customElement("ak-stage-identification-form")
export class IdentificationStageForm extends Form<IdentificationStage> { export class IdentificationStageForm extends ModelForm<IdentificationStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<IdentificationStage> {
new StagesApi(DEFAULT_CONFIG).stagesIdentificationRead({ return new StagesApi(DEFAULT_CONFIG).stagesIdentificationRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: IdentificationStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -33,9 +28,9 @@ export class IdentificationStageForm extends Form<IdentificationStage> {
} }
send = (data: IdentificationStage): Promise<IdentificationStage> => { send = (data: IdentificationStage): Promise<IdentificationStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesIdentificationUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesIdentificationUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -46,7 +41,7 @@ export class IdentificationStageForm extends Form<IdentificationStage> {
}; };
isUserFieldSelected(field: IdentificationStageUserFieldsEnum): boolean { isUserFieldSelected(field: IdentificationStageUserFieldsEnum): boolean {
return (this.stage?.userFields || []).filter(isField => { return (this.instance?.userFields || []).filter(isField => {
return field === isField; return field === isField;
}).length > 0; }).length > 0;
} }
@ -60,7 +55,7 @@ export class IdentificationStageForm extends Form<IdentificationStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -83,7 +78,7 @@ export class IdentificationStageForm extends Form<IdentificationStage> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="caseInsensitiveMatching"> <ak-form-element-horizontal name="caseInsensitiveMatching">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.stage?.caseInsensitiveMatching, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.caseInsensitiveMatching, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Case insensitive matching`} ${t`Case insensitive matching`}
</label> </label>
@ -92,7 +87,7 @@ export class IdentificationStageForm extends Form<IdentificationStage> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="showMatchedUser"> <ak-form-element-horizontal name="showMatchedUser">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.stage?.showMatchedUser, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.showMatchedUser, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Show matched user`} ${t`Show matched user`}
</label> </label>
@ -103,13 +98,13 @@ export class IdentificationStageForm extends Form<IdentificationStage> {
label=${t`Enrollment flow`} label=${t`Enrollment flow`}
name="enrollmentFlow"> name="enrollmentFlow">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.stage?.enrollmentFlow === undefined}>---------</option> <option value="" ?selected=${this.instance?.enrollmentFlow === undefined}>---------</option>
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ ${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk", ordering: "pk",
designation: FlowDesignationEnum.Enrollment, designation: FlowDesignationEnum.Enrollment,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
const selected = this.stage?.enrollmentFlow === flow.pk; const selected = this.instance?.enrollmentFlow === flow.pk;
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}
@ -120,13 +115,13 @@ export class IdentificationStageForm extends Form<IdentificationStage> {
label=${t`Recovery flow`} label=${t`Recovery flow`}
name="recoveryFlow"> name="recoveryFlow">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.stage?.recoveryFlow === undefined}>---------</option> <option value="" ?selected=${this.instance?.recoveryFlow === undefined}>---------</option>
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ ${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk", ordering: "pk",
designation: FlowDesignationEnum.Recovery, designation: FlowDesignationEnum.Recovery,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
const selected = this.stage?.recoveryFlow === flow.pk; const selected = this.instance?.recoveryFlow === flow.pk;
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
}); });
}), html`<option>${t`Loading...`}</option>`)} }), html`<option>${t`Loading...`}</option>`)}

View File

@ -1,22 +1,25 @@
import { Invitation, StagesApi } from "authentik-api"; import { Invitation, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/CodeMirror"; import "../../../elements/CodeMirror";
import YAML from "yaml"; import YAML from "yaml";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-invitation-form") @customElement("ak-invitation-form")
export class InvitationForm extends Form<Invitation> { export class InvitationForm extends ModelForm<Invitation, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<Invitation> {
invitation?: Invitation; return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsRead({
inviteUuid: pk,
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.invitation) { if (this.instance) {
return t`Successfully updated invitation.`; return t`Successfully updated invitation.`;
} else { } else {
return t`Successfully created invitation.`; return t`Successfully created invitation.`;
@ -24,9 +27,9 @@ export class InvitationForm extends Form<Invitation> {
} }
send = (data: Invitation): Promise<Invitation> => { send = (data: Invitation): Promise<Invitation> => {
if (this.invitation) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesInvitationInvitationsUpdate({
inviteUuid: this.invitation.pk || "", inviteUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -47,13 +50,13 @@ export class InvitationForm extends Form<Invitation> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Attributes`} label=${t`Attributes`}
name="fixedData"> name="fixedData">
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.invitation?.fixedData, {}))}"> <ak-codemirror mode="yaml" value="${YAML.stringify(first(this.instance?.fixedData, {}))}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${t`Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON.`}</p> <p class="pf-c-form__helper-text">${t`Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="singleUse"> <ak-form-element-horizontal name="singleUse">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.invitation?.singleUse, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.singleUse, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Single use`} ${t`Single use`}
</label> </label>

View File

@ -1,30 +1,25 @@
import { InvitationStage, StagesApi } from "authentik-api"; import { InvitationStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-invitation-form") @customElement("ak-stage-invitation-form")
export class InvitationStageForm extends Form<InvitationStage> { export class InvitationStageForm extends ModelForm<InvitationStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<InvitationStage> {
new StagesApi(DEFAULT_CONFIG).stagesInvitationStagesRead({ return new StagesApi(DEFAULT_CONFIG).stagesInvitationStagesRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: InvitationStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -32,9 +27,9 @@ export class InvitationStageForm extends Form<InvitationStage> {
} }
send = (data: InvitationStage): Promise<InvitationStage> => { send = (data: InvitationStage): Promise<InvitationStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesInvitationStagesUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesInvitationStagesUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -53,7 +48,7 @@ export class InvitationStageForm extends Form<InvitationStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -62,7 +57,7 @@ export class InvitationStageForm extends Form<InvitationStage> {
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="continueFlowWithoutInvitation"> <ak-form-element-horizontal name="continueFlowWithoutInvitation">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.stage?.continueFlowWithoutInvitation, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.continueFlowWithoutInvitation, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Continue flow without invitation`} ${t`Continue flow without invitation`}
</label> </label>

View File

@ -1,31 +1,26 @@
import { FlowDesignationEnum, FlowsApi, PasswordStage, PasswordStageBackendsEnum, StagesApi } from "authentik-api"; import { FlowDesignationEnum, FlowsApi, PasswordStage, PasswordStageBackendsEnum, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-password-form") @customElement("ak-stage-password-form")
export class PasswordStageForm extends Form<PasswordStage> { export class PasswordStageForm extends ModelForm<PasswordStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<PasswordStage> {
new StagesApi(DEFAULT_CONFIG).stagesPasswordRead({ return new StagesApi(DEFAULT_CONFIG).stagesPasswordRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: PasswordStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -33,9 +28,9 @@ export class PasswordStageForm extends Form<PasswordStage> {
} }
send = (data: PasswordStage): Promise<PasswordStage> => { send = (data: PasswordStage): Promise<PasswordStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesPasswordUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesPasswordUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -46,7 +41,7 @@ export class PasswordStageForm extends Form<PasswordStage> {
}; };
isBackendSelected(field: PasswordStageBackendsEnum): boolean { isBackendSelected(field: PasswordStageBackendsEnum): boolean {
return (this.stage?.backends || []).filter(isField => { return (this.instance?.backends || []).filter(isField => {
return field === isField; return field === isField;
}).length > 0; }).length > 0;
} }
@ -60,7 +55,7 @@ export class PasswordStageForm extends Form<PasswordStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -87,14 +82,14 @@ export class PasswordStageForm extends Form<PasswordStage> {
?required=${true} ?required=${true}
name="configureFlow"> name="configureFlow">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.stage?.configureFlow === undefined}>---------</option> <option value="" ?selected=${this.instance?.configureFlow === undefined}>---------</option>
${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ ${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
ordering: "pk", ordering: "pk",
designation: FlowDesignationEnum.StageConfiguration, designation: FlowDesignationEnum.StageConfiguration,
}).then(flows => { }).then(flows => {
return flows.results.map(flow => { return flows.results.map(flow => {
let selected = this.stage?.configureFlow === flow.pk; let selected = this.instance?.configureFlow === flow.pk;
if (!this.stage?.pk && !this.stage?.configureFlow && flow.slug === "default-password-change") { if (!this.instance?.pk && !this.instance?.configureFlow && flow.slug === "default-password-change") {
selected = true; selected = true;
} }
return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`; return html`<option value=${ifDefined(flow.pk)} ?selected=${selected}>${flow.name} (${flow.slug})</option>`;
@ -107,7 +102,7 @@ export class PasswordStageForm extends Form<PasswordStage> {
label=${t`Failed attempts before cancel`} label=${t`Failed attempts before cancel`}
?required=${true} ?required=${true}
name="failedAttemptsBeforeCancel"> name="failedAttemptsBeforeCancel">
<input type="number" value="${first(this.stage?.failedAttemptsBeforeCancel, 5)}" class="pf-c-form-control" required> <input type="number" value="${first(this.instance?.failedAttemptsBeforeCancel, 5)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage.`}</p> <p class="pf-c-form__helper-text">${t`How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</div> </div>

View File

@ -1,21 +1,24 @@
import { Prompt, PromptTypeEnum, StagesApi } from "authentik-api"; import { Prompt, PromptTypeEnum, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-prompt-form") @customElement("ak-prompt-form")
export class PromptForm extends Form<Prompt> { export class PromptForm extends ModelForm<Prompt, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<Prompt> {
prompt?: Prompt; return new StagesApi(DEFAULT_CONFIG).stagesPromptPromptsRead({
promptUuid: pk
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.prompt) { if (this.instance) {
return t`Successfully updated prompt.`; return t`Successfully updated prompt.`;
} else { } else {
return t`Successfully created prompt.`; return t`Successfully created prompt.`;
@ -23,9 +26,9 @@ export class PromptForm extends Form<Prompt> {
} }
send = (data: Prompt): Promise<Prompt> => { send = (data: Prompt): Promise<Prompt> => {
if (this.prompt) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesPromptPromptsUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesPromptPromptsUpdate({
promptUuid: this.prompt.pk || "", promptUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -37,37 +40,37 @@ export class PromptForm extends Form<Prompt> {
renderTypes(): TemplateResult { renderTypes(): TemplateResult {
return html` return html`
<option value=${PromptTypeEnum.Text} ?selected=${this.prompt?.type === PromptTypeEnum.Text}> <option value=${PromptTypeEnum.Text} ?selected=${this.instance?.type === PromptTypeEnum.Text}>
${t`Text: Simple Text input`} ${t`Text: Simple Text input`}
</option> </option>
<option value=${PromptTypeEnum.Username} ?selected=${this.prompt?.type === PromptTypeEnum.Username}> <option value=${PromptTypeEnum.Username} ?selected=${this.instance?.type === PromptTypeEnum.Username}>
${t`Username: Same as Text input, but checks for and prevents duplicate usernames.`} ${t`Username: Same as Text input, but checks for and prevents duplicate usernames.`}
</option> </option>
<option value=${PromptTypeEnum.Email} ?selected=${this.prompt?.type === PromptTypeEnum.Email}> <option value=${PromptTypeEnum.Email} ?selected=${this.instance?.type === PromptTypeEnum.Email}>
${t`Email: Text field with Email type.`} ${t`Email: Text field with Email type.`}
</option> </option>
<option value=${PromptTypeEnum.Password} ?selected=${this.prompt?.type === PromptTypeEnum.Password}> <option value=${PromptTypeEnum.Password} ?selected=${this.instance?.type === PromptTypeEnum.Password}>
${t`Password: Masked input, password is validated against sources. Policies still have to be applied to this Stage. If two of these are used in the same stage, they are ensured to be identical.`} ${t`Password: Masked input, password is validated against sources. Policies still have to be applied to this Stage. If two of these are used in the same stage, they are ensured to be identical.`}
</option> </option>
<option value=${PromptTypeEnum.Number} ?selected=${this.prompt?.type === PromptTypeEnum.Number}> <option value=${PromptTypeEnum.Number} ?selected=${this.instance?.type === PromptTypeEnum.Number}>
${t`Number`} ${t`Number`}
</option> </option>
<option value=${PromptTypeEnum.Checkbox} ?selected=${this.prompt?.type === PromptTypeEnum.Checkbox}> <option value=${PromptTypeEnum.Checkbox} ?selected=${this.instance?.type === PromptTypeEnum.Checkbox}>
${t`Checkbox`} ${t`Checkbox`}
</option> </option>
<option value=${PromptTypeEnum.Date} ?selected=${this.prompt?.type === PromptTypeEnum.Date}> <option value=${PromptTypeEnum.Date} ?selected=${this.instance?.type === PromptTypeEnum.Date}>
${t`Date`} ${t`Date`}
</option> </option>
<option value=${PromptTypeEnum.DateTime} ?selected=${this.prompt?.type === PromptTypeEnum.DateTime}> <option value=${PromptTypeEnum.DateTime} ?selected=${this.instance?.type === PromptTypeEnum.DateTime}>
${t`Date Time`} ${t`Date Time`}
</option> </option>
<option value=${PromptTypeEnum.Separator} ?selected=${this.prompt?.type === PromptTypeEnum.Separator}> <option value=${PromptTypeEnum.Separator} ?selected=${this.instance?.type === PromptTypeEnum.Separator}>
${t`Separator: Static Separator Line`} ${t`Separator: Static Separator Line`}
</option> </option>
<option value=${PromptTypeEnum.Hidden} ?selected=${this.prompt?.type === PromptTypeEnum.Hidden}> <option value=${PromptTypeEnum.Hidden} ?selected=${this.instance?.type === PromptTypeEnum.Hidden}>
${t`Hidden: Hidden field, can be used to insert data into form.`} ${t`Hidden: Hidden field, can be used to insert data into form.`}
</option> </option>
<option value=${PromptTypeEnum.Static} ?selected=${this.prompt?.type === PromptTypeEnum.Static}> <option value=${PromptTypeEnum.Static} ?selected=${this.instance?.type === PromptTypeEnum.Static}>
${t`Static: Static value, displayed as-is.`} ${t`Static: Static value, displayed as-is.`}
</option> </option>
`; `;
@ -79,14 +82,14 @@ export class PromptForm extends Form<Prompt> {
label=${t`Field Key`} label=${t`Field Key`}
?required=${true} ?required=${true}
name="fieldKey"> name="fieldKey">
<input type="text" value="${ifDefined(this.prompt?.fieldKey)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.fieldKey)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Name of the form field, also used to store the value.`}</p> <p class="pf-c-form__helper-text">${t`Name of the form field, also used to store the value.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Label`} label=${t`Label`}
?required=${true} ?required=${true}
name="label"> name="label">
<input type="text" value="${ifDefined(this.prompt?.label)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.label)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Label shown next to/above the prompt.`}</p> <p class="pf-c-form__helper-text">${t`Label shown next to/above the prompt.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
@ -99,7 +102,7 @@ export class PromptForm extends Form<Prompt> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="required"> <ak-form-element-horizontal name="required">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.prompt?.required, false)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.required, false)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Required`} ${t`Required`}
</label> </label>
@ -108,14 +111,14 @@ export class PromptForm extends Form<Prompt> {
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Placeholder`} label=${t`Placeholder`}
name="placeholder"> name="placeholder">
<input type="text" value="${ifDefined(this.prompt?.placeholder)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.placeholder)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Optionally pre-fill the input value`}</p> <p class="pf-c-form__helper-text">${t`Optionally pre-fill the input value`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Order`} label=${t`Order`}
?required=${true} ?required=${true}
name="order"> name="order">
<input type="number" value="${ifDefined(this.prompt?.order)}" class="pf-c-form-control" required> <input type="number" value="${ifDefined(this.instance?.order)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -68,7 +68,7 @@ export class PromptListPage extends TablePage<Prompt> {
<span slot="header"> <span slot="header">
${t`Update Prompt`} ${t`Update Prompt`}
</span> </span>
<ak-prompt-form slot="form" .prompt=${item}> <ak-prompt-form slot="form" .instancePk=${item.pk}>
</ak-prompt-form> </ak-prompt-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -1,32 +1,27 @@
import { PoliciesApi, PromptStage, StagesApi } from "authentik-api"; import { PoliciesApi, PromptStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import "../../../elements/forms/ModalForm"; import "../../../elements/forms/ModalForm";
import "./PromptForm"; import "./PromptForm";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-prompt-form") @customElement("ak-stage-prompt-form")
export class PromptStageForm extends Form<PromptStage> { export class PromptStageForm extends ModelForm<PromptStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<PromptStage> {
new StagesApi(DEFAULT_CONFIG).stagesPromptStagesRead({ return new StagesApi(DEFAULT_CONFIG).stagesPromptStagesRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: PromptStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -34,9 +29,9 @@ export class PromptStageForm extends Form<PromptStage> {
} }
send = (data: PromptStage): Promise<PromptStage> => { send = (data: PromptStage): Promise<PromptStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesPromptStagesUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesPromptStagesUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -55,7 +50,7 @@ export class PromptStageForm extends Form<PromptStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -71,7 +66,7 @@ export class PromptStageForm extends Form<PromptStage> {
ordering: "field_name" ordering: "field_name"
}).then(prompts => { }).then(prompts => {
return prompts.results.map(prompt => { return prompts.results.map(prompt => {
const selected = Array.from(this.stage?.fields || []).some(su => { const selected = Array.from(this.instance?.fields || []).some(su => {
return su == prompt.pk; return su == prompt.pk;
}); });
return html`<option value=${ifDefined(prompt.pk)} ?selected=${selected}> return html`<option value=${ifDefined(prompt.pk)} ?selected=${selected}>
@ -103,7 +98,7 @@ export class PromptStageForm extends Form<PromptStage> {
ordering: "name" ordering: "name"
}).then(policies => { }).then(policies => {
return policies.results.map(policy => { return policies.results.map(policy => {
const selected = Array.from(this.stage?.validationPolicies || []).some(su => { const selected = Array.from(this.instance?.validationPolicies || []).some(su => {
return su == policy.pk; return su == policy.pk;
}); });
return html`<option value=${ifDefined(policy.pk)} ?selected=${selected}> return html`<option value=${ifDefined(policy.pk)} ?selected=${selected}>

View File

@ -1,28 +1,23 @@
import { UserDeleteStage, StagesApi } from "authentik-api"; import { UserDeleteStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-user-delete-form") @customElement("ak-stage-user-delete-form")
export class UserDeleteStageForm extends Form<UserDeleteStage> { export class UserDeleteStageForm extends ModelForm<UserDeleteStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<UserDeleteStage> {
new StagesApi(DEFAULT_CONFIG).stagesUserDeleteRead({ return new StagesApi(DEFAULT_CONFIG).stagesUserDeleteRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: UserDeleteStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -30,9 +25,9 @@ export class UserDeleteStageForm extends Form<UserDeleteStage> {
} }
send = (data: UserDeleteStage): Promise<UserDeleteStage> => { send = (data: UserDeleteStage): Promise<UserDeleteStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesUserDeleteUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesUserDeleteUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -52,7 +47,7 @@ export class UserDeleteStageForm extends Form<UserDeleteStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,29 +1,24 @@
import { UserLoginStage, StagesApi } from "authentik-api"; import { UserLoginStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import "../../../elements/forms/FormGroup"; import "../../../elements/forms/FormGroup";
import { first } from "../../../utils"; import { first } from "../../../utils";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-user-login-form") @customElement("ak-stage-user-login-form")
export class UserLoginStageForm extends Form<UserLoginStage> { export class UserLoginStageForm extends ModelForm<UserLoginStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<UserLoginStage> {
new StagesApi(DEFAULT_CONFIG).stagesUserLoginRead({ return new StagesApi(DEFAULT_CONFIG).stagesUserLoginRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: UserLoginStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -31,9 +26,9 @@ export class UserLoginStageForm extends Form<UserLoginStage> {
} }
send = (data: UserLoginStage): Promise<UserLoginStage> => { send = (data: UserLoginStage): Promise<UserLoginStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesUserLoginUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesUserLoginUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -52,7 +47,7 @@ export class UserLoginStageForm extends Form<UserLoginStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${first(this.stage?.name, "")}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.name, "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
@ -63,7 +58,7 @@ export class UserLoginStageForm extends Form<UserLoginStage> {
label=${t`Session duration`} label=${t`Session duration`}
?required=${true} ?required=${true}
name="sessionDuration"> name="sessionDuration">
<input type="text" value="${first(this.stage?.sessionDuration, "seconds=0")}" class="pf-c-form-control" required> <input type="text" value="${first(this.instance?.sessionDuration, "seconds=0")}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Determines how long a session lasts. Default of 0 seconds means that the sessions lasts until the browser is closed.`}</p> <p class="pf-c-form__helper-text">${t`Determines how long a session lasts. Default of 0 seconds means that the sessions lasts until the browser is closed.`}</p>
<p class="pf-c-form__helper-text">${t`(Format: hours=-1;minutes=-2;seconds=-3).`}</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>

View File

@ -1,28 +1,23 @@
import { UserLogoutStage, StagesApi } from "authentik-api"; import { UserLogoutStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-user-logout-form") @customElement("ak-stage-user-logout-form")
export class UserLogoutStageForm extends Form<UserLogoutStage> { export class UserLogoutStageForm extends ModelForm<UserLogoutStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<UserLogoutStage> {
new StagesApi(DEFAULT_CONFIG).stagesUserLogoutRead({ return new StagesApi(DEFAULT_CONFIG).stagesUserLogoutRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: UserLogoutStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -30,9 +25,9 @@ export class UserLogoutStageForm extends Form<UserLogoutStage> {
} }
send = (data: UserLogoutStage): Promise<UserLogoutStage> => { send = (data: UserLogoutStage): Promise<UserLogoutStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesUserLogoutUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesUserLogoutUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -51,7 +46,7 @@ export class UserLogoutStageForm extends Form<UserLogoutStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,28 +1,23 @@
import { UserWriteStage, StagesApi } from "authentik-api"; import { UserWriteStage, StagesApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-stage-user-write-form") @customElement("ak-stage-user-write-form")
export class UserWriteStageForm extends Form<UserWriteStage> { export class UserWriteStageForm extends ModelForm<UserWriteStage, string> {
set stageUUID(value: string) { loadInstance(pk: string): Promise<UserWriteStage> {
new StagesApi(DEFAULT_CONFIG).stagesUserWriteRead({ return new StagesApi(DEFAULT_CONFIG).stagesUserWriteRead({
stageUuid: value, stageUuid: pk,
}).then(stage => {
this.stage = stage;
}); });
} }
@property({attribute: false})
stage?: UserWriteStage;
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.stage) { if (this.instance) {
return t`Successfully updated stage.`; return t`Successfully updated stage.`;
} else { } else {
return t`Successfully created stage.`; return t`Successfully created stage.`;
@ -30,9 +25,9 @@ export class UserWriteStageForm extends Form<UserWriteStage> {
} }
send = (data: UserWriteStage): Promise<UserWriteStage> => { send = (data: UserWriteStage): Promise<UserWriteStage> => {
if (this.stage) { if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesUserWriteUpdate({ return new StagesApi(DEFAULT_CONFIG).stagesUserWriteUpdate({
stageUuid: this.stage.pk || "", stageUuid: this.instance.pk || "",
data: data data: data
}); });
} else { } else {
@ -52,7 +47,7 @@ export class UserWriteStageForm extends Form<UserWriteStage> {
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.stage?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name || "")}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,20 +1,23 @@
import { CoreApi, Token } from "authentik-api"; import { CoreApi, Token } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
import { Form } from "../../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../../elements/forms/HorizontalFormElement"; import "../../../elements/forms/HorizontalFormElement";
import { ModelForm } from "../../../elements/forms/ModelForm";
@customElement("ak-user-token-form") @customElement("ak-user-token-form")
export class UserTokenForm extends Form<Token> { export class UserTokenForm extends ModelForm<Token, string> {
@property({attribute: false}) loadInstance(pk: string): Promise<Token> {
token?: Token; return new CoreApi(DEFAULT_CONFIG).coreTokensRead({
identifier: pk
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.token) { if (this.instance) {
return t`Successfully updated token.`; return t`Successfully updated token.`;
} else { } else {
return t`Successfully created token.`; return t`Successfully created token.`;
@ -22,9 +25,9 @@ export class UserTokenForm extends Form<Token> {
} }
send = (data: Token): Promise<Token> => { send = (data: Token): Promise<Token> => {
if (this.token) { if (this.instance) {
return new CoreApi(DEFAULT_CONFIG).coreTokensUpdate({ return new CoreApi(DEFAULT_CONFIG).coreTokensUpdate({
identifier: this.token.identifier, identifier: this.instance.identifier,
data: data data: data
}); });
} else { } else {
@ -40,13 +43,13 @@ export class UserTokenForm extends Form<Token> {
label=${t`Identifier`} label=${t`Identifier`}
?required=${true} ?required=${true}
name="identifier"> name="identifier">
<input type="text" value="${ifDefined(this.token?.identifier)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.identifier)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Description`} label=${t`Description`}
?required=${true} ?required=${true}
name="description"> name="description">
<input type="text" value="${ifDefined(this.token?.description)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.description)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -110,7 +110,7 @@ export class UserTokenList extends Table<Token> {
<span slot="header"> <span slot="header">
${t`Update Token`} ${t`Update Token`}
</span> </span>
<ak-user-token-form slot="form" .token=${item}> <ak-user-token-form slot="form" .instancePk=${item.identifier}>
</ak-user-token-form> </ak-user-token-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${t`Edit`} ${t`Edit`}

View File

@ -1,23 +1,26 @@
import { CoreApi, User } from "authentik-api"; import { CoreApi, User } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement"; import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror"; import "../../elements/CodeMirror";
import YAML from "yaml"; import YAML from "yaml";
import { first } from "../../utils"; import { first } from "../../utils";
import { ModelForm } from "../../elements/forms/ModelForm";
@customElement("ak-user-form") @customElement("ak-user-form")
export class UserForm extends Form<User> { export class UserForm extends ModelForm<User, number> {
@property({ attribute: false }) loadInstance(pk: number): Promise<User> {
user?: User; return new CoreApi(DEFAULT_CONFIG).coreUsersRead({
id: pk
});
}
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.user) { if (this.instance) {
return t`Successfully updated user.`; return t`Successfully updated user.`;
} else { } else {
return t`Successfully created user.`; return t`Successfully created user.`;
@ -25,9 +28,9 @@ export class UserForm extends Form<User> {
} }
send = (data: User): Promise<User> => { send = (data: User): Promise<User> => {
if (this.user) { if (this.instance) {
return new CoreApi(DEFAULT_CONFIG).coreUsersUpdate({ return new CoreApi(DEFAULT_CONFIG).coreUsersUpdate({
id: this.user.pk || 0, id: this.instance.pk || 0,
data: data data: data
}); });
} else { } else {
@ -43,26 +46,26 @@ export class UserForm extends Form<User> {
label=${t`Username`} label=${t`Username`}
?required=${true} ?required=${true}
name="username"> name="username">
<input type="text" value="${ifDefined(this.user?.username)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.username)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.`}</p> <p class="pf-c-form__helper-text">${t`Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Name`} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.user?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.instance?.name)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${t`User's display name.`}</p> <p class="pf-c-form__helper-text">${t`User's display name.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${t`Email`} label=${t`Email`}
?required=${true} ?required=${true}
name="email"> name="email">
<input type="email" autocomplete="off" value="${ifDefined(this.user?.email)}" class="pf-c-form-control" required> <input type="email" autocomplete="off" value="${ifDefined(this.instance?.email)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
name="isActive"> name="isActive">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.user?.isActive, true)}> <input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.isActive, true)}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${t`Is active`} ${t`Is active`}
</label> </label>
@ -73,7 +76,7 @@ export class UserForm extends Form<User> {
label=${t`Attributes`} label=${t`Attributes`}
?required=${true} ?required=${true}
name="attributes"> name="attributes">
<ak-codemirror mode="yaml" value="${YAML.stringify(first(this.user?.attributes, {}))}"> <ak-codemirror mode="yaml" value="${YAML.stringify(first(this.instance?.attributes, {}))}">
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p> <p class="pf-c-form__helper-text">${t`Set custom attributes using YAML or JSON.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -75,7 +75,7 @@ export class UserListPage extends TablePage<User> {
<span slot="header"> <span slot="header">
${t`Update User`} ${t`Update User`}
</span> </span>
<ak-user-form slot="form" .user=${item}> <ak-user-form slot="form" .instancePk=${item.pk}>
</ak-user-form> </ak-user-form>
<button slot="trigger" class="pf-m-secondary pf-c-button"> <button slot="trigger" class="pf-m-secondary pf-c-button">
${t`Edit`} ${t`Edit`}

View File

@ -144,7 +144,7 @@ export class UserViewPage extends LitElement {
<span slot="header"> <span slot="header">
${t`Update User`} ${t`Update User`}
</span> </span>
<ak-user-form slot="form" .user=${this.user}> <ak-user-form slot="form" .instancePk=${this.user.pk}>
</ak-user-form> </ak-user-form>
<button slot="trigger" class="pf-m-primary pf-c-button"> <button slot="trigger" class="pf-m-primary pf-c-button">
${t`Edit`} ${t`Edit`}