Merge branch 'main' into web/theme-controller-2
* main: sources/oauth: fix oidc well-known parsing (#7248) web/admin: improve user email button labels (#7233)
This commit is contained in:
commit
8713a1d120
|
@ -71,15 +71,12 @@ class OAuthSourceSerializer(SourceSerializer):
|
||||||
text = exc.response.text if exc.response else str(exc)
|
text = exc.response.text if exc.response else str(exc)
|
||||||
raise ValidationError({"oidc_well_known_url": text})
|
raise ValidationError({"oidc_well_known_url": text})
|
||||||
config = well_known_config.json()
|
config = well_known_config.json()
|
||||||
try:
|
if "issuer" not in config:
|
||||||
attrs["authorization_url"] = config["authorization_endpoint"]
|
raise ValidationError({"oidc_well_known_url": "Invalid well-known configuration"})
|
||||||
attrs["access_token_url"] = config["token_endpoint"]
|
attrs["authorization_url"] = config.get("authorization_endpoint", "")
|
||||||
attrs["profile_url"] = config["userinfo_endpoint"]
|
attrs["access_token_url"] = config.get("token_endpoint", "")
|
||||||
inferred_oidc_jwks_url = config["jwks_uri"]
|
attrs["profile_url"] = config.get("userinfo_endpoint", "")
|
||||||
except (IndexError, KeyError) as exc:
|
inferred_oidc_jwks_url = config.get("jwks_uri", "")
|
||||||
raise ValidationError(
|
|
||||||
{"oidc_well_known_url": f"Invalid well-known configuration: {exc}"}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Prefer user-entered URL to inferred URL to default URL
|
# Prefer user-entered URL to inferred URL to default URL
|
||||||
jwks_url = attrs.get("oidc_jwks_url") or inferred_oidc_jwks_url or source_type.oidc_jwks_url
|
jwks_url = attrs.get("oidc_jwks_url") or inferred_oidc_jwks_url or source_type.oidc_jwks_url
|
||||||
|
|
|
@ -38,7 +38,7 @@ def update_well_known_jwks(self: MonitoredTask):
|
||||||
for source_attr, config_key in source_attr_key:
|
for source_attr, config_key in source_attr_key:
|
||||||
# Check if we're actually changing anything to only
|
# Check if we're actually changing anything to only
|
||||||
# save when something has changed
|
# save when something has changed
|
||||||
if getattr(source, source_attr) != config[config_key]:
|
if getattr(source, source_attr, "") != config[config_key]:
|
||||||
dirty = True
|
dirty = True
|
||||||
setattr(source, source_attr, config[config_key])
|
setattr(source, source_attr, config[config_key])
|
||||||
except (IndexError, KeyError) as exc:
|
except (IndexError, KeyError) as exc:
|
||||||
|
|
|
@ -50,6 +50,7 @@ class TestOAuthSource(TestCase):
|
||||||
def test_api_validate_openid_connect(self):
|
def test_api_validate_openid_connect(self):
|
||||||
"""Test API validation (with OIDC endpoints)"""
|
"""Test API validation (with OIDC endpoints)"""
|
||||||
openid_config = {
|
openid_config = {
|
||||||
|
"issuer": "foo",
|
||||||
"authorization_endpoint": "http://mock/oauth/authorize",
|
"authorization_endpoint": "http://mock/oauth/authorize",
|
||||||
"token_endpoint": "http://mock/oauth/token",
|
"token_endpoint": "http://mock/oauth/token",
|
||||||
"userinfo_endpoint": "http://mock/oauth/userinfo",
|
"userinfo_endpoint": "http://mock/oauth/userinfo",
|
||||||
|
|
|
@ -21,10 +21,11 @@ import { getURLParam, updateURLParams } from "@goauthentik/elements/router/Route
|
||||||
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
||||||
import { TableColumn } from "@goauthentik/elements/table/Table";
|
import { TableColumn } from "@goauthentik/elements/table/Table";
|
||||||
import { TablePage } from "@goauthentik/elements/table/TablePage";
|
import { TablePage } from "@goauthentik/elements/table/TablePage";
|
||||||
|
import { writeToClipboard } from "@goauthentik/elements/utils/writeToClipboard";
|
||||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||||
|
|
||||||
import { msg, str } from "@lit/localize";
|
import { msg, str } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, html } from "lit";
|
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
|
||||||
import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
|
import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
|
||||||
|
@ -40,6 +41,56 @@ import {
|
||||||
UserPath,
|
UserPath,
|
||||||
} from "@goauthentik/api";
|
} from "@goauthentik/api";
|
||||||
|
|
||||||
|
export const requestRecoveryLink = (user: User) =>
|
||||||
|
new CoreApi(DEFAULT_CONFIG)
|
||||||
|
.coreUsersRecoveryRetrieve({
|
||||||
|
id: user.pk,
|
||||||
|
})
|
||||||
|
.then((rec) =>
|
||||||
|
writeToClipboard(rec.link).then((wroteToClipboard) =>
|
||||||
|
showMessage({
|
||||||
|
level: MessageLevel.success,
|
||||||
|
message: rec.link,
|
||||||
|
description: wroteToClipboard
|
||||||
|
? msg("A copy of this recovery link has been placed in your clipboard")
|
||||||
|
: "",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.catch((ex: ResponseError) =>
|
||||||
|
ex.response.json().then(() =>
|
||||||
|
showMessage({
|
||||||
|
level: MessageLevel.error,
|
||||||
|
message: msg(
|
||||||
|
"The current tenant must have a recovery flow configured to use a recovery link",
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const renderRecoveryEmailRequest = (user: User) =>
|
||||||
|
html`<ak-forms-modal .closeAfterSuccessfulSubmit=${false} id="ak-email-recovery-request">
|
||||||
|
<span slot="submit"> ${msg("Send link")} </span>
|
||||||
|
<span slot="header"> ${msg("Send recovery link to user")} </span>
|
||||||
|
<ak-user-reset-email-form slot="form" .user=${user}> </ak-user-reset-email-form>
|
||||||
|
<button slot="trigger" class="pf-c-button pf-m-secondary">
|
||||||
|
${msg("Email recovery link")}
|
||||||
|
</button>
|
||||||
|
</ak-forms-modal>`;
|
||||||
|
|
||||||
|
const recoveryButtonStyles = css`
|
||||||
|
#recovery-request-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.375rem;
|
||||||
|
}
|
||||||
|
#recovery-request-buttons > *,
|
||||||
|
#update-password-request .pf-c-button {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
@customElement("ak-user-list")
|
@customElement("ak-user-list")
|
||||||
export class UserListPage extends TablePage<User> {
|
export class UserListPage extends TablePage<User> {
|
||||||
expandable = true;
|
expandable = true;
|
||||||
|
@ -74,7 +125,7 @@ export class UserListPage extends TablePage<User> {
|
||||||
me?: SessionUser;
|
me?: SessionUser;
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return super.styles.concat(PFDescriptionList, PFCard, PFAlert);
|
return [...super.styles, PFDescriptionList, PFCard, PFAlert, recoveryButtonStyles];
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -287,8 +338,14 @@ export class UserListPage extends TablePage<User> {
|
||||||
<span class="pf-c-description-list__text">${msg("Recovery")}</span>
|
<span class="pf-c-description-list__text">${msg("Recovery")}</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text">
|
<div
|
||||||
<ak-forms-modal size=${PFSize.Medium}>
|
class="pf-c-description-list__text"
|
||||||
|
id="recovery-request-buttons"
|
||||||
|
>
|
||||||
|
<ak-forms-modal
|
||||||
|
size=${PFSize.Medium}
|
||||||
|
id="update-password-request"
|
||||||
|
>
|
||||||
<span slot="submit">${msg("Update password")}</span>
|
<span slot="submit">${msg("Update password")}</span>
|
||||||
<span slot="header">${msg("Update password")}</span>
|
<span slot="header">${msg("Update password")}</span>
|
||||||
<ak-user-password-form
|
<ak-user-password-form
|
||||||
|
@ -303,56 +360,12 @@ export class UserListPage extends TablePage<User> {
|
||||||
? html`
|
? html`
|
||||||
<ak-action-button
|
<ak-action-button
|
||||||
class="pf-m-secondary"
|
class="pf-m-secondary"
|
||||||
.apiRequest=${() => {
|
.apiRequest=${() => requestRecoveryLink(item)}
|
||||||
return new CoreApi(DEFAULT_CONFIG)
|
|
||||||
.coreUsersRecoveryRetrieve({
|
|
||||||
id: item.pk,
|
|
||||||
})
|
|
||||||
.then((rec) => {
|
|
||||||
showMessage({
|
|
||||||
level: MessageLevel.success,
|
|
||||||
message: msg(
|
|
||||||
"Successfully generated recovery link",
|
|
||||||
),
|
|
||||||
description: rec.link,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((ex: ResponseError) => {
|
|
||||||
ex.response.json().then(() => {
|
|
||||||
showMessage({
|
|
||||||
level: MessageLevel.error,
|
|
||||||
message: msg(
|
|
||||||
"No recovery flow is configured.",
|
|
||||||
),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
${msg("Copy recovery link")}
|
${msg("Create recovery link")}
|
||||||
</ak-action-button>
|
</ak-action-button>
|
||||||
${item.email
|
${item.email
|
||||||
? html`<ak-forms-modal
|
? renderRecoveryEmailRequest(item)
|
||||||
.closeAfterSuccessfulSubmit=${false}
|
|
||||||
>
|
|
||||||
<span slot="submit">
|
|
||||||
${msg("Send link")}
|
|
||||||
</span>
|
|
||||||
<span slot="header">
|
|
||||||
${msg("Send recovery link to user")}
|
|
||||||
</span>
|
|
||||||
<ak-user-reset-email-form
|
|
||||||
slot="form"
|
|
||||||
.user=${item}
|
|
||||||
>
|
|
||||||
</ak-user-reset-email-form>
|
|
||||||
<button
|
|
||||||
slot="trigger"
|
|
||||||
class="pf-c-button pf-m-secondary"
|
|
||||||
>
|
|
||||||
${msg("Email recovery link")}
|
|
||||||
</button>
|
|
||||||
</ak-forms-modal>`
|
|
||||||
: html`<span
|
: html`<span
|
||||||
>${msg(
|
>${msg(
|
||||||
"Recovery link cannot be emailed, user has no email address saved.",
|
"Recovery link cannot be emailed, user has no email address saved.",
|
||||||
|
|
|
@ -5,11 +5,14 @@ import "@goauthentik/admin/users/UserForm";
|
||||||
import "@goauthentik/admin/users/UserPasswordForm";
|
import "@goauthentik/admin/users/UserPasswordForm";
|
||||||
import "@goauthentik/app/admin/users/UserAssignedGlobalPermissionsTable";
|
import "@goauthentik/app/admin/users/UserAssignedGlobalPermissionsTable";
|
||||||
import "@goauthentik/app/admin/users/UserAssignedObjectPermissionsTable";
|
import "@goauthentik/app/admin/users/UserAssignedObjectPermissionsTable";
|
||||||
|
import {
|
||||||
|
renderRecoveryEmailRequest,
|
||||||
|
requestRecoveryLink,
|
||||||
|
} from "@goauthentik/app/admin/users/UserListPage";
|
||||||
import { me } from "@goauthentik/app/common/users";
|
import { me } from "@goauthentik/app/common/users";
|
||||||
import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||||
import { MessageLevel } from "@goauthentik/common/messages";
|
|
||||||
import "@goauthentik/components/events/ObjectChangelog";
|
import "@goauthentik/components/events/ObjectChangelog";
|
||||||
import "@goauthentik/components/events/UserEvents";
|
import "@goauthentik/components/events/UserEvents";
|
||||||
import { AKElement, rootInterface } from "@goauthentik/elements/Base";
|
import { AKElement, rootInterface } from "@goauthentik/elements/Base";
|
||||||
|
@ -21,13 +24,12 @@ import "@goauthentik/elements/Tabs";
|
||||||
import "@goauthentik/elements/buttons/ActionButton";
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||||
import "@goauthentik/elements/forms/ModalForm";
|
import "@goauthentik/elements/forms/ModalForm";
|
||||||
import { showMessage } from "@goauthentik/elements/messages/MessageContainer";
|
|
||||||
import "@goauthentik/elements/oauth/UserRefreshList";
|
import "@goauthentik/elements/oauth/UserRefreshList";
|
||||||
import "@goauthentik/elements/user/SessionList";
|
import "@goauthentik/elements/user/SessionList";
|
||||||
import "@goauthentik/elements/user/UserConsentList";
|
import "@goauthentik/elements/user/UserConsentList";
|
||||||
|
|
||||||
import { msg, str } from "@lit/localize";
|
import { msg, str } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
import { css, html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
|
||||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||||
|
@ -72,7 +74,7 @@ export class UserViewPage extends AKElement {
|
||||||
@state()
|
@state()
|
||||||
me?: SessionUser;
|
me?: SessionUser;
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles() {
|
||||||
return [
|
return [
|
||||||
PFBase,
|
PFBase,
|
||||||
PFPage,
|
PFPage,
|
||||||
|
@ -84,12 +86,24 @@ export class UserViewPage extends AKElement {
|
||||||
PFDescriptionList,
|
PFDescriptionList,
|
||||||
PFSizing,
|
PFSizing,
|
||||||
css`
|
css`
|
||||||
.pf-c-description-list__description ak-action-button {
|
|
||||||
margin-right: 6px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
.ak-button-collection {
|
.ak-button-collection {
|
||||||
max-width: 12em;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.375rem;
|
||||||
|
max-width: 12rem;
|
||||||
|
}
|
||||||
|
.ak-button-collection > * {
|
||||||
|
flex: 1 0 100%;
|
||||||
|
}
|
||||||
|
#reset-password-button {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ak-email-recovery-request,
|
||||||
|
#update-password-request .pf-c-button,
|
||||||
|
#ak-email-recovery-request .pf-c-button {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
@ -103,7 +117,7 @@ export class UserViewPage extends AKElement {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): TemplateResult {
|
render() {
|
||||||
return html`<ak-page-header
|
return html`<ak-page-header
|
||||||
icon="pf-icon pf-icon-user"
|
icon="pf-icon pf-icon-user"
|
||||||
header=${msg(str`User ${this.user?.username || ""}`)}
|
header=${msg(str`User ${this.user?.username || ""}`)}
|
||||||
|
@ -113,13 +127,17 @@ export class UserViewPage extends AKElement {
|
||||||
${this.renderBody()}`;
|
${this.renderBody()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderUserCard(): TemplateResult {
|
renderUserCard() {
|
||||||
if (!this.user) {
|
if (!this.user) {
|
||||||
return html``;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const user = this.user;
|
||||||
|
|
||||||
const canImpersonate =
|
const canImpersonate =
|
||||||
rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanImpersonate) &&
|
rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanImpersonate) &&
|
||||||
this.user.pk !== this.me?.user.pk;
|
this.user.pk !== this.me?.user.pk;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="pf-c-card__title">${msg("User Info")}</div>
|
<div class="pf-c-card__title">${msg("User Info")}</div>
|
||||||
<div class="pf-c-card__body">
|
<div class="pf-c-card__body">
|
||||||
|
@ -129,7 +147,7 @@ export class UserViewPage extends AKElement {
|
||||||
<span class="pf-c-description-list__text">${msg("Username")}</span>
|
<span class="pf-c-description-list__text">${msg("Username")}</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text">${this.user.username}</div>
|
<div class="pf-c-description-list__text">${user.username}</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-c-description-list__group">
|
<div class="pf-c-description-list__group">
|
||||||
|
@ -137,7 +155,7 @@ export class UserViewPage extends AKElement {
|
||||||
<span class="pf-c-description-list__text">${msg("Name")}</span>
|
<span class="pf-c-description-list__text">${msg("Name")}</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text">${this.user.name}</div>
|
<div class="pf-c-description-list__text">${user.name}</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-c-description-list__group">
|
<div class="pf-c-description-list__group">
|
||||||
|
@ -145,7 +163,7 @@ export class UserViewPage extends AKElement {
|
||||||
<span class="pf-c-description-list__text">${msg("Email")}</span>
|
<span class="pf-c-description-list__text">${msg("Email")}</span>
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text">${this.user.email || "-"}</div>
|
<div class="pf-c-description-list__text">${user.email || "-"}</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="pf-c-description-list__group">
|
<div class="pf-c-description-list__group">
|
||||||
|
@ -154,7 +172,7 @@ export class UserViewPage extends AKElement {
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text">
|
<div class="pf-c-description-list__text">
|
||||||
${this.user.lastLogin?.toLocaleString()}
|
${user.lastLogin?.toLocaleString()}
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
@ -165,7 +183,7 @@ export class UserViewPage extends AKElement {
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text">
|
<div class="pf-c-description-list__text">
|
||||||
<ak-label
|
<ak-label
|
||||||
color=${this.user.isActive ? PFColor.Green : PFColor.Orange}
|
color=${user.isActive ? PFColor.Green : PFColor.Orange}
|
||||||
></ak-label>
|
></ak-label>
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -177,7 +195,7 @@ export class UserViewPage extends AKElement {
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text">
|
<div class="pf-c-description-list__text">
|
||||||
<ak-label
|
<ak-label
|
||||||
color=${this.user.isSuperuser ? PFColor.Green : PFColor.Orange}
|
color=${user.isSuperuser ? PFColor.Green : PFColor.Orange}
|
||||||
></ak-label>
|
></ak-label>
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -191,7 +209,7 @@ export class UserViewPage extends AKElement {
|
||||||
<ak-forms-modal>
|
<ak-forms-modal>
|
||||||
<span slot="submit"> ${msg("Update")} </span>
|
<span slot="submit"> ${msg("Update")} </span>
|
||||||
<span slot="header"> ${msg("Update User")} </span>
|
<span slot="header"> ${msg("Update User")} </span>
|
||||||
<ak-user-form slot="form" .instancePk=${this.user.pk}>
|
<ak-user-form slot="form" .instancePk=${user.pk}>
|
||||||
</ak-user-form>
|
</ak-user-form>
|
||||||
<button
|
<button
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
|
@ -201,13 +219,13 @@ export class UserViewPage extends AKElement {
|
||||||
</button>
|
</button>
|
||||||
</ak-forms-modal>
|
</ak-forms-modal>
|
||||||
<ak-user-active-form
|
<ak-user-active-form
|
||||||
.obj=${this.user}
|
.obj=${user}
|
||||||
objectLabel=${msg("User")}
|
objectLabel=${msg("User")}
|
||||||
.delete=${() => {
|
.delete=${() => {
|
||||||
return new CoreApi(DEFAULT_CONFIG).coreUsersPartialUpdate({
|
return new CoreApi(DEFAULT_CONFIG).coreUsersPartialUpdate({
|
||||||
id: this.user?.pk || 0,
|
id: user.pk,
|
||||||
patchedUserRequest: {
|
patchedUserRequest: {
|
||||||
isActive: !this.user?.isActive,
|
isActive: !user.isActive,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
@ -218,15 +236,13 @@ export class UserViewPage extends AKElement {
|
||||||
>
|
>
|
||||||
<pf-tooltip
|
<pf-tooltip
|
||||||
position="top"
|
position="top"
|
||||||
content=${this.user.isActive
|
content=${user.isActive
|
||||||
? msg("Lock the user out of this system")
|
? msg("Lock the user out of this system")
|
||||||
: msg(
|
: msg(
|
||||||
"Allow the user to log in and use this system",
|
"Allow the user to log in and use this system",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
${this.user.isActive
|
${user.isActive ? msg("Deactivate") : msg("Activate")}
|
||||||
? msg("Deactivate")
|
|
||||||
: msg("Activate")}
|
|
||||||
</pf-tooltip>
|
</pf-tooltip>
|
||||||
</button>
|
</button>
|
||||||
</ak-user-active-form>
|
</ak-user-active-form>
|
||||||
|
@ -238,7 +254,7 @@ export class UserViewPage extends AKElement {
|
||||||
.apiRequest=${() => {
|
.apiRequest=${() => {
|
||||||
return new CoreApi(DEFAULT_CONFIG)
|
return new CoreApi(DEFAULT_CONFIG)
|
||||||
.coreUsersImpersonateCreate({
|
.coreUsersImpersonateCreate({
|
||||||
id: this.user?.pk || 0,
|
id: user.pk,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
|
@ -255,7 +271,7 @@ export class UserViewPage extends AKElement {
|
||||||
</pf-tooltip>
|
</pf-tooltip>
|
||||||
</ak-action-button>
|
</ak-action-button>
|
||||||
`
|
`
|
||||||
: html``}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
@ -265,12 +281,12 @@ export class UserViewPage extends AKElement {
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="pf-c-description-list__description">
|
<dd class="pf-c-description-list__description">
|
||||||
<div class="pf-c-description-list__text ak-button-collection">
|
<div class="pf-c-description-list__text ak-button-collection">
|
||||||
<ak-forms-modal size=${PFSize.Medium}>
|
<ak-forms-modal size=${PFSize.Medium} id="update-password-request">
|
||||||
<span slot="submit">${msg("Update password")}</span>
|
<span slot="submit">${msg("Update password")}</span>
|
||||||
<span slot="header">${msg("Update password")}</span>
|
<span slot="header">${msg("Update password")}</span>
|
||||||
<ak-user-password-form
|
<ak-user-password-form
|
||||||
slot="form"
|
slot="form"
|
||||||
.instancePk=${this.user?.pk}
|
.instancePk=${user.pk}
|
||||||
></ak-user-password-form>
|
></ak-user-password-form>
|
||||||
<button
|
<button
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
|
@ -287,30 +303,7 @@ export class UserViewPage extends AKElement {
|
||||||
<ak-action-button
|
<ak-action-button
|
||||||
id="reset-password-button"
|
id="reset-password-button"
|
||||||
class="pf-m-secondary pf-m-block"
|
class="pf-m-secondary pf-m-block"
|
||||||
.apiRequest=${() => {
|
.apiRequest=${() => requestRecoveryLink(user)}
|
||||||
return new CoreApi(DEFAULT_CONFIG)
|
|
||||||
.coreUsersRecoveryRetrieve({
|
|
||||||
id: this.user?.pk || 0,
|
|
||||||
})
|
|
||||||
.then((rec) => {
|
|
||||||
showMessage({
|
|
||||||
level: MessageLevel.success,
|
|
||||||
message: msg(
|
|
||||||
"Successfully generated recovery link",
|
|
||||||
),
|
|
||||||
description: rec.link,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
showMessage({
|
|
||||||
level: MessageLevel.error,
|
|
||||||
message: msg(
|
|
||||||
"To create a recovery link, the current tenant needs to have a recovery flow configured.",
|
|
||||||
),
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<pf-tooltip
|
<pf-tooltip
|
||||||
position="top"
|
position="top"
|
||||||
|
@ -318,9 +311,10 @@ export class UserViewPage extends AKElement {
|
||||||
"Create a link for this user to reset their password",
|
"Create a link for this user to reset their password",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
${msg("Reset Password")}
|
${msg("Create Recovery Link")}
|
||||||
</pf-tooltip>
|
</pf-tooltip>
|
||||||
</ak-action-button>
|
</ak-action-button>
|
||||||
|
${user.email ? renderRecoveryEmailRequest(user) : nothing}
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
@ -329,9 +323,9 @@ export class UserViewPage extends AKElement {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBody(): TemplateResult {
|
renderBody() {
|
||||||
if (!this.user) {
|
if (!this.user) {
|
||||||
return html``;
|
return nothing;
|
||||||
}
|
}
|
||||||
return html`<ak-tabs>
|
return html`<ak-tabs>
|
||||||
<section
|
<section
|
||||||
|
|
Reference in New Issue