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; + } +}