diff --git a/web/package.json b/web/package.json
index 4e3bd503f1..51716ce9d0 100644
--- a/web/package.json
+++ b/web/package.json
@@ -15,7 +15,7 @@
"build-proxy": "run-s build-locales esbuild:build-proxy",
"watch": "run-s build-locales esbuild:watch",
"lint": "cross-env NODE_OPTIONS='--max_old_space_size=65536' eslint . --max-warnings 0 --fix",
- "lint:precommit": "cross-env NODE_OPTIONS='--max_old_space_size=65536' node scripts/eslint-precommit.mjs",
+ "lint:precommit": "bun scripts/eslint-precommit.mjs",
"lint:spelling": "node scripts/check-spelling.mjs",
"lit-analyse": "lit-analyzer src",
"precommit": "npm-run-all --parallel tsc lit-analyse lint:spelling --sequential lint:precommit prettier",
diff --git a/web/src/admin/admin-overview/AdminOverviewPage.ts b/web/src/admin/admin-overview/AdminOverviewPage.ts
index d24d17814d..f361d11ac1 100644
--- a/web/src/admin/admin-overview/AdminOverviewPage.ts
+++ b/web/src/admin/admin-overview/AdminOverviewPage.ts
@@ -1,5 +1,6 @@
import "@goauthentik/admin/admin-overview/TopApplicationsTable";
import "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
+import "@goauthentik/admin/admin-overview/cards/FipsStatusCard";
import "@goauthentik/admin/admin-overview/cards/RecentEventsCard";
import "@goauthentik/admin/admin-overview/cards/SystemStatusCard";
import "@goauthentik/admin/admin-overview/cards/VersionStatusCard";
@@ -10,13 +11,17 @@ import "@goauthentik/admin/admin-overview/charts/SyncStatusChart";
import { VERSION } from "@goauthentik/common/constants";
import { me } from "@goauthentik/common/users";
import { AKElement } from "@goauthentik/elements/Base";
+import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider.js";
import "@goauthentik/elements/PageHeader";
import "@goauthentik/elements/cards/AggregatePromiseCard";
import { paramURL } from "@goauthentik/elements/router/RouterOutlet";
import { msg, str } from "@lit/localize";
-import { CSSResult, TemplateResult, css, html } from "lit";
+import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement, state } from "lit/decorators.js";
+import { classMap } from "lit/directives/class-map.js";
+import { map } from "lit/directives/map.js";
+import { when } from "lit/directives/when.js";
import PFContent from "@patternfly/patternfly/components/Content/content.css";
import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";
@@ -33,8 +38,12 @@ export function versionFamily(): string {
return parts.join(".");
}
+const AdminOverviewBase = WithLicenseSummary(AKElement);
+
+type Renderer = () => TemplateResult | typeof nothing;
+
@customElement("ak-admin-overview")
-export class AdminOverviewPage extends AKElement {
+export class AdminOverviewPage extends AdminOverviewBase {
static get styles(): CSSResult[] {
return [
PFBase,
@@ -73,6 +82,7 @@ export class AdminOverviewPage extends AKElement {
render(): TemplateResult {
const name = this.user?.user.name ?? this.user?.user.username;
+
return html`
${msg(str`Welcome, ${name}.`)}
@@ -89,48 +99,7 @@ export class AdminOverviewPage extends AKElement {
.isCenter=${false}
>
@@ -153,21 +122,7 @@ export class AdminOverviewPage extends AKElement {
-
-
-
+ ${this.renderCards()}
@@ -201,4 +156,70 @@ export class AdminOverviewPage extends AKElement {
`;
}
+
+ renderCards() {
+ const isEnterprise = this.hasEnterpriseLicense;
+ const classes = {
+ "card-container": true,
+ "pf-l-grid__item": true,
+ "pf-m-6-col": true,
+ "pf-m-4-col-on-md": !isEnterprise,
+ "pf-m-4-col-on-xl": !isEnterprise,
+ "pf-m-3-col-on-md": isEnterprise,
+ "pf-m-3-col-on-xl": isEnterprise,
+ };
+
+ return html`
+
+
+ ${isEnterprise
+ ? html` `
+ : nothing} `;
+ }
+
+ renderActions() {
+ const release = `${versionFamily()}#fixed-in-${VERSION.replaceAll(".", "")}`;
+
+ const quickActions: [string, string][] = [
+ [msg("Create a new application"), paramURL("/core/applications", { createForm: true })],
+ [msg("Check the logs"), paramURL("/events/log")],
+ [msg("Explore integrations"), "https://goauthentik.io/integrations/"],
+ [msg("Manage users"), paramURL("/identity/users")],
+ [msg("Check the release notes"), `https://goauthentik.io/docs/releases/${release}`],
+ ];
+
+ const action = ([label, url]: [string, string]) => {
+ const isExternal = url.startsWith("https://");
+ const ex = (truecase: Renderer, falsecase: Renderer) =>
+ when(isExternal, truecase, falsecase);
+
+ const content = html`${label}${ex(
+ () => html``,
+ () => nothing,
+ )}`;
+
+ return html`
+ ${ex(
+ () => html`${content}`,
+ () => html`${content}`,
+ )}
+ `;
+ };
+
+ return html`${map(quickActions, action)}`;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ak-admin-overview": AdminOverviewPage;
+ }
}
diff --git a/web/src/admin/admin-overview/cards/FipsStatusCard.ts b/web/src/admin/admin-overview/cards/FipsStatusCard.ts
new file mode 100644
index 0000000000..5f9e4168ba
--- /dev/null
+++ b/web/src/admin/admin-overview/cards/FipsStatusCard.ts
@@ -0,0 +1,56 @@
+import {
+ AdminStatus,
+ AdminStatusCard,
+} from "@goauthentik/admin/admin-overview/cards/AdminStatusCard";
+import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
+
+import { msg } from "@lit/localize";
+import { TemplateResult, html } from "lit";
+import { customElement, state } from "lit/decorators.js";
+
+import { AdminApi, SystemInfo } from "@goauthentik/api";
+
+type StatusContent = { icon: string; message: TemplateResult };
+
+@customElement("ak-admin-fips-status-system")
+export class FipsStatusCard extends AdminStatusCard {
+ icon = "pf-icon pf-icon-server";
+
+ @state()
+ statusSummary?: string;
+
+ async getPrimaryValue(): Promise {
+ return await new AdminApi(DEFAULT_CONFIG).adminSystemRetrieve();
+ }
+
+ setStatus(summary: string, content: StatusContent): Promise {
+ this.statusSummary = summary;
+ return Promise.resolve(content);
+ }
+
+ getStatus(value: SystemInfo): Promise {
+ return value.runtime.opensslFipsMode
+ ? this.setStatus(msg("OK"), {
+ icon: "fa fa-check-circle pf-m-success",
+ message: html`${msg("FIPS compliance: passing")}`,
+ })
+ : this.setStatus(msg("Unverified"), {
+ icon: "fa fa-info-circle pf-m-warning",
+ message: html`${msg("FIPS compliance: unverified")}`,
+ });
+ }
+
+ renderHeader(): TemplateResult {
+ return html`${msg("FIPS Status")}`;
+ }
+
+ renderValue(): TemplateResult {
+ return html`${this.statusSummary}`;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ak-admin-fips-status-system": FipsStatusCard;
+ }
+}