web/user: fix user source settings not updating correctly after deletion

also optimise the amount of API requests sent

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3411
This commit is contained in:
Jens Langhammer 2022-08-16 11:43:13 +02:00
parent d7e8ca1c8f
commit 54eeb7add6
3 changed files with 112 additions and 80 deletions

View File

@ -15,13 +15,16 @@ import AKGlobal from "@goauthentik/web/authentik.css";
import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css";
import PFDataList from "@patternfly/patternfly/components/DataList/data-list.css"; import PFDataList from "@patternfly/patternfly/components/DataList/data-list.css";
import { SourcesApi, UserSetting } from "@goauthentik/api"; import { PaginatedUserSourceConnectionList, SourcesApi, UserSetting } from "@goauthentik/api";
@customElement("ak-user-settings-source") @customElement("ak-user-settings-source")
export class UserSourceSettingsPage extends LitElement { export class UserSourceSettingsPage extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
sourceSettings?: Promise<UserSetting[]>; sourceSettings?: Promise<UserSetting[]>;
@property({ attribute: false })
connections?: PaginatedUserSourceConnectionList;
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [ return [
PFDataList, PFDataList,
@ -55,15 +58,30 @@ export class UserSourceSettingsPage extends LitElement {
firstUpdated(): void { firstUpdated(): void {
this.sourceSettings = new SourcesApi(DEFAULT_CONFIG).sourcesAllUserSettingsList(); this.sourceSettings = new SourcesApi(DEFAULT_CONFIG).sourcesAllUserSettingsList();
new SourcesApi(DEFAULT_CONFIG).sourcesUserConnectionsAllList().then((connections) => {
this.connections = connections;
});
} }
renderSourceSettings(source: UserSetting): TemplateResult { renderSourceSettings(source: UserSetting): TemplateResult {
let connectionPk = -1;
if (this.connections) {
const connections = this.connections.results.filter(
(con) => con.source.slug === source.objectUid,
);
if (connections.length > 0) {
connectionPk = connections[0].pk;
} else {
connectionPk = 0;
}
}
switch (source.component) { switch (source.component) {
case "ak-user-settings-source-oauth": case "ak-user-settings-source-oauth":
return html`<ak-user-settings-source-oauth return html`<ak-user-settings-source-oauth
class="pf-c-data-list__item-row" class="pf-c-data-list__item-row"
objectId=${source.objectUid} objectId=${source.objectUid}
title=${source.title} title=${source.title}
connectionPk=${connectionPk}
.configureUrl=${source.configureUrl} .configureUrl=${source.configureUrl}
> >
</ak-user-settings-source-oauth>`; </ak-user-settings-source-oauth>`;
@ -72,6 +90,7 @@ export class UserSourceSettingsPage extends LitElement {
class="pf-c-data-list__item-row" class="pf-c-data-list__item-row"
objectId=${source.objectUid} objectId=${source.objectUid}
title=${source.title} title=${source.title}
connectionPk=${connectionPk}
.configureUrl=${source.configureUrl} .configureUrl=${source.configureUrl}
> >
</ak-user-settings-source-plex>`; </ak-user-settings-source-plex>`;

View File

@ -1,4 +1,6 @@
import { AndNext, DEFAULT_CONFIG } from "@goauthentik/web/api/Config"; import { AndNext, DEFAULT_CONFIG } from "@goauthentik/web/api/Config";
import { EVENT_REFRESH } from "@goauthentik/web/constants";
import "@goauthentik/web/elements/Spinner";
import { MessageLevel } from "@goauthentik/web/elements/messages/Message"; import { MessageLevel } from "@goauthentik/web/elements/messages/Message";
import { showMessage } from "@goauthentik/web/elements/messages/MessageContainer"; import { showMessage } from "@goauthentik/web/elements/messages/MessageContainer";
import { BaseUserSettings } from "@goauthentik/web/user/user-settings/BaseUserSettings"; import { BaseUserSettings } from "@goauthentik/web/user/user-settings/BaseUserSettings";
@ -8,7 +10,6 @@ import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js"; import { ifDefined } from "lit/directives/if-defined.js";
import { until } from "lit/directives/until.js";
import { SourcesApi } from "@goauthentik/api"; import { SourcesApi } from "@goauthentik/api";
@ -17,47 +18,53 @@ export class SourceSettingsOAuth extends BaseUserSettings {
@property() @property()
title!: string; title!: string;
@property({ type: Number })
connectionPk = 0;
render(): TemplateResult { render(): TemplateResult {
return html`${until( if (this.connectionPk === -1) {
new SourcesApi(DEFAULT_CONFIG) return html`<ak-spinner></ak-spinner>`;
.sourcesUserConnectionsOauthList({ }
sourceSlug: this.objectId, if (this.connectionPk > 0) {
}) return html`<button
.then((connection) => { class="pf-c-button pf-m-danger"
if (connection.results.length > 0) { @click=${() => {
return html` <button return new SourcesApi(DEFAULT_CONFIG)
class="pf-c-button pf-m-danger" .sourcesUserConnectionsOauthDestroy({
@click=${() => { id: this.connectionPk,
return new SourcesApi(DEFAULT_CONFIG) })
.sourcesUserConnectionsOauthDestroy({ .then(() => {
id: connection.results[0].pk || 0, showMessage({
}) level: MessageLevel.info,
.then(() => { message: t`Successfully disconnected source`,
showMessage({ });
level: MessageLevel.info, })
message: t`Successfully disconnected source`, .catch((exc) => {
}); showMessage({
}) level: MessageLevel.error,
.catch((exc) => { message: t`Failed to disconnected source: ${exc}`,
showMessage({ });
level: MessageLevel.error, })
message: t`Failed to disconnected source: ${exc}`, .finally(() => {
}); this.parentElement?.dispatchEvent(
}); new CustomEvent(EVENT_REFRESH, {
}} bubbles: true,
> composed: true,
${t`Disconnect`} }),
</button>`; );
} });
return html` <a }}
class="pf-c-button pf-m-primary" >
href="${ifDefined(this.configureUrl)}${AndNext( ${t`Disconnect`}
`/if/user/#/settings;${JSON.stringify({ page: "page-sources" })}`, </button>`;
)}" }
> return html`<a
${t`Connect`} class="pf-c-button pf-m-primary"
</a>`; href="${ifDefined(this.configureUrl)}${AndNext(
}), `/if/user/#/settings;${JSON.stringify({ page: "page-sources" })}`,
)}`; )}"
>
${t`Connect`}
</a>`;
} }
} }

View File

@ -1,6 +1,7 @@
import { DEFAULT_CONFIG } from "@goauthentik/web/api/Config"; import { DEFAULT_CONFIG } from "@goauthentik/web/api/Config";
import { PlexAPIClient, popupCenterScreen } from "@goauthentik/web/api/Plex"; import { PlexAPIClient, popupCenterScreen } from "@goauthentik/web/api/Plex";
import { EVENT_REFRESH } from "@goauthentik/web/constants"; import { EVENT_REFRESH } from "@goauthentik/web/constants";
import "@goauthentik/web/elements/Spinner";
import { MessageLevel } from "@goauthentik/web/elements/messages/Message"; import { MessageLevel } from "@goauthentik/web/elements/messages/Message";
import { showMessage } from "@goauthentik/web/elements/messages/MessageContainer"; import { showMessage } from "@goauthentik/web/elements/messages/MessageContainer";
import { BaseUserSettings } from "@goauthentik/web/user/user-settings/BaseUserSettings"; import { BaseUserSettings } from "@goauthentik/web/user/user-settings/BaseUserSettings";
@ -9,7 +10,6 @@ import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit"; import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
import { until } from "lit/directives/until.js";
import { SourcesApi } from "@goauthentik/api"; import { SourcesApi } from "@goauthentik/api";
@ -18,6 +18,9 @@ export class SourceSettingsPlex extends BaseUserSettings {
@property() @property()
title!: string; title!: string;
@property({ type: Number })
connectionPk = 0;
async doPlex(): Promise<void> { async doPlex(): Promise<void> {
const authInfo = await PlexAPIClient.getPin(this.configureUrl || ""); const authInfo = await PlexAPIClient.getPin(this.configureUrl || "");
const authWindow = popupCenterScreen(authInfo.authUrl, "plex auth", 550, 700); const authWindow = popupCenterScreen(authInfo.authUrl, "plex auth", 550, 700);
@ -39,41 +42,44 @@ export class SourceSettingsPlex extends BaseUserSettings {
} }
render(): TemplateResult { render(): TemplateResult {
return html`${until( if (this.connectionPk === -1) {
new SourcesApi(DEFAULT_CONFIG) return html`<ak-spinner></ak-spinner>`;
.sourcesUserConnectionsPlexList({ }
sourceSlug: this.objectId, if (this.connectionPk > 0) {
}) return html`<button
.then((connection) => { class="pf-c-button pf-m-danger"
if (connection.results.length > 0) { @click=${() => {
return html` <button return new SourcesApi(DEFAULT_CONFIG)
class="pf-c-button pf-m-danger" .sourcesUserConnectionsPlexDestroy({
@click=${() => { id: this.connectionPk,
return new SourcesApi(DEFAULT_CONFIG) })
.sourcesUserConnectionsPlexDestroy({ .then(() => {
id: connection.results[0].pk || 0, showMessage({
}) level: MessageLevel.info,
.then(() => { message: t`Successfully disconnected source`,
showMessage({ });
level: MessageLevel.info, })
message: t`Successfully disconnected source`, .catch((exc) => {
}); showMessage({
}) level: MessageLevel.error,
.catch((exc) => { message: t`Failed to disconnected source: ${exc}`,
showMessage({ });
level: MessageLevel.error, })
message: t`Failed to disconnected source: ${exc}`, .finally(() => {
}); this.parentElement?.dispatchEvent(
}); new CustomEvent(EVENT_REFRESH, {
}} bubbles: true,
> composed: true,
${t`Disconnect`} }),
</button>`; );
} });
return html` <button @click=${this.doPlex} class="pf-c-button pf-m-primary"> }}
${t`Connect`} >
</button>`; ${t`Disconnect`}
}), </button>`;
)}`; }
return html`<button @click=${this.doPlex} class="pf-c-button pf-m-primary">
${t`Connect`}
</button>`;
} }
} }