web/admin: revamped rbac and user settings tabs (#8299)
* web/admin: fix duplicate RBAC preview banner on permission modal Signed-off-by: Jens Langhammer <jens@goauthentik.io> * switch non-embedded permission page to use vertical tabs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix some leftover html? Signed-off-by: Jens Langhammer <jens@goauthentik.io> * move stuff into vertical subtab Signed-off-by: Jens Langhammer <jens@goauthentik.io> * show all of users permission tabs on one main tab Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rework role page to match user page Signed-off-by: Jens Langhammer <jens@goauthentik.io> * use separate tabs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rename role permission tables to match user tables Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rename to credentials and tokens Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add country icon to session list Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add oauth access token list Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add helper to get relative time Signed-off-by: Jens Langhammer <jens@goauthentik.io> * use pfdivider Signed-off-by: Jens Langhammer <jens@goauthentik.io> * replace plain hr with pf-c-divider Signed-off-by: Jens Langhammer <jens@goauthentik.io> * use new logic for showing relative time in charts Signed-off-by: Jens Langhammer <jens@goauthentik.io> * use consistent relative time for event display Signed-off-by: Jens Langhammer <jens@goauthentik.io> * remove more leftovers Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix some alignment issues on the admin dashboard Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update storybook map Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add sanity check to event app lookup Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make api drawer header fixed Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix table padding for toggle Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix notification drawer for user interface Signed-off-by: Jens Langhammer <jens@goauthentik.io> * enable system task search Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix formatting, exclude generated script from formatting Signed-off-by: Jens Langhammer <jens@goauthentik.io> * web: minor fixes There's a renderer (it's not a component, not yet) for producing definition lists without the risk of missing a class or tag. Breaking conditionally rendered components out to make their use easier to identify. * fix prettier Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix outpost form Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix more flaky tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * re-create locale Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add some description for different permission views Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix system task search Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update docs Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Ken Sternberg <ken@goauthentik.io>
This commit is contained in:
@ -19,6 +19,7 @@ import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";
|
||||
import PFList from "@patternfly/patternfly/components/List/list.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
|
||||
@ -41,15 +42,12 @@ export class AdminOverviewPage extends AKElement {
|
||||
PFPage,
|
||||
PFContent,
|
||||
PFList,
|
||||
PFDivider,
|
||||
css`
|
||||
.row-divider {
|
||||
margin-top: -4px;
|
||||
margin-bottom: -4px;
|
||||
.pf-l-grid__item {
|
||||
height: 100%;
|
||||
}
|
||||
.graph-container {
|
||||
height: 20em;
|
||||
}
|
||||
.big-graph-container {
|
||||
.pf-l-grid__item.big-graph-container {
|
||||
height: 35em;
|
||||
}
|
||||
.card-container {
|
||||
@ -82,9 +80,7 @@ export class AdminOverviewPage extends AKElement {
|
||||
<div class="pf-l-grid pf-m-gutter">
|
||||
<!-- row 1 -->
|
||||
<div class="pf-l-grid__item pf-m-6-col pf-l-grid pf-m-gutter">
|
||||
<div
|
||||
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl graph-container"
|
||||
>
|
||||
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl">
|
||||
<ak-aggregate-card
|
||||
icon="fa fa-share"
|
||||
header=${msg("Quick actions")}
|
||||
@ -136,9 +132,7 @@ export class AdminOverviewPage extends AKElement {
|
||||
</ul>
|
||||
</ak-aggregate-card>
|
||||
</div>
|
||||
<div
|
||||
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl graph-container"
|
||||
>
|
||||
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl">
|
||||
<ak-aggregate-card
|
||||
icon="pf-icon pf-icon-zone"
|
||||
header=${msg("Outpost status")}
|
||||
@ -148,14 +142,14 @@ export class AdminOverviewPage extends AKElement {
|
||||
</ak-aggregate-card>
|
||||
</div>
|
||||
<div
|
||||
class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-4-col-on-2xl graph-container"
|
||||
class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-4-col-on-2xl"
|
||||
>
|
||||
<ak-aggregate-card icon="fa fa-sync-alt" header=${msg("Sync status")}>
|
||||
<ak-admin-status-chart-sync></ak-admin-status-chart-sync>
|
||||
</ak-aggregate-card>
|
||||
</div>
|
||||
<div class="pf-l-grid__item pf-m-12-col row-divider">
|
||||
<hr />
|
||||
<div class="pf-l-grid__item pf-m-12-col">
|
||||
<hr class="pf-c-divider" />
|
||||
</div>
|
||||
<div
|
||||
class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-4-col-on-xl card-container"
|
||||
@ -176,8 +170,8 @@ export class AdminOverviewPage extends AKElement {
|
||||
<div class="pf-l-grid__item pf-m-6-col">
|
||||
<ak-recent-events pageSize="6"></ak-recent-events>
|
||||
</div>
|
||||
<div class="pf-l-grid__item pf-m-12-col row-divider">
|
||||
<hr />
|
||||
<div class="pf-l-grid__item pf-m-12-col">
|
||||
<hr class="pf-c-divider" />
|
||||
</div>
|
||||
<!-- row 3 -->
|
||||
<div
|
||||
|
||||
@ -8,6 +8,7 @@ import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";
|
||||
import PFList from "@patternfly/patternfly/components/List/list.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
|
||||
@ -22,14 +23,8 @@ export class DashboardUserPage extends AKElement {
|
||||
PFPage,
|
||||
PFContent,
|
||||
PFList,
|
||||
PFDivider,
|
||||
css`
|
||||
.row-divider {
|
||||
margin-top: -4px;
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
.graph-container {
|
||||
height: 20em;
|
||||
}
|
||||
.big-graph-container {
|
||||
height: 35em;
|
||||
}
|
||||
@ -59,8 +54,8 @@ export class DashboardUserPage extends AKElement {
|
||||
</ak-charts-admin-model-per-day>
|
||||
</ak-aggregate-card>
|
||||
</div>
|
||||
<div class="pf-l-grid__item pf-m-12-col row-divider">
|
||||
<hr />
|
||||
<div class="pf-l-grid__item pf-m-12-col">
|
||||
<hr class="pf-c-divider" />
|
||||
</div>
|
||||
<!-- row 2 -->
|
||||
<div
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
|
||||
import { getRelativeTime } from "@goauthentik/app/common/utils";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EventWithContext } from "@goauthentik/common/events";
|
||||
import { actionToLabel } from "@goauthentik/common/labels";
|
||||
@ -71,7 +72,8 @@ export class RecentEventsCard extends Table<Event> {
|
||||
html`<div><a href="${`#/events/log/${item.pk}`}">${actionToLabel(item.action)}</a></div>
|
||||
<small>${item.app}</small>`,
|
||||
EventUser(item),
|
||||
html`<span>${item.created?.toLocaleString()}</span>`,
|
||||
html`<div>${getRelativeTime(item.created)}</div>
|
||||
<small>${item.created.toLocaleString()}</small>`,
|
||||
html` <div>${item.clientIp || msg("-")}</div>
|
||||
<small>${EventGeo(item)}</small>`,
|
||||
html`<span>${item.brand?.name || msg("-")}</span>`,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { AKChart, RGBAColor } from "@goauthentik/elements/charts/Chart";
|
||||
import { ChartData, Tick } from "chart.js";
|
||||
import { ChartData } from "chart.js";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { msg } from "@lit/localize";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
import { AdminApi, LoginMetrics } from "@goauthentik/api";
|
||||
@ -13,13 +13,6 @@ export class AdminLoginAuthorizeChart extends AKChart<LoginMetrics> {
|
||||
return new AdminApi(DEFAULT_CONFIG).adminMetricsRetrieve();
|
||||
}
|
||||
|
||||
timeTickCallback(tickValue: string | number, index: number, ticks: Tick[]): string {
|
||||
const valueStamp = ticks[index];
|
||||
const delta = Date.now() - valueStamp.value;
|
||||
const ago = Math.round(delta / 1000 / 3600 / 24);
|
||||
return msg(str`${ago} day(s) ago`);
|
||||
}
|
||||
|
||||
getChartData(data: LoginMetrics): ChartData {
|
||||
return {
|
||||
datasets: [
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import "@goauthentik/admin/events/EventVolumeChart";
|
||||
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
|
||||
import { getRelativeTime } from "@goauthentik/app/common/utils";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EventWithContext } from "@goauthentik/common/events";
|
||||
import { actionToLabel } from "@goauthentik/common/labels";
|
||||
@ -82,9 +83,9 @@ export class EventListPage extends TablePage<Event> {
|
||||
html`<div>${actionToLabel(item.action)}</div>
|
||||
<small>${item.app}</small>`,
|
||||
EventUser(item),
|
||||
html`<span>${item.created?.toLocaleString()}</span>`,
|
||||
html`<div>${getRelativeTime(item.created)}</div>
|
||||
<small>${item.created.toLocaleString()}</small>`,
|
||||
html`<div>${item.clientIp || msg("-")}</div>
|
||||
|
||||
<small>${EventGeo(item)}</small>`,
|
||||
html`<span>${item.brand?.name || msg("-")}</span>`,
|
||||
html`<a href="#/events/log/${item.pk}">
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
|
||||
import { getRelativeTime } from "@goauthentik/app/common/utils";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EventWithContext } from "@goauthentik/common/events";
|
||||
import { actionToLabel } from "@goauthentik/common/labels";
|
||||
@ -99,7 +100,8 @@ export class EventViewPage extends AKElement {
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
${this.event.created?.toLocaleString()}
|
||||
<div>${getRelativeTime(this.event.created)}</div>
|
||||
<small>${this.event.created.toLocaleString()}</small>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
@ -230,25 +230,29 @@ export class OutpostForm extends ModelForm<Outpost, string> {
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-group aria-label="Advanced settings">
|
||||
<span slot="header"> ${msg("Advanced settings")} </span>
|
||||
<ak-form-element-horizontal label=${msg("Configuration")} name="config">
|
||||
<ak-codemirror
|
||||
mode=${CodeMirrorMode.YAML}
|
||||
value="${YAML.stringify(
|
||||
this.instance ? this.instance.config : this.defaultConfig?.config,
|
||||
)}"
|
||||
></ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg("Set custom attributes using YAML or JSON.")}
|
||||
</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg("See more here:")}
|
||||
<a
|
||||
target="_blank"
|
||||
href="${docLink("/docs/outposts?utm_source=authentik#configuration")}"
|
||||
>${msg("Documentation")}</a
|
||||
>
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<div slot="body" class="pf-c-form">
|
||||
<ak-form-element-horizontal label=${msg("Configuration")} name="config">
|
||||
<ak-codemirror
|
||||
mode=${CodeMirrorMode.YAML}
|
||||
value="${YAML.stringify(
|
||||
this.instance ? this.instance.config : this.defaultConfig?.config,
|
||||
)}"
|
||||
></ak-codemirror>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg("Set custom attributes using YAML or JSON.")}
|
||||
</p>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg("See more here:")}
|
||||
<a
|
||||
target="_blank"
|
||||
href="${docLink(
|
||||
"/docs/outposts?utm_source=authentik#configuration",
|
||||
)}"
|
||||
>${msg("Documentation")}</a
|
||||
>
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
|
||||
import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
@ -70,6 +71,7 @@ export class OAuth2ProviderViewPage extends AKElement {
|
||||
PFForm,
|
||||
PFFormControl,
|
||||
PFBanner,
|
||||
PFDivider,
|
||||
];
|
||||
}
|
||||
|
||||
@ -258,7 +260,7 @@ export class OAuth2ProviderViewPage extends AKElement {
|
||||
value="${this.providerUrls?.issuer || msg("-")}"
|
||||
/>
|
||||
</div>
|
||||
<hr />
|
||||
<hr class="pf-c-divider" />
|
||||
<div class="pf-c-form__group">
|
||||
<label class="pf-c-form__label">
|
||||
<span class="pf-c-form__label-text"
|
||||
|
||||
@ -11,8 +11,8 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
import { Permission, RbacApi } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-role-permissions-global-table")
|
||||
export class RolePermissionGlobalTable extends Table<Permission> {
|
||||
@customElement("ak-role-assigned-global-permissions-table")
|
||||
export class RoleAssignedGlobalPermissionsTable extends Table<Permission> {
|
||||
@property()
|
||||
roleUuid?: string;
|
||||
|
||||
@ -10,8 +10,8 @@ import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import { ExtraRoleObjectPermission, ModelEnum, RbacApi } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-role-permissions-object-table")
|
||||
export class RolePermissionObjectTable extends Table<ExtraRoleObjectPermission> {
|
||||
@customElement("ak-role-assigned-object-permissions-table")
|
||||
export class RoleAssignedObjectPermissionTable extends Table<ExtraRoleObjectPermission> {
|
||||
@property()
|
||||
roleUuid?: string;
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
import "@goauthentik/admin/groups/RelatedGroupList";
|
||||
import "@goauthentik/app/admin/roles/RolePermissionGlobalTable";
|
||||
import "@goauthentik/app/admin/roles/RolePermissionObjectTable";
|
||||
import "@goauthentik/admin/roles/RoleForm";
|
||||
import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { renderDescriptionList } from "@goauthentik/components/DescriptionList";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import "@goauthentik/components/events/UserEvents";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import "@goauthentik/elements/PageHeader";
|
||||
import "@goauthentik/elements/Tabs";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
|
||||
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 PFBanner from "@patternfly/patternfly/components/Banner/banner.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
@ -43,7 +42,7 @@ export class RoleViewPage extends AKElement {
|
||||
@state()
|
||||
_role?: Role;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
static get styles() {
|
||||
return [
|
||||
PFBase,
|
||||
PFPage,
|
||||
@ -53,7 +52,6 @@ export class RoleViewPage extends AKElement {
|
||||
PFContent,
|
||||
PFCard,
|
||||
PFDescriptionList,
|
||||
PFBanner,
|
||||
css`
|
||||
.pf-c-description-list__description ak-action-button {
|
||||
margin-right: 6px;
|
||||
@ -74,7 +72,7 @@ export class RoleViewPage extends AKElement {
|
||||
});
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
render() {
|
||||
return html`<ak-page-header
|
||||
icon="fa fa-lock"
|
||||
header=${msg(str`Role ${this._role?.name || ""}`)}
|
||||
@ -83,73 +81,61 @@ export class RoleViewPage extends AKElement {
|
||||
${this.renderBody()}`;
|
||||
}
|
||||
|
||||
renderBody(): TemplateResult {
|
||||
renderUpdateControl(role: Role) {
|
||||
return html` <div class="pf-c-description-list__text">
|
||||
<ak-forms-modal>
|
||||
<span slot="submit"> ${msg("Update")} </span>
|
||||
<span slot="header"> ${msg("Update Role")} </span>
|
||||
<ak-role-form slot="form" .instancePk=${role.pk}> </ak-role-form>
|
||||
<button slot="trigger" class="pf-c-button pf-m-primary">${msg("Edit")}</button>
|
||||
</ak-forms-modal>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
renderBody() {
|
||||
if (!this._role) {
|
||||
return html``;
|
||||
return nothing;
|
||||
}
|
||||
return html`<div class="pf-c-banner pf-m-info">
|
||||
${msg("RBAC is in preview.")}
|
||||
<a href="mailto:hello@goauthentik.io">${msg("Send us feedback!")}</a>
|
||||
</div>
|
||||
<ak-tabs>
|
||||
<section
|
||||
slot="page-overview"
|
||||
data-tab-title="${msg("Overview")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-l-grid pf-m-gutter">
|
||||
<div
|
||||
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-3-col-on-xl pf-m-3-col-on-2xl"
|
||||
>
|
||||
<div class="pf-c-card__title">${msg("Role Info")}</div>
|
||||
<div class="pf-c-card__body">
|
||||
<dl class="pf-c-description-list">
|
||||
<div class="pf-c-description-list__group">
|
||||
<dt class="pf-c-description-list__term">
|
||||
<span class="pf-c-description-list__text"
|
||||
>${msg("Name")}</span
|
||||
>
|
||||
</dt>
|
||||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
${this._role.name}
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-9-col-on-xl pf-m-9-col-on-2xl"
|
||||
>
|
||||
<div class="pf-c-card__title">
|
||||
${msg("Assigned global permissions")}
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
<ak-role-permissions-global-table
|
||||
roleUuid=${this._role.pk}
|
||||
></ak-role-permissions-global-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
|
||||
<div class="pf-c-card__title">
|
||||
${msg("Assigned object permissions")}
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
<ak-role-permissions-object-table
|
||||
roleUuid=${this._role.pk}
|
||||
></ak-role-permissions-object-table>
|
||||
</div>
|
||||
|
||||
return html` <ak-tabs>
|
||||
<section
|
||||
slot="page-overview"
|
||||
data-tab-title="${msg("Overview")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-l-grid pf-m-gutter">
|
||||
<div
|
||||
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-3-col-on-xl pf-m-3-col-on-2xl"
|
||||
>
|
||||
<div class="pf-c-card__title">${msg("Role Info")}</div>
|
||||
<div class="pf-c-card__body">
|
||||
${renderDescriptionList([
|
||||
[msg("Name"), this._role.name],
|
||||
[msg("Edit"), this.renderUpdateControl(this._role)],
|
||||
])}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<ak-rbac-object-permission-page
|
||||
slot="page-permissions"
|
||||
data-tab-title="${msg("Permissions")}"
|
||||
model=${RbacPermissionsAssignedByUsersListModelEnum.RbacRole}
|
||||
objectPk=${this._role.pk}
|
||||
.showBanner=${false}
|
||||
></ak-rbac-object-permission-page>
|
||||
</ak-tabs>`;
|
||||
<div
|
||||
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-9-col-on-xl pf-m-9-col-on-2xl"
|
||||
>
|
||||
<div class="pf-c-card__title">${msg("Changelog")}</div>
|
||||
<div class="pf-c-card__body">
|
||||
<ak-object-changelog
|
||||
targetModelPk=${this.roleId}
|
||||
targetModelApp="authentik_rbac"
|
||||
targetModelName="role"
|
||||
>
|
||||
</ak-object-changelog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<ak-rbac-object-permission-page
|
||||
slot="page-permissions"
|
||||
data-tab-title="${msg("Permissions")}"
|
||||
model=${RbacPermissionsAssignedByUsersListModelEnum.RbacRole}
|
||||
objectPk=${this._role.pk}
|
||||
></ak-rbac-object-permission-page>
|
||||
</ak-tabs>`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,10 @@ export class SystemTaskListPage extends TablePage<SystemTask> {
|
||||
|
||||
expandable = true;
|
||||
|
||||
searchEnabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
@property()
|
||||
order = "name";
|
||||
|
||||
|
||||
@ -3,13 +3,13 @@ import "@goauthentik/admin/users/UserActiveForm";
|
||||
import "@goauthentik/admin/users/UserChart";
|
||||
import "@goauthentik/admin/users/UserForm";
|
||||
import "@goauthentik/admin/users/UserPasswordForm";
|
||||
import "@goauthentik/app/admin/users/UserAssignedGlobalPermissionsTable";
|
||||
import "@goauthentik/app/admin/users/UserAssignedObjectPermissionsTable";
|
||||
import {
|
||||
renderRecoveryEmailRequest,
|
||||
requestRecoveryLink,
|
||||
} from "@goauthentik/app/admin/users/UserListPage";
|
||||
import { me } from "@goauthentik/app/common/users";
|
||||
import "@goauthentik/app/elements/oauth/UserAccessTokenList";
|
||||
import "@goauthentik/app/elements/oauth/UserRefreshTokenList";
|
||||
import "@goauthentik/app/elements/rbac/ObjectPermissionsPage";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
@ -31,12 +31,11 @@ import "@goauthentik/elements/Tabs";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
import "@goauthentik/elements/oauth/UserRefreshList";
|
||||
import "@goauthentik/elements/user/SessionList";
|
||||
import "@goauthentik/elements/user/UserConsentList";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { css, html, nothing } from "lit";
|
||||
import { TemplateResult, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
|
||||
import PFBanner from "@patternfly/patternfly/components/Banner/banner.css";
|
||||
@ -227,45 +226,94 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) {
|
||||
|
||||
renderRecoveryButtons(user: User) {
|
||||
return html`<div class="ak-button-collection">
|
||||
<ak-forms-modal size=${PFSize.Medium} id="update-password-request">
|
||||
<span slot="submit">${msg("Update password")}</span>
|
||||
<span slot="header">${msg("Update password")}</span>
|
||||
<ak-user-password-form
|
||||
slot="form"
|
||||
.instancePk=${user.pk}
|
||||
></ak-user-password-form>
|
||||
<button
|
||||
slot="trigger"
|
||||
class="pf-c-button pf-m-secondary pf-m-block"
|
||||
>
|
||||
<pf-tooltip
|
||||
position="top"
|
||||
content=${msg("Enter a new password for this user")}
|
||||
>
|
||||
${msg("Set password")}
|
||||
</pf-tooltip>
|
||||
</button>
|
||||
</ak-forms-modal>
|
||||
<ak-action-button
|
||||
id="reset-password-button"
|
||||
class="pf-m-secondary pf-m-block"
|
||||
.apiRequest=${() => requestRecoveryLink(user)}
|
||||
>
|
||||
<pf-tooltip
|
||||
position="top"
|
||||
content=${msg(
|
||||
"Create a link for this user to reset their password",
|
||||
)}
|
||||
>
|
||||
${msg("Create Recovery Link")}
|
||||
</pf-tooltip>
|
||||
</ak-action-button>
|
||||
${user.email ? renderRecoveryEmailRequest(user) : nothing}
|
||||
</div>
|
||||
</dd>
|
||||
<ak-forms-modal size=${PFSize.Medium} id="update-password-request">
|
||||
<span slot="submit">${msg("Update password")}</span>
|
||||
<span slot="header">${msg("Update password")}</span>
|
||||
<ak-user-password-form slot="form" .instancePk=${user.pk}></ak-user-password-form>
|
||||
<button slot="trigger" class="pf-c-button pf-m-secondary pf-m-block">
|
||||
<pf-tooltip position="top" content=${msg("Enter a new password for this user")}>
|
||||
${msg("Set password")}
|
||||
</pf-tooltip>
|
||||
</button>
|
||||
</ak-forms-modal>
|
||||
<ak-action-button
|
||||
id="reset-password-button"
|
||||
class="pf-m-secondary pf-m-block"
|
||||
.apiRequest=${() => requestRecoveryLink(user)}
|
||||
>
|
||||
<pf-tooltip
|
||||
position="top"
|
||||
content=${msg("Create a link for this user to reset their password")}
|
||||
>
|
||||
${msg("Create Recovery Link")}
|
||||
</pf-tooltip>
|
||||
</ak-action-button>
|
||||
${user.email ? renderRecoveryEmailRequest(user) : nothing}
|
||||
</div> `;
|
||||
}
|
||||
|
||||
renderTabCredentialsToken(user: User): TemplateResult {
|
||||
return html`
|
||||
<ak-tabs pageIdentifier="userCredentialsTokens" ?vertical=${true}>
|
||||
<section
|
||||
slot="page-sessions"
|
||||
data-tab-title="${msg("Sessions")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-session-list targetUser=${user.username}>
|
||||
</ak-user-session-list>
|
||||
</div>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-consent"
|
||||
data-tab-title="${msg("Explicit Consent")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-consent-list userId=${user.pk}> </ak-user-consent-list>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-oauth-access"
|
||||
data-tab-title="${msg("OAuth Access Tokens")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-oauth-access-token-list userId=${user.pk}>
|
||||
</ak-user-oauth-access-token-list>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-oauth-refresh"
|
||||
data-tab-title="${msg("OAuth Refresh Tokens")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-oauth-refresh-token-list userId=${user.pk}>
|
||||
</ak-user-oauth-refresh-token-list>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-mfa-authenticators"
|
||||
data-tab-title="${msg("MFA Authenticators")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-device-table userId=${user.pk}> </ak-user-device-table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</ak-tabs>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -326,18 +374,6 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-sessions"
|
||||
data-tab-title="${msg("Sessions")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-session-list targetUser=${this.user.username}>
|
||||
</ak-user-session-list>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-groups"
|
||||
data-tab-title="${msg("Groups")}"
|
||||
@ -360,78 +396,16 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-consent"
|
||||
data-tab-title="${msg("Explicit Consent")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-consent-list userId=${this.user.pk}> </ak-user-consent-list>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-oauth-refresh"
|
||||
data-tab-title="${msg("OAuth Refresh Tokens")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-oauth-refresh-list userId=${this.user.pk}>
|
||||
</ak-user-oauth-refresh-list>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-mfa-authenticators"
|
||||
data-tab-title="${msg("MFA Authenticators")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-device-table userId=${this.user.pk}> </ak-user-device-table>
|
||||
</div>
|
||||
</div>
|
||||
<section slot="page-credentials" data-tab-title="${msg("Credentials / Tokens")}">
|
||||
${this.renderTabCredentialsToken(this.user)}
|
||||
</section>
|
||||
<ak-rbac-object-permission-page
|
||||
slot="page-permissions"
|
||||
data-tab-title="${msg("Permissions")}"
|
||||
model=${RbacPermissionsAssignedByUsersListModelEnum.CoreUser}
|
||||
objectPk=${this.user.pk}
|
||||
></ak-rbac-object-permission-page>
|
||||
<div
|
||||
slot="page-mfa-assigned-permissions"
|
||||
data-tab-title="${msg("Assigned permissions")}"
|
||||
class=""
|
||||
>
|
||||
<div class="pf-c-banner pf-m-info">
|
||||
${msg("RBAC is in preview.")}
|
||||
<a href="mailto:hello@goauthentik.io">${msg("Send us feedback!")}</a>
|
||||
</div>
|
||||
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||
<div class="pf-l-grid pf-m-gutter">
|
||||
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
|
||||
<div class="pf-c-card__title">
|
||||
${msg("Assigned global permissions")}
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-assigned-global-permissions-table userId=${this.user.pk}>
|
||||
</ak-user-assigned-global-permissions-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-card pf-l-grid__item pf-m-12-col">
|
||||
<div class="pf-c-card__title">
|
||||
${msg("Assigned object permissions")}
|
||||
</div>
|
||||
<div class="pf-c-card__body">
|
||||
<ak-user-assigned-object-permissions-table userId=${this.user.pk}>
|
||||
</ak-user-assigned-object-permissions-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</ak-rbac-object-permission-page>
|
||||
</ak-tabs>`;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user