web/admin: migrate user forms to web

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer
2021-03-29 16:16:27 +02:00
parent fac8d53163
commit 526af26536
11 changed files with 145 additions and 144 deletions

View File

@ -68,10 +68,6 @@ export class AdminURLManager {
return `/administration/events/transports/${rest}`;
}
static users(rest: string): string {
return `/administration/users/${rest}`;
}
}
export class UserURLManager {

View File

@ -23,8 +23,7 @@ export class ActionButton extends SpinnerButton {
this.setLoading();
this.apiRequest().then(() => {
this.setDone(SUCCESS_CLASS);
})
.catch((e: Error | Response) => {
}).catch((e: Error | Response) => {
if (e instanceof Error) {
showMessage({
level: MessageLevel.error,

View File

@ -18,9 +18,9 @@ export class GroupForm extends Form<Group> {
getSuccessMessage(): string {
if (this.group) {
return gettext("Successfully updated group");
return gettext("Successfully updated group.");
} else {
return gettext("Successfully created group");
return gettext("Successfully created group.");
}
}

View File

@ -66,7 +66,7 @@ export class GroupListPage extends TablePage<Group> {
</span>
<ak-group-form slot="form" .group=${item}>
</ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
<button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")}
</button>
</ak-forms-modal>

View File

@ -0,0 +1,68 @@
import { CoreApi, User } from "authentik-api";
import { gettext } from "django";
import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config";
import { Form } from "../../elements/forms/Form";
import { ifDefined } from "lit-html/directives/if-defined";
import "../../elements/forms/HorizontalFormElement";
import "../../elements/CodeMirror";
import YAML from "yaml";
@customElement("ak-user-form")
export class UserForm extends Form<User> {
@property({ attribute: false })
user?: User;
getSuccessMessage(): string {
if (this.user) {
return gettext("Successfully updated user.");
} else {
return gettext("Successfully created user.");
}
}
send = (data: User): Promise<User> => {
if (this.user) {
return new CoreApi(DEFAULT_CONFIG).coreUsersUpdate({
id: this.user.pk || 0,
data: data
});
} else {
return new CoreApi(DEFAULT_CONFIG).coreUsersCreate({
data: data
});
}
};
renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${gettext("Username")} ?required=${true}>
<input type="text" name="username" value="${ifDefined(this.user?.username)}" class="pf-c-form-control" required="">
<p class="pf-c-form__helper-text">${gettext("Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.")}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${gettext("Name")} ?required=${true}>
<input type="text" name="name" value="${ifDefined(this.user?.name)}" class="pf-c-form-control" required="">
<p class="pf-c-form__helper-text">${gettext("User's display name.")}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${gettext("Email")} ?required=${true}>
<input type="email" name="email" autocomplete="off" value="${ifDefined(this.user?.email)}" class="pf-c-form-control" required="">
</ak-form-element-horizontal>
<ak-form-element-horizontal>
<div class="pf-c-check">
<input type="checkbox" name="is_active" class="pf-c-check__input" ?checked=${this.user?.isActive || false}>
<label class="pf-c-check__label">
${gettext("Is active")}
</label>
</div>
<p class="pf-c-form__helper-text">${gettext("Designates whether this user should be treated as active. Unselect this instead of deleting accounts.")}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${gettext("Attributes")}>
<ak-codemirror mode="yaml" name="attributes" value="${YAML.stringify(this.user?.attributes)}">
</ak-codemirror>
</ak-form-element-horizontal>
</form>`;
}
}

View File

@ -3,16 +3,18 @@ import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client";
import { TablePage } from "../../elements/table/TablePage";
import "../../elements/buttons/ModalButton";
import "../../elements/forms/ModalForm";
import "../../elements/buttons/Dropdown";
import "../../elements/buttons/ActionButton";
import { TableColumn } from "../../elements/table/Table";
import { PAGE_SIZE } from "../../constants";
import { CoreApi, User } from "authentik-api";
import { DEFAULT_CONFIG } from "../../api/Config";
import { AdminURLManager } from "../../api/legacy";
import "../../elements/forms/DeleteForm";
import "./UserActiveForm";
import "./UserForm";
import { showMessage } from "../../elements/messages/MessageContainer";
import { MessageLevel } from "../../elements/messages/Message";
@customElement("ak-user-list")
export class UserListPage extends TablePage<User> {
@ -59,12 +61,19 @@ export class UserListPage extends TablePage<User> {
html`${item.isActive ? "Yes" : "No"}`,
html`${item.lastLogin?.toLocaleString()}`,
html`
<ak-modal-button href="${AdminURLManager.users(`${item.pk}/update/`)}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
<ak-forms-modal>
<span slot="submit">
${gettext("Update")}
</span>
<span slot="header">
${gettext("Update User")}
</span>
<ak-user-form slot="form" .user=${item}>
</ak-user-form>
<button slot="trigger" class="pf-m-secondary pf-c-button">
${gettext("Edit")}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</button>
</ak-forms-modal>
<ak-dropdown class="pf-c-dropdown">
<button class="pf-c-dropdown__toggle pf-m-primary" type="button">
<span class="pf-c-dropdown__toggle-text">${gettext(item.isActive ? "Disable" : "Enable")}</span>
@ -107,7 +116,18 @@ export class UserListPage extends TablePage<User> {
</li>
</ul>
</ak-dropdown>
<ak-action-button method="GET" url="${AdminURLManager.users(`${item.pk}/reset/`)}">
<ak-action-button
.apiRequest=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUsersRecovery({
id: item.pk || 0,
}).then(rec => {
showMessage({
level: MessageLevel.success,
message: gettext("Successfully generated recovery link"),
description: rec.link
});
});
}}>
${gettext("Reset Password")}
</ak-action-button>
<a class="pf-c-button pf-m-tertiary" href="${`/-/impersonation/${item.pk}/`}">
@ -118,13 +138,21 @@ export class UserListPage extends TablePage<User> {
renderToolbar(): TemplateResult {
return html`
<ak-modal-button href=${AdminURLManager.users("create/")}>
<ak-spinner-button slot="trigger" class="pf-m-primary">
<ak-forms-modal>
<span slot="submit">
${gettext("Create")}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</span>
<span slot="header">
${gettext("Create User")}
</span>
<ak-user-form slot="form">
</ak-user-form>
<button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")}
</button>
</ak-forms-modal>
${super.renderToolbar()}
`;
}
}

View File

@ -12,7 +12,9 @@ import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import AKGlobal from "../../authentik.css";
import "../../elements/buttons/ModalButton";
import "../../elements/forms/ModalForm";
import "./UserForm";
import "../../elements/buttons/ActionButton";
import "../../elements/buttons/SpinnerButton";
import "../../elements/CodeMirror";
import "../../elements/Tabs";
@ -24,8 +26,9 @@ import "../../elements/charts/UserChart";
import { Page } from "../../elements/Page";
import { CoreApi, User } from "authentik-api";
import { DEFAULT_CONFIG } from "../../api/Config";
import { AdminURLManager } from "../../api/legacy";
import { EVENT_REFRESH } from "../../constants";
import { showMessage } from "../../elements/messages/MessageContainer";
import { MessageLevel } from "../../elements/messages/Message";
@customElement("ak-user-view")
export class UserViewPage extends Page {
@ -131,20 +134,35 @@ export class UserViewPage extends Page {
</dl>
</div>
<div class="pf-c-card__footer">
<ak-modal-button href="${AdminURLManager.users(`${this.user.pk}/update/`)}">
<ak-spinner-button slot="trigger" class="pf-m-primary">
<ak-forms-modal>
<span slot="submit">
${gettext("Update")}
</span>
<span slot="header">
${gettext("Update User")}
</span>
<ak-user-form slot="form" .user=${this.user}>
</ak-user-form>
<button slot="trigger" class="pf-m-primary pf-c-button">
${gettext("Edit")}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
</button>
</ak-forms-modal>
</div>
<div class="pf-c-card__footer">
<ak-modal-button href="${AdminURLManager.users(`${this.user.pk}/reset/`)}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
${gettext("Reset Password")}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-action-button
.apiRequest=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUsersRecovery({
id: this.user?.pk || 0,
}).then(rec => {
showMessage({
level: MessageLevel.success,
message: gettext("Successfully generated recovery link"),
description: rec.link
});
});
}}>
${gettext("Reset Password")}
</ak-action-button>
</div>
</div>
<div class="pf-c-card pf-l-gallery__item pf-m-4-col" style="grid-column-end: span 4;grid-row-end: span 2;">