Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web/admin: revamped rbac and user settings tabs #8299

Merged
merged 33 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
14c23c3
web/admin: fix duplicate RBAC preview banner on permission modal
BeryJu Jan 25, 2024
5bc94e6
switch non-embedded permission page to use vertical tabs
BeryJu Jan 25, 2024
ed1a779
fix some leftover html?
BeryJu Jan 25, 2024
1f90869
move stuff into vertical subtab
BeryJu Jan 25, 2024
1d531cd
show all of users permission tabs on one main tab
BeryJu Jan 25, 2024
8ab2077
rework role page to match user page
BeryJu Jan 25, 2024
83fdf41
use separate tabs
BeryJu Jan 25, 2024
3a19e25
rename role permission tables to match user tables
BeryJu Jan 25, 2024
5661ab3
rename to credentials and tokens
BeryJu Jan 25, 2024
a1bc4e5
add country icon to session list
BeryJu Jan 25, 2024
a2a99db
add oauth access token list
BeryJu Jan 25, 2024
b5e18e5
add helper to get relative time
BeryJu Jan 25, 2024
f7082d5
use pfdivider
BeryJu Jan 25, 2024
b96457a
replace plain hr with pf-c-divider
BeryJu Jan 25, 2024
bef6386
use new logic for showing relative time in charts
BeryJu Jan 25, 2024
ce65aa3
use consistent relative time for event display
BeryJu Jan 25, 2024
ed3f655
remove more leftovers
BeryJu Jan 25, 2024
745519d
fix some alignment issues on the admin dashboard
BeryJu Jan 25, 2024
b491abb
update storybook map
BeryJu Jan 25, 2024
ac822b8
add sanity check to event app lookup
BeryJu Jan 25, 2024
5e51347
make api drawer header fixed
BeryJu Jan 25, 2024
584b221
fix table padding for toggle
BeryJu Jan 25, 2024
fd59281
fix notification drawer for user interface
BeryJu Jan 25, 2024
38ea282
enable system task search
BeryJu Jan 25, 2024
01c023e
fix formatting, exclude generated script from formatting
BeryJu Jan 25, 2024
0a2d77a
web: minor fixes
kensternberg-authentik Jan 25, 2024
74aa0d5
fix prettier
BeryJu Jan 25, 2024
a592828
fix outpost form
BeryJu Jan 25, 2024
db7be23
fix more flaky tests
BeryJu Jan 25, 2024
a3feefe
re-create locale
BeryJu Jan 25, 2024
6354a25
add some description for different permission views
BeryJu Jan 25, 2024
5a65477
fix system task search
BeryJu Jan 25, 2024
96d13a3
update docs
BeryJu Jan 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion authentik/events/api/notification_transports.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ def test(self, request: Request, pk=None) -> Response:
event = Event.new(
action="notification_test",
user=get_user(request.user),
app=self.__class__.__module__,
context={"foo": "bar"},
)
event.save()
Expand Down
5 changes: 3 additions & 2 deletions authentik/events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,9 @@ def new(
app = parent.f_globals["__name__"]
# Attempt to match the calling module to the django app it belongs to
# if we can't find a match, keep the module name
django_apps = get_close_matches(app, django_app_names(), n=1)
if len(django_apps) > 0:
django_apps: list[str] = get_close_matches(app, django_app_names(), n=1)
# Also ensure that closest django app has the correct prefix
if len(django_apps) > 0 and django_apps[0].startswith(app):
app = django_apps[0]
cleaned_kwargs = cleanse_dict(sanitize_dict(kwargs))
event = Event(action=action, app=app, context=cleaned_kwargs)
Expand Down
4 changes: 2 additions & 2 deletions authentik/tenants/tests/test_recovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def test_create_key(self):
body = loads(response.content.decode())
token = Token.objects.get(intent=TokenIntents.INTENT_RECOVERY, user=self.user)
self.assertIn(token.key, body["url"])
self.assertEqual(len(Token.objects.all()), 1)
self.assertEqual(len(Token.objects.filter(intent=TokenIntents.INTENT_RECOVERY)), 1)

@CONFIG.patch("outposts.disable_embedded_outpost", True)
@CONFIG.patch("tenants.enabled", True)
Expand All @@ -86,4 +86,4 @@ def test_create_key_invalid(self):
headers=HEADERS,
)
self.assertEqual(response.status_code, 404)
self.assertEqual(len(Token.objects.all()), 0)
self.assertEqual(len(Token.objects.filter(intent=TokenIntents.INTENT_RECOVERY)), 0)
1 change: 1 addition & 0 deletions web/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ src/locales/
storybook-static/
# Prettier breaks the tsconfig file
tsconfig.json
.storybook/css-import-maps*
7 changes: 3 additions & 4 deletions web/.storybook/css-import-maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const rawCssImportMaps = [
'import PFDataList from "@patternfly/patternfly/components/DataList/data-list.css";',
'import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";',
'import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css";',
'import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";',
'import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";',
'import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css";',
'import PFDualListSelector from "@patternfly/patternfly/components/DualListSelector/dual-list-selector.css";',
Expand Down Expand Up @@ -70,10 +71,8 @@ const rawCssImportMaps = [
'import styles from "./LibraryPageImpl.css";',
];

const cssImportMaps = rawCssImportMaps.reduce(
(acc, line) => ({ ...acc, [line]: line.replace(/\.css/, ".css?inline") }),
{},
);
const cssImportMaps = rawCssImportMaps.reduce((acc, line) => (
{...acc, [line]: line.replace(/\.css/, ".css?inline")}), {});

export { cssImportMaps };
export default cssImportMaps;
3 changes: 1 addition & 2 deletions web/scripts/build-storybook-import-maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ function getTheImportLines(importPaths: string[]) {
const importPaths = getTheSourceFiles();
const importLines = getTheImportLines(importPaths);

const outputFile = `
// THIS IS A GENERATED FILE. DO NOT EDIT BY HAND.
const outputFile = `// THIS IS A GENERATED FILE. DO NOT EDIT BY HAND.
//
// This file is generated by the build-storybook-import-maps script in the UI's base directory.
// This is a *hack* to work around an inconsistency in the way rollup, vite, and storybook
Expand Down
30 changes: 12 additions & 18 deletions web/src/admin/admin-overview/AdminOverviewPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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 {
Expand Down Expand Up @@ -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")}
Expand Down Expand Up @@ -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")}
Expand All @@ -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"
Expand All @@ -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
Expand Down
13 changes: 4 additions & 9 deletions web/src/admin/admin-overview/DashboardUserPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion web/src/admin/admin-overview/cards/RecentEventsCard.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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>`,
Expand Down
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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: [
Expand Down
5 changes: 3 additions & 2 deletions web/src/admin/events/EventListPage.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nifty. I tend to reverse these: "Dec 10, 2023 (23 days ago)", but I think the human brain appreciates having a "distance from here / distance from now" along with a location or date.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My brain is quite happy to get that relative info.

<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}">
Expand Down
4 changes: 3 additions & 1 deletion web/src/admin/events/EventViewPage.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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>
Expand Down
42 changes: 23 additions & 19 deletions web/src/admin/outposts/OutpostForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:")}&nbsp;
<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:")}&nbsp;
<a
target="_blank"
href="${docLink(
"/docs/outposts?utm_source=authentik#configuration",
)}"
>${msg("Documentation")}</a
>
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>`;
}
}
4 changes: 3 additions & 1 deletion web/src/admin/providers/oauth2/OAuth2ProviderViewPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -70,6 +71,7 @@ export class OAuth2ProviderViewPage extends AKElement {
PFForm,
PFFormControl,
PFBanner,
PFDivider,
];
}

Expand Down Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading
Loading