From 303b847cdc11571159bb17f2c95bb7833ea2dba8 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 6 May 2021 13:02:07 +0200 Subject: [PATCH] web/admin: rewrite overview page Signed-off-by: Jens Langhammer --- web/src/elements/charts/Chart.ts | 127 ++++++---- web/src/locales/en.po | 224 ++++++++---------- web/src/locales/pseudo-LOCALE.po | 212 ++++++++--------- .../pages/admin-overview/AdminOverviewPage.ts | 110 ++++++--- .../admin-overview/TopApplicationsTable.ts | 1 + .../cards/FlowCacheStatusCard.ts | 52 ---- .../cards/LDAPSyncStatusCard.ts | 56 ----- .../cards/LDAPSyncStatusCardContainer.ts | 30 --- .../cards/PolicyCacheStatusCard.ts | 53 ----- .../cards/PolicyUnboundStatusCard.ts | 32 --- .../admin-overview/graphs/FlowStatusCard.ts | 67 ++++++ .../graphs/LDAPSyncStatusCard.ts | 91 +++++++ .../graphs/OutpostStatusCard.ts | 87 +++++++ .../admin-overview/graphs/PolicyStatusCard.ts | 76 ++++++ web/src/pages/policies/PolicyBindingForm.ts | 1 - 15 files changed, 677 insertions(+), 542 deletions(-) delete mode 100644 web/src/pages/admin-overview/cards/FlowCacheStatusCard.ts delete mode 100644 web/src/pages/admin-overview/cards/LDAPSyncStatusCard.ts delete mode 100644 web/src/pages/admin-overview/cards/LDAPSyncStatusCardContainer.ts delete mode 100644 web/src/pages/admin-overview/cards/PolicyCacheStatusCard.ts delete mode 100644 web/src/pages/admin-overview/cards/PolicyUnboundStatusCard.ts create mode 100644 web/src/pages/admin-overview/graphs/FlowStatusCard.ts create mode 100644 web/src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts create mode 100644 web/src/pages/admin-overview/graphs/OutpostStatusCard.ts create mode 100644 web/src/pages/admin-overview/graphs/PolicyStatusCard.ts diff --git a/web/src/elements/charts/Chart.ts b/web/src/elements/charts/Chart.ts index 5167260ca..85e6bc34e 100644 --- a/web/src/elements/charts/Chart.ts +++ b/web/src/elements/charts/Chart.ts @@ -1,8 +1,15 @@ -import { css, CSSResult, html, LitElement, TemplateResult } from "lit-element"; -import { Chart, ChartDataset, Tick, LineController, TimeScale, LinearScale, BarController, BarElement, ChartConfiguration, Legend, ChartData } from "chart.js"; +import { css, CSSResult, html, LitElement, property, TemplateResult } from "lit-element"; +import { Chart, Plugin, Tick, ChartConfiguration, ChartData, ChartOptions } from "chart.js"; +import { Legend, Tooltip } from "chart.js"; +import { DoughnutController, LineController, BarController } from "chart.js"; +import { ArcElement, BarElement } from "chart.js"; +import { TimeScale, LinearScale } from "chart.js"; import "chartjs-adapter-moment"; -Chart.register(LineController, TimeScale, LinearScale, BarController, BarElement, Legend); +Chart.register(Legend, Tooltip); +Chart.register(LineController, BarController, DoughnutController); +Chart.register(ArcElement, BarElement); +Chart.register(TimeScale, LinearScale); export abstract class AKChart extends LitElement { @@ -11,14 +18,13 @@ export abstract class AKChart extends LitElement { chart?: Chart; + @property() + centerText?: string; + static get styles(): CSSResult[] { return [css` - :host { - position: relative; + .container { height: 100%; - width: 100%; - display: block; - min-height: 25rem; } canvas { width: 100px; @@ -36,46 +42,79 @@ export abstract class AKChart extends LitElement { }); } + getChartType(): string { + return "bar"; + } + + getPlugins(): Plugin[] { + return [ + { + id: "center-text", + beforeDraw: (chart) => { + if (!chart.ctx) return; + if (!this.centerText) return; + const width = chart.width || 0; + const height = chart.height || 0; + + const fontSize = (height / 114).toFixed(2); + chart.ctx.font = fontSize + "em RedHatText, Overpass, overpass, helvetica, arial, sans-serif"; + chart.ctx.textBaseline = "middle"; + + const textX = Math.round((width - chart.ctx.measureText(this.centerText).width) / 2); + const textY = height / 2; + + chart.ctx.fillText(this.centerText, textX, textY); + } + } + ]; + } + + getOptions(): ChartOptions { + return { + maintainAspectRatio: false, + scales: { + x: { + type: "time", + display: true, + ticks: { + callback: function (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); + return `${ago} Hours ago`; + }, + autoSkip: true, + maxTicksLimit: 8, + }, + stacked: true, + grid: { + color: "rgba(0, 0, 0, 0)", + }, + offset: true + }, + y: { + type: "linear", + display: true, + stacked: true, + grid: { + color: "rgba(0, 0, 0, 0)", + }, + } + }, + } as ChartOptions; + } + configureChart(data: T, ctx: CanvasRenderingContext2D): Chart { const config = { - type: "bar", + type: this.getChartType(), data: this.getChartData(data), - options: { - maintainAspectRatio: false, - scales: { - x: { - type: "time", - display: true, - ticks: { - callback: function (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); - return `${ago} Hours ago`; - }, - autoSkip: true, - maxTicksLimit: 8, - }, - stacked: true, - grid: { - color: "rgba(0, 0, 0, 0)", - }, - offset: true - }, - y: { - type: "linear", - display: true, - stacked: true, - grid: { - color: "rgba(0, 0, 0, 0)", - }, - } - }, - }, + options: this.getOptions(), + plugins: this.getPlugins(), }; return new Chart(ctx, config as ChartConfiguration); } + firstUpdated(): void { this.apiRequest().then((r) => { const canvas = this.shadowRoot?.querySelector("canvas"); @@ -93,6 +132,10 @@ export abstract class AKChart extends LitElement { } render(): TemplateResult { - return html``; + return html` +
+ +
+ `; } } diff --git a/web/src/locales/en.po b/web/src/locales/en.po index f96a0a9e3..adde97f89 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -144,6 +144,10 @@ msgstr "Algorithm used to sign the JWT Tokens." msgid "Allow IDP-initiated logins" msgstr "Allow IDP-initiated logins" +#: src/pages/sources/plex/PlexSourceForm.ts:147 +msgid "Allow friends to authenticate via Plex, even if you don't share any servers" +msgstr "Allow friends to authenticate via Plex, even if you don't share any servers" + #: src/pages/policies/hibp/HaveIBeenPwnedPolicyForm.ts:90 msgid "Allow up to N occurrences in the HIBP database." msgstr "Allow up to N occurrences in the HIBP database." @@ -156,7 +160,7 @@ msgstr "Allow users to use Applications based on properties, enforce Password Cr msgid "Allowed count" msgstr "Allowed count" -#: src/pages/sources/plex/PlexSourceForm.ts:141 +#: src/pages/sources/plex/PlexSourceForm.ts:152 msgid "Allowed servers" msgstr "Allowed servers" @@ -182,7 +186,7 @@ msgid "App" msgstr "App" #: src/elements/user/UserConsentList.ts:29 -#: src/pages/admin-overview/TopApplicationsTable.ts:42 +#: src/pages/admin-overview/TopApplicationsTable.ts:43 #: src/pages/applications/ApplicationListPage.ts:105 #: src/pages/providers/ProviderListPage.ts:54 msgid "Application" @@ -207,26 +211,10 @@ msgstr "Application's display Name." msgid "Applications" msgstr "Applications" -#: src/pages/admin-overview/AdminOverviewPage.ts:43 +#: src/pages/admin-overview/AdminOverviewPage.ts:105 msgid "Apps with most usage" msgstr "Apps with most usage" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:44 -msgid "" -"Are you sure you want to clear the flow cache?\n" -"This will cause all flows to be re-evaluated on their next usage." -msgstr "" -"Are you sure you want to clear the flow cache?\n" -"This will cause all flows to be re-evaluated on their next usage." - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:45 -msgid "" -"Are you sure you want to clear the policy cache?\n" -"This will cause all policies to be re-evaluated on their next usage." -msgstr "" -"Are you sure you want to clear the policy cache?\n" -"This will cause all policies to be re-evaluated on their next usage." - #: src/elements/forms/DeleteForm.ts:69 msgid "Are you sure you want to delete {0} {objName} ?" msgstr "Are you sure you want to delete {0} {objName} ?" @@ -291,7 +279,7 @@ msgid "Authentication" msgstr "Authentication" #: src/pages/sources/oauth/OAuthSourceForm.ts:212 -#: src/pages/sources/plex/PlexSourceForm.ts:171 +#: src/pages/sources/plex/PlexSourceForm.ts:182 #: src/pages/sources/saml/SAMLSourceForm.ts:245 msgid "Authentication flow" msgstr "Authentication flow" @@ -350,7 +338,7 @@ msgstr "Backup finished with errors." msgid "Backup finished with warnings." msgstr "Backup finished with warnings." -#: src/pages/admin-overview/AdminOverviewPage.ts:60 +#: src/pages/admin-overview/AdminOverviewPage.ts:84 msgid "Backup status" msgstr "Backup status" @@ -420,13 +408,13 @@ msgstr "Built-in" msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." -#: src/pages/admin-overview/AdminOverviewPage.ts:58 -msgid "Cached Flows" -msgstr "Cached Flows" +#: src/pages/admin-overview/graphs/FlowStatusCard.ts:54 +msgid "Cached flows" +msgstr "Cached flows" -#: src/pages/admin-overview/AdminOverviewPage.ts:56 -msgid "Cached Policies" -msgstr "Cached Policies" +#: src/pages/admin-overview/graphs/PolicyStatusCard.ts:59 +msgid "Cached policies" +msgstr "Cached policies" #: src/pages/sources/oauth/OAuthSourceViewPage.ts:80 msgid "Callback URL" @@ -539,19 +527,6 @@ msgstr "Checks if the request's user's password has been changed in the last x d msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength." msgstr "Checks the value from the policy request against several rules, mostly used to ensure password strength." -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:41 -msgid "Clear Flow cache" -msgstr "Clear Flow cache" - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:42 -msgid "Clear Policy cache" -msgstr "Clear Policy cache" - -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:36 -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:37 -msgid "Clear cache" -msgstr "Clear cache" - #: src/elements/forms/HorizontalFormElement.ts:82 msgid "Click to change value" msgstr "Click to change value" @@ -562,7 +537,7 @@ msgstr "Click to copy token" #: src/pages/providers/oauth2/OAuth2ProviderForm.ts:107 #: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts:99 -#: src/pages/sources/plex/PlexSourceForm.ts:135 +#: src/pages/sources/plex/PlexSourceForm.ts:138 msgid "Client ID" msgstr "Client ID" @@ -1154,10 +1129,10 @@ msgid "Enable this if you don't want to use this provider as a proxy, and want t msgstr "Enable this if you don't want to use this provider as a proxy, and want to use it with Traefik's forwardAuth or nginx's auth_request." #: src/pages/policies/BoundPoliciesList.ts:41 -#: src/pages/policies/PolicyBindingForm.ts:199 +#: src/pages/policies/PolicyBindingForm.ts:198 #: src/pages/sources/ldap/LDAPSourceForm.ts:69 #: src/pages/sources/oauth/OAuthSourceForm.ts:115 -#: src/pages/sources/plex/PlexSourceForm.ts:102 +#: src/pages/sources/plex/PlexSourceForm.ts:105 #: src/pages/sources/saml/SAMLSourceForm.ts:69 msgid "Enabled" msgstr "Enabled" @@ -1167,7 +1142,7 @@ msgid "Enrollment" msgstr "Enrollment" #: src/pages/sources/oauth/OAuthSourceForm.ts:233 -#: src/pages/sources/plex/PlexSourceForm.ts:192 +#: src/pages/sources/plex/PlexSourceForm.ts:203 #: src/pages/sources/saml/SAMLSourceForm.ts:266 #: src/pages/stages/identification/IdentificationStageForm.ts:106 msgid "Enrollment flow" @@ -1321,13 +1296,9 @@ msgstr "External host" msgid "Failed attempts before cancel" msgstr "Failed attempts before cancel" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:35 -msgid "Failed to delete flow cache" -msgstr "Failed to delete flow cache" - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:36 -msgid "Failed to delete policy cache" -msgstr "Failed to delete policy cache" +#: src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts:76 +msgid "Failed sources" +msgstr "Failed sources" #: src/elements/forms/DeleteForm.ts:46 msgid "Failed to delete {0}: {1}" @@ -1380,19 +1351,19 @@ msgid "Flow Overview" msgstr "Flow Overview" #: src/pages/sources/oauth/OAuthSourceForm.ts:208 -#: src/pages/sources/plex/PlexSourceForm.ts:167 +#: src/pages/sources/plex/PlexSourceForm.ts:178 #: src/pages/sources/saml/SAMLSourceForm.ts:220 msgid "Flow settings" msgstr "Flow settings" #: src/pages/sources/oauth/OAuthSourceForm.ts:230 -#: src/pages/sources/plex/PlexSourceForm.ts:189 +#: src/pages/sources/plex/PlexSourceForm.ts:200 #: src/pages/sources/saml/SAMLSourceForm.ts:263 msgid "Flow to use when authenticating existing users." msgstr "Flow to use when authenticating existing users." #: src/pages/sources/oauth/OAuthSourceForm.ts:251 -#: src/pages/sources/plex/PlexSourceForm.ts:210 +#: src/pages/sources/plex/PlexSourceForm.ts:221 #: src/pages/sources/saml/SAMLSourceForm.ts:284 msgid "Flow to use when enrolling new users." msgstr "Flow to use when enrolling new users." @@ -1423,6 +1394,7 @@ msgstr "Flow used when authorizing this provider." #: src/interfaces/AdminInterface.ts:82 #: src/interfaces/AdminInterface.ts:84 +#: src/pages/admin-overview/AdminOverviewPage.ts:61 #: src/pages/flows/FlowListPage.ts:28 #: src/pages/stages/StageListPage.ts:66 msgid "Flows" @@ -1456,7 +1428,7 @@ msgstr "Friendly Name" msgid "From address" msgstr "From address" -#: src/pages/admin-overview/AdminOverviewPage.ts:36 +#: src/pages/admin-overview/AdminOverviewPage.ts:50 msgid "General system status" msgstr "General system status" @@ -1479,8 +1451,8 @@ msgstr "Go to previous page" #: src/pages/events/RuleForm.ts:65 #: src/pages/groups/GroupListPage.ts:74 -#: src/pages/policies/PolicyBindingForm.ts:125 -#: src/pages/policies/PolicyBindingForm.ts:161 +#: src/pages/policies/PolicyBindingForm.ts:124 +#: src/pages/policies/PolicyBindingForm.ts:160 #: src/pages/providers/ldap/LDAPProviderForm.ts:77 msgid "Group" msgstr "Group" @@ -1526,6 +1498,14 @@ msgstr "HTTP-Basic Username Key" msgid "Health and Version" msgstr "Health and Version" +#: src/pages/admin-overview/graphs/OutpostStatusCard.ts:70 +msgid "Healthy outposts" +msgstr "Healthy outposts" + +#: src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts:75 +msgid "Healthy sources" +msgstr "Healthy sources" + #: src/pages/stages/prompt/PromptForm.ts:72 msgid "Hidden: Hidden field, can be used to insert data into form." msgstr "Hidden: Hidden field, can be used to insert data into form." @@ -1545,7 +1525,7 @@ msgstr "Hide service-accounts" #: src/pages/providers/saml/SAMLProviderForm.ts:177 #: src/pages/sources/ldap/LDAPSourceForm.ts:167 #: src/pages/sources/ldap/LDAPSourceForm.ts:193 -#: src/pages/sources/plex/PlexSourceForm.ts:154 +#: src/pages/sources/plex/PlexSourceForm.ts:165 #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:114 #: src/pages/stages/identification/IdentificationStageForm.ts:85 #: src/pages/stages/password/PasswordStageForm.ts:86 @@ -1692,9 +1672,9 @@ msgstr "LDAP (Technical preview)" msgid "LDAP DN under which bind requests and search requests can be made." msgstr "LDAP DN under which bind requests and search requests can be made." -#: src/pages/admin-overview/cards/LDAPSyncStatusCardContainer.ts:24 -msgid "LDAP Sync status {0}" -msgstr "LDAP Sync status {0}" +#: src/pages/admin-overview/AdminOverviewPage.ts:66 +msgid "LDAP Sync status" +msgstr "LDAP Sync status" #: src/pages/stages/prompt/PromptForm.ts:90 #: src/pages/stages/prompt/PromptListPage.ts:47 @@ -1719,7 +1699,6 @@ msgstr "Last run" msgid "Last seen: {0}" msgstr "Last seen: {0}" -#: src/pages/admin-overview/cards/LDAPSyncStatusCard.ts:25 #: src/pages/sources/ldap/LDAPSourceViewPage.ts:143 msgid "Last sync: {0}" msgstr "Last sync: {0}" @@ -1742,21 +1721,21 @@ msgid "Library" msgstr "Library" #: src/pages/sources/oauth/OAuthSourceForm.ts:128 -#: src/pages/sources/plex/PlexSourceForm.ts:115 +#: src/pages/sources/plex/PlexSourceForm.ts:118 msgid "Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses" msgstr "Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses" #: src/pages/sources/oauth/OAuthSourceForm.ts:134 -#: src/pages/sources/plex/PlexSourceForm.ts:121 +#: src/pages/sources/plex/PlexSourceForm.ts:124 msgid "Link to a user with identical username address. Can have security implications when a username is used with another source." msgstr "Link to a user with identical username address. Can have security implications when a username is used with another source." #: src/pages/sources/oauth/OAuthSourceForm.ts:125 -#: src/pages/sources/plex/PlexSourceForm.ts:112 +#: src/pages/sources/plex/PlexSourceForm.ts:115 msgid "Link users on unique identifier" msgstr "Link users on unique identifier" -#: src/pages/sources/plex/PlexSourceForm.ts:159 +#: src/pages/sources/plex/PlexSourceForm.ts:170 msgid "Load servers" msgstr "Load servers" @@ -1796,9 +1775,9 @@ msgstr "Loading" #: src/pages/outposts/OutpostForm.ts:108 #: src/pages/outposts/ServiceConnectionDockerForm.ts:86 #: src/pages/outposts/ServiceConnectionDockerForm.ts:102 -#: src/pages/policies/PolicyBindingForm.ts:157 -#: src/pages/policies/PolicyBindingForm.ts:173 -#: src/pages/policies/PolicyBindingForm.ts:189 +#: src/pages/policies/PolicyBindingForm.ts:156 +#: src/pages/policies/PolicyBindingForm.ts:172 +#: src/pages/policies/PolicyBindingForm.ts:188 #: src/pages/policies/PolicyTestForm.ts:71 #: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:88 #: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:108 @@ -1821,8 +1800,8 @@ msgstr "Loading" #: src/pages/sources/oauth/OAuthSourceForm.ts:200 #: src/pages/sources/oauth/OAuthSourceForm.ts:228 #: src/pages/sources/oauth/OAuthSourceForm.ts:249 -#: src/pages/sources/plex/PlexSourceForm.ts:187 -#: src/pages/sources/plex/PlexSourceForm.ts:208 +#: src/pages/sources/plex/PlexSourceForm.ts:198 +#: src/pages/sources/plex/PlexSourceForm.ts:219 #: src/pages/sources/saml/SAMLSourceForm.ts:126 #: src/pages/sources/saml/SAMLSourceForm.ts:240 #: src/pages/sources/saml/SAMLSourceForm.ts:261 @@ -1857,11 +1836,11 @@ msgstr "Login password is synced from LDAP into authentik automatically. Enable msgid "Login to continue to {0}." msgstr "Login to continue to {0}." -#: src/pages/admin-overview/TopApplicationsTable.ts:43 +#: src/pages/admin-overview/TopApplicationsTable.ts:44 msgid "Logins" msgstr "Logins" -#: src/pages/admin-overview/AdminOverviewPage.ts:40 +#: src/pages/admin-overview/AdminOverviewPage.ts:100 #: src/pages/applications/ApplicationViewPage.ts:128 msgid "Logins over the last 24 hours" msgstr "Logins over the last 24 hours" @@ -1993,7 +1972,7 @@ msgstr "Monitor" #: src/pages/sources/ldap/LDAPSourceViewPage.ts:64 #: src/pages/sources/oauth/OAuthSourceForm.ts:100 #: src/pages/sources/oauth/OAuthSourceViewPage.ts:64 -#: src/pages/sources/plex/PlexSourceForm.ts:87 +#: src/pages/sources/plex/PlexSourceForm.ts:90 #: src/pages/sources/plex/PlexSourceViewPage.ts:63 #: src/pages/sources/saml/SAMLSourceForm.ts:54 #: src/pages/sources/saml/SAMLSourceViewPage.ts:66 @@ -2080,10 +2059,6 @@ msgstr "No additional data available." msgid "No elements found." msgstr "No elements found." -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:23 -msgid "No flows cached." -msgstr "No flows cached." - #: src/elements/forms/ModalForm.ts:29 msgid "No form found" msgstr "No form found" @@ -2097,10 +2072,6 @@ msgstr "No matching events could be found." msgid "No policies are currently bound to this object." msgstr "No policies are currently bound to this object." -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:24 -msgid "No policies cached. Users may experience slow response times." -msgstr "No policies cached. Users may experience slow response times." - #: src/pages/users/UserListPage.ts:139 msgid "No recovery flow is configured." msgstr "No recovery flow is configured." @@ -2137,10 +2108,6 @@ msgstr "Not found" msgid "Not synced yet." msgstr "Not synced yet." -#: src/pages/admin-overview/cards/LDAPSyncStatusCard.ts:40 -msgid "Not synced." -msgstr "Not synced." - #: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts:58 #: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts:48 #: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts:45 @@ -2266,12 +2233,16 @@ msgstr "Optionally set the 'FriendlyName' value of the Assertion attribute." #: src/pages/flows/BoundStagesList.ts:38 #: src/pages/flows/StageBindingForm.ts:110 #: src/pages/policies/BoundPoliciesList.ts:42 -#: src/pages/policies/PolicyBindingForm.ts:204 +#: src/pages/policies/PolicyBindingForm.ts:203 #: src/pages/stages/prompt/PromptForm.ts:119 #: src/pages/stages/prompt/PromptListPage.ts:49 msgid "Order" msgstr "Order" +#: src/pages/admin-overview/graphs/OutpostStatusCard.ts:71 +msgid "Outdated outposts" +msgstr "Outdated outposts" + #: src/pages/outposts/OutpostListPage.ts:80 msgid "Outpost" msgstr "Outpost" @@ -2284,6 +2255,10 @@ msgstr "Outpost Deployment Info" msgid "Outpost Service-connection" msgstr "Outpost Service-connection" +#: src/pages/admin-overview/AdminOverviewPage.ts:71 +msgid "Outpost status" +msgstr "Outpost status" + #: src/interfaces/AdminInterface.ts:49 #: src/interfaces/AdminInterface.ts:51 #: src/pages/outposts/OutpostListPage.ts:29 @@ -2357,18 +2332,15 @@ msgid "Please enter your password" msgstr "Please enter your password" #: src/interfaces/AdminInterface.ts:74 +#: src/pages/admin-overview/AdminOverviewPage.ts:56 #: src/pages/flows/FlowListPage.ts:50 #: src/pages/policies/PolicyListPage.ts:38 msgid "Policies" msgstr "Policies" -#: src/pages/admin-overview/cards/PolicyUnboundStatusCard.ts:25 -msgid "Policies without binding exist." -msgstr "Policies without binding exist." - -#: src/pages/policies/PolicyBindingForm.ts:108 -#: src/pages/policies/PolicyBindingForm.ts:117 -#: src/pages/policies/PolicyBindingForm.ts:148 +#: src/pages/policies/PolicyBindingForm.ts:107 +#: src/pages/policies/PolicyBindingForm.ts:116 +#: src/pages/policies/PolicyBindingForm.ts:147 #: src/pages/policies/PolicyListPage.ts:108 msgid "Policy" msgstr "Policy" @@ -2490,7 +2462,7 @@ msgstr "Property mappings used to user creation." #: src/pages/providers/proxy/ProxyProviderForm.ts:123 #: src/pages/providers/saml/SAMLProviderForm.ts:78 #: src/pages/sources/oauth/OAuthSourceForm.ts:144 -#: src/pages/sources/plex/PlexSourceForm.ts:131 +#: src/pages/sources/plex/PlexSourceForm.ts:134 #: src/pages/sources/saml/SAMLSourceForm.ts:76 msgid "Protocol settings" msgstr "Protocol settings" @@ -2523,10 +2495,6 @@ msgstr "Provider type" msgid "Providers" msgstr "Providers" -#: src/pages/admin-overview/AdminOverviewPage.ts:46 -msgid "Providers without application" -msgstr "Providers without application" - #: src/pages/outposts/OutpostForm.ts:57 msgid "Proxy" msgstr "Proxy" @@ -2801,7 +2769,7 @@ msgstr "Select users to add" msgid "Select which scopes can be used by the client. The client stil has to specify the scope to access the data." msgstr "Select which scopes can be used by the client. The client stil has to specify the scope to access the data." -#: src/pages/sources/plex/PlexSourceForm.ts:153 +#: src/pages/sources/plex/PlexSourceForm.ts:164 msgid "Select which server a user has to be a member of to be allowed to authenticate." msgstr "Select which server a user has to be a member of to be allowed to authenticate." @@ -2941,7 +2909,7 @@ msgstr "Skip path regex" #: src/pages/flows/FlowForm.ts:94 #: src/pages/sources/ldap/LDAPSourceForm.ts:60 #: src/pages/sources/oauth/OAuthSourceForm.ts:106 -#: src/pages/sources/plex/PlexSourceForm.ts:93 +#: src/pages/sources/plex/PlexSourceForm.ts:96 #: src/pages/sources/saml/SAMLSourceForm.ts:60 msgid "Slug" msgstr "Slug" @@ -3083,14 +3051,6 @@ msgstr "Subject-alt name" msgid "Successful" msgstr "Successful" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:34 -msgid "Successfully cleared flow cache" -msgstr "Successfully cleared flow cache" - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:35 -msgid "Successfully cleared policy cache" -msgstr "Successfully cleared policy cache" - #: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts:63 msgid "Successfully copied TOTP Config." msgstr "Successfully copied TOTP Config." @@ -3162,7 +3122,7 @@ msgstr "Successfully created service-connection." #: src/pages/sources/ldap/LDAPSourceForm.ts:47 #: src/pages/sources/oauth/OAuthSourceForm.ts:51 -#: src/pages/sources/plex/PlexSourceForm.ts:60 +#: src/pages/sources/plex/PlexSourceForm.ts:63 #: src/pages/sources/saml/SAMLSourceForm.ts:47 msgid "Successfully created source." msgstr "Successfully created source." @@ -3300,7 +3260,7 @@ msgstr "Successfully updated service-connection." #: src/pages/sources/ldap/LDAPSourceForm.ts:44 #: src/pages/sources/oauth/OAuthSourceForm.ts:48 -#: src/pages/sources/plex/PlexSourceForm.ts:57 +#: src/pages/sources/plex/PlexSourceForm.ts:60 #: src/pages/sources/saml/SAMLSourceForm.ts:44 msgid "Successfully updated source." msgstr "Successfully updated source." @@ -3357,10 +3317,6 @@ msgstr "Symbol charset" msgid "Sync" msgstr "Sync" -#: src/pages/admin-overview/cards/LDAPSyncStatusCard.ts:31 -msgid "Sync failed." -msgstr "Sync failed." - #: src/pages/sources/ldap/LDAPSourceForm.ts:94 msgid "Sync groups" msgstr "Sync groups" @@ -3373,7 +3329,7 @@ msgstr "Sync status" msgid "Sync users" msgstr "Sync users" -#: src/pages/admin-overview/AdminOverviewPage.ts:35 +#: src/pages/admin-overview/AdminOverviewPage.ts:49 msgid "System Overview" msgstr "System Overview" @@ -3497,7 +3453,7 @@ msgid "Time-based One-Time Passwords" msgstr "Time-based One-Time Passwords" #: src/pages/policies/BoundPoliciesList.ts:43 -#: src/pages/policies/PolicyBindingForm.ts:210 +#: src/pages/policies/PolicyBindingForm.ts:209 #: src/pages/stages/email/EmailStageForm.ts:101 msgid "Timeout" msgstr "Timeout" @@ -3539,6 +3495,14 @@ msgstr "Tokens" msgid "Tokens are used throughout authentik for Email validation stages, Recovery keys and API access." msgstr "Tokens are used throughout authentik for Email validation stages, Recovery keys and API access." +#: src/pages/admin-overview/graphs/FlowStatusCard.ts:53 +msgid "Total flows" +msgstr "Total flows" + +#: src/pages/admin-overview/graphs/PolicyStatusCard.ts:58 +msgid "Total policies" +msgstr "Total policies" + #: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts:80 msgid "Traditional authenticator" msgstr "Traditional authenticator" @@ -3595,7 +3559,7 @@ msgstr "URL used by authentik to retrieve tokens." msgid "URL used to request the initial token. This URL is only required for OAuth 1." msgstr "URL used to request the initial token. This URL is only required for OAuth 1." -#: src/pages/admin-overview/AdminOverviewPage.ts:48 +#: src/pages/admin-overview/graphs/PolicyStatusCard.ts:60 msgid "Unbound policies" msgstr "Unbound policies" @@ -3607,10 +3571,18 @@ msgstr "Unenrollment" msgid "Unhealthy" msgstr "Unhealthy" +#: src/pages/admin-overview/graphs/OutpostStatusCard.ts:72 +msgid "Unhealthy outposts" +msgstr "Unhealthy outposts" + #: src/pages/system-tasks/SystemTaskListPage.ts:70 msgid "Unknown" msgstr "Unknown" +#: src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts:77 +msgid "Unsynced sources" +msgstr "Unsynced sources" + #: src/pages/admin-overview/cards/VersionStatusCard.ts:32 msgid "Up-to-date!" msgstr "Up-to-date!" @@ -3780,12 +3752,12 @@ msgid "Use global settings" msgstr "Use global settings" #: src/pages/sources/oauth/OAuthSourceForm.ts:131 -#: src/pages/sources/plex/PlexSourceForm.ts:118 +#: src/pages/sources/plex/PlexSourceForm.ts:121 msgid "Use the user's email address, but deny enrollment when the email address already exists." msgstr "Use the user's email address, but deny enrollment when the email address already exists." #: src/pages/sources/oauth/OAuthSourceForm.ts:137 -#: src/pages/sources/plex/PlexSourceForm.ts:124 +#: src/pages/sources/plex/PlexSourceForm.ts:127 msgid "Use the user's username, but deny enrollment when the username already exists." msgstr "Use the user's username, but deny enrollment when the username already exists." @@ -3793,8 +3765,8 @@ msgstr "Use the user's username, but deny enrollment when the username already e #: src/elements/events/UserEvents.ts:36 #: src/pages/events/EventInfo.ts:83 #: src/pages/events/EventListPage.ts:44 -#: src/pages/policies/PolicyBindingForm.ts:133 -#: src/pages/policies/PolicyBindingForm.ts:177 +#: src/pages/policies/PolicyBindingForm.ts:132 +#: src/pages/policies/PolicyBindingForm.ts:176 #: src/pages/policies/PolicyTestForm.ts:61 #: src/pages/property-mappings/PropertyMappingTestForm.ts:51 #: src/pages/tokens/TokenListPage.ts:45 @@ -3830,7 +3802,7 @@ msgid "User fields" msgstr "User fields" #: src/pages/sources/oauth/OAuthSourceForm.ts:120 -#: src/pages/sources/plex/PlexSourceForm.ts:107 +#: src/pages/sources/plex/PlexSourceForm.ts:110 msgid "User matching mode" msgstr "User matching mode" @@ -3881,7 +3853,7 @@ msgid "Username: Same as Text input, but checks for and prevents duplicate usern msgstr "Username: Same as Text input, but checks for and prevents duplicate usernames." #: src/interfaces/AdminInterface.ts:100 -#: src/pages/admin-overview/AdminOverviewPage.ts:50 +#: src/pages/admin-overview/AdminOverviewPage.ts:88 #: src/pages/users/UserListPage.ts:33 msgid "Users" msgstr "Users" @@ -3930,7 +3902,7 @@ msgstr "Verification Certificate" msgid "Verify the user's email address by sending them a one-time-link. Can also be used for recovery to verify the user's authenticity." msgstr "Verify the user's email address by sending them a one-time-link. Can also be used for recovery to verify the user's authenticity." -#: src/pages/admin-overview/AdminOverviewPage.ts:52 +#: src/pages/admin-overview/AdminOverviewPage.ts:80 msgid "Version" msgstr "Version" @@ -4033,7 +4005,7 @@ msgstr "Whoops!" msgid "Windows" msgstr "Windows" -#: src/pages/admin-overview/AdminOverviewPage.ts:54 +#: src/pages/admin-overview/AdminOverviewPage.ts:92 msgid "Workers" msgstr "Workers" diff --git a/web/src/locales/pseudo-LOCALE.po b/web/src/locales/pseudo-LOCALE.po index 0a683a01f..9103f167f 100644 --- a/web/src/locales/pseudo-LOCALE.po +++ b/web/src/locales/pseudo-LOCALE.po @@ -144,6 +144,10 @@ msgstr "" msgid "Allow IDP-initiated logins" msgstr "" +#: src/pages/sources/plex/PlexSourceForm.ts:147 +msgid "Allow friends to authenticate via Plex, even if you don't share any servers" +msgstr "" + #: src/pages/policies/hibp/HaveIBeenPwnedPolicyForm.ts:90 msgid "Allow up to N occurrences in the HIBP database." msgstr "" @@ -156,7 +160,7 @@ msgstr "" msgid "Allowed count" msgstr "" -#: src/pages/sources/plex/PlexSourceForm.ts:141 +#: src/pages/sources/plex/PlexSourceForm.ts:152 msgid "Allowed servers" msgstr "" @@ -182,7 +186,7 @@ msgid "App" msgstr "" #: src/elements/user/UserConsentList.ts:29 -#: src/pages/admin-overview/TopApplicationsTable.ts:42 +#: src/pages/admin-overview/TopApplicationsTable.ts:43 #: src/pages/applications/ApplicationListPage.ts:105 #: src/pages/providers/ProviderListPage.ts:54 msgid "Application" @@ -207,22 +211,10 @@ msgstr "" msgid "Applications" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:43 +#: src/pages/admin-overview/AdminOverviewPage.ts:105 msgid "Apps with most usage" msgstr "" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:44 -msgid "" -"Are you sure you want to clear the flow cache?\n" -"This will cause all flows to be re-evaluated on their next usage." -msgstr "" - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:45 -msgid "" -"Are you sure you want to clear the policy cache?\n" -"This will cause all policies to be re-evaluated on their next usage." -msgstr "" - #: src/elements/forms/DeleteForm.ts:69 msgid "Are you sure you want to delete {0} {objName} ?" msgstr "" @@ -287,7 +279,7 @@ msgid "Authentication" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:212 -#: src/pages/sources/plex/PlexSourceForm.ts:171 +#: src/pages/sources/plex/PlexSourceForm.ts:182 #: src/pages/sources/saml/SAMLSourceForm.ts:245 msgid "Authentication flow" msgstr "" @@ -346,7 +338,7 @@ msgstr "" msgid "Backup finished with warnings." msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:60 +#: src/pages/admin-overview/AdminOverviewPage.ts:84 msgid "Backup status" msgstr "" @@ -416,12 +408,12 @@ msgstr "" msgid "CA which the endpoint's Certificate is verified against. Can be left empty for no validation." msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:58 -msgid "Cached Flows" +#: src/pages/admin-overview/graphs/FlowStatusCard.ts:54 +msgid "Cached flows" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:56 -msgid "Cached Policies" +#: src/pages/admin-overview/graphs/PolicyStatusCard.ts:59 +msgid "Cached policies" msgstr "" #: src/pages/sources/oauth/OAuthSourceViewPage.ts:80 @@ -533,19 +525,6 @@ msgstr "" msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength." msgstr "" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:41 -msgid "Clear Flow cache" -msgstr "" - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:42 -msgid "Clear Policy cache" -msgstr "" - -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:36 -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:37 -msgid "Clear cache" -msgstr "" - #: src/elements/forms/HorizontalFormElement.ts:82 msgid "Click to change value" msgstr "" @@ -556,7 +535,7 @@ msgstr "" #: src/pages/providers/oauth2/OAuth2ProviderForm.ts:107 #: src/pages/providers/oauth2/OAuth2ProviderViewPage.ts:99 -#: src/pages/sources/plex/PlexSourceForm.ts:135 +#: src/pages/sources/plex/PlexSourceForm.ts:138 msgid "Client ID" msgstr "" @@ -1146,10 +1125,10 @@ msgid "Enable this if you don't want to use this provider as a proxy, and want t msgstr "" #: src/pages/policies/BoundPoliciesList.ts:41 -#: src/pages/policies/PolicyBindingForm.ts:199 +#: src/pages/policies/PolicyBindingForm.ts:198 #: src/pages/sources/ldap/LDAPSourceForm.ts:69 #: src/pages/sources/oauth/OAuthSourceForm.ts:115 -#: src/pages/sources/plex/PlexSourceForm.ts:102 +#: src/pages/sources/plex/PlexSourceForm.ts:105 #: src/pages/sources/saml/SAMLSourceForm.ts:69 msgid "Enabled" msgstr "" @@ -1159,7 +1138,7 @@ msgid "Enrollment" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:233 -#: src/pages/sources/plex/PlexSourceForm.ts:192 +#: src/pages/sources/plex/PlexSourceForm.ts:203 #: src/pages/sources/saml/SAMLSourceForm.ts:266 #: src/pages/stages/identification/IdentificationStageForm.ts:106 msgid "Enrollment flow" @@ -1313,12 +1292,8 @@ msgstr "" msgid "Failed attempts before cancel" msgstr "" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:35 -msgid "Failed to delete flow cache" -msgstr "" - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:36 -msgid "Failed to delete policy cache" +#: src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts:76 +msgid "Failed sources" msgstr "" #: src/elements/forms/DeleteForm.ts:46 @@ -1372,19 +1347,19 @@ msgid "Flow Overview" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:208 -#: src/pages/sources/plex/PlexSourceForm.ts:167 +#: src/pages/sources/plex/PlexSourceForm.ts:178 #: src/pages/sources/saml/SAMLSourceForm.ts:220 msgid "Flow settings" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:230 -#: src/pages/sources/plex/PlexSourceForm.ts:189 +#: src/pages/sources/plex/PlexSourceForm.ts:200 #: src/pages/sources/saml/SAMLSourceForm.ts:263 msgid "Flow to use when authenticating existing users." msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:251 -#: src/pages/sources/plex/PlexSourceForm.ts:210 +#: src/pages/sources/plex/PlexSourceForm.ts:221 #: src/pages/sources/saml/SAMLSourceForm.ts:284 msgid "Flow to use when enrolling new users." msgstr "" @@ -1415,6 +1390,7 @@ msgstr "" #: src/interfaces/AdminInterface.ts:82 #: src/interfaces/AdminInterface.ts:84 +#: src/pages/admin-overview/AdminOverviewPage.ts:61 #: src/pages/flows/FlowListPage.ts:28 #: src/pages/stages/StageListPage.ts:66 msgid "Flows" @@ -1448,7 +1424,7 @@ msgstr "" msgid "From address" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:36 +#: src/pages/admin-overview/AdminOverviewPage.ts:50 msgid "General system status" msgstr "" @@ -1471,8 +1447,8 @@ msgstr "" #: src/pages/events/RuleForm.ts:65 #: src/pages/groups/GroupListPage.ts:74 -#: src/pages/policies/PolicyBindingForm.ts:125 -#: src/pages/policies/PolicyBindingForm.ts:161 +#: src/pages/policies/PolicyBindingForm.ts:124 +#: src/pages/policies/PolicyBindingForm.ts:160 #: src/pages/providers/ldap/LDAPProviderForm.ts:77 msgid "Group" msgstr "" @@ -1518,6 +1494,14 @@ msgstr "" msgid "Health and Version" msgstr "" +#: src/pages/admin-overview/graphs/OutpostStatusCard.ts:70 +msgid "Healthy outposts" +msgstr "" + +#: src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts:75 +msgid "Healthy sources" +msgstr "" + #: src/pages/stages/prompt/PromptForm.ts:72 msgid "Hidden: Hidden field, can be used to insert data into form." msgstr "" @@ -1537,7 +1521,7 @@ msgstr "" #: src/pages/providers/saml/SAMLProviderForm.ts:177 #: src/pages/sources/ldap/LDAPSourceForm.ts:167 #: src/pages/sources/ldap/LDAPSourceForm.ts:193 -#: src/pages/sources/plex/PlexSourceForm.ts:154 +#: src/pages/sources/plex/PlexSourceForm.ts:165 #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts:114 #: src/pages/stages/identification/IdentificationStageForm.ts:85 #: src/pages/stages/password/PasswordStageForm.ts:86 @@ -1684,8 +1668,8 @@ msgstr "" msgid "LDAP DN under which bind requests and search requests can be made." msgstr "" -#: src/pages/admin-overview/cards/LDAPSyncStatusCardContainer.ts:24 -msgid "LDAP Sync status {0}" +#: src/pages/admin-overview/AdminOverviewPage.ts:66 +msgid "LDAP Sync status" msgstr "" #: src/pages/stages/prompt/PromptForm.ts:90 @@ -1711,7 +1695,6 @@ msgstr "" msgid "Last seen: {0}" msgstr "" -#: src/pages/admin-overview/cards/LDAPSyncStatusCard.ts:25 #: src/pages/sources/ldap/LDAPSourceViewPage.ts:143 msgid "Last sync: {0}" msgstr "" @@ -1734,21 +1717,21 @@ msgid "Library" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:128 -#: src/pages/sources/plex/PlexSourceForm.ts:115 +#: src/pages/sources/plex/PlexSourceForm.ts:118 msgid "Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:134 -#: src/pages/sources/plex/PlexSourceForm.ts:121 +#: src/pages/sources/plex/PlexSourceForm.ts:124 msgid "Link to a user with identical username address. Can have security implications when a username is used with another source." msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:125 -#: src/pages/sources/plex/PlexSourceForm.ts:112 +#: src/pages/sources/plex/PlexSourceForm.ts:115 msgid "Link users on unique identifier" msgstr "" -#: src/pages/sources/plex/PlexSourceForm.ts:159 +#: src/pages/sources/plex/PlexSourceForm.ts:170 msgid "Load servers" msgstr "" @@ -1788,9 +1771,9 @@ msgstr "" #: src/pages/outposts/OutpostForm.ts:108 #: src/pages/outposts/ServiceConnectionDockerForm.ts:86 #: src/pages/outposts/ServiceConnectionDockerForm.ts:102 -#: src/pages/policies/PolicyBindingForm.ts:157 -#: src/pages/policies/PolicyBindingForm.ts:173 -#: src/pages/policies/PolicyBindingForm.ts:189 +#: src/pages/policies/PolicyBindingForm.ts:156 +#: src/pages/policies/PolicyBindingForm.ts:172 +#: src/pages/policies/PolicyBindingForm.ts:188 #: src/pages/policies/PolicyTestForm.ts:71 #: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:88 #: src/pages/policies/event_matcher/EventMatcherPolicyForm.ts:108 @@ -1813,8 +1796,8 @@ msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:200 #: src/pages/sources/oauth/OAuthSourceForm.ts:228 #: src/pages/sources/oauth/OAuthSourceForm.ts:249 -#: src/pages/sources/plex/PlexSourceForm.ts:187 -#: src/pages/sources/plex/PlexSourceForm.ts:208 +#: src/pages/sources/plex/PlexSourceForm.ts:198 +#: src/pages/sources/plex/PlexSourceForm.ts:219 #: src/pages/sources/saml/SAMLSourceForm.ts:126 #: src/pages/sources/saml/SAMLSourceForm.ts:240 #: src/pages/sources/saml/SAMLSourceForm.ts:261 @@ -1849,11 +1832,11 @@ msgstr "" msgid "Login to continue to {0}." msgstr "" -#: src/pages/admin-overview/TopApplicationsTable.ts:43 +#: src/pages/admin-overview/TopApplicationsTable.ts:44 msgid "Logins" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:40 +#: src/pages/admin-overview/AdminOverviewPage.ts:100 #: src/pages/applications/ApplicationViewPage.ts:128 msgid "Logins over the last 24 hours" msgstr "" @@ -1985,7 +1968,7 @@ msgstr "" #: src/pages/sources/ldap/LDAPSourceViewPage.ts:64 #: src/pages/sources/oauth/OAuthSourceForm.ts:100 #: src/pages/sources/oauth/OAuthSourceViewPage.ts:64 -#: src/pages/sources/plex/PlexSourceForm.ts:87 +#: src/pages/sources/plex/PlexSourceForm.ts:90 #: src/pages/sources/plex/PlexSourceViewPage.ts:63 #: src/pages/sources/saml/SAMLSourceForm.ts:54 #: src/pages/sources/saml/SAMLSourceViewPage.ts:66 @@ -2072,10 +2055,6 @@ msgstr "" msgid "No elements found." msgstr "" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:23 -msgid "No flows cached." -msgstr "" - #: src/elements/forms/ModalForm.ts:29 msgid "No form found" msgstr "" @@ -2089,10 +2068,6 @@ msgstr "" msgid "No policies are currently bound to this object." msgstr "" -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:24 -msgid "No policies cached. Users may experience slow response times." -msgstr "" - #: src/pages/users/UserListPage.ts:139 msgid "No recovery flow is configured." msgstr "" @@ -2129,10 +2104,6 @@ msgstr "" msgid "Not synced yet." msgstr "" -#: src/pages/admin-overview/cards/LDAPSyncStatusCard.ts:40 -msgid "Not synced." -msgstr "" - #: src/flows/stages/authenticator_static/AuthenticatorStaticStage.ts:58 #: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts:48 #: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts:45 @@ -2258,12 +2229,16 @@ msgstr "" #: src/pages/flows/BoundStagesList.ts:38 #: src/pages/flows/StageBindingForm.ts:110 #: src/pages/policies/BoundPoliciesList.ts:42 -#: src/pages/policies/PolicyBindingForm.ts:204 +#: src/pages/policies/PolicyBindingForm.ts:203 #: src/pages/stages/prompt/PromptForm.ts:119 #: src/pages/stages/prompt/PromptListPage.ts:49 msgid "Order" msgstr "" +#: src/pages/admin-overview/graphs/OutpostStatusCard.ts:71 +msgid "Outdated outposts" +msgstr "" + #: src/pages/outposts/OutpostListPage.ts:80 msgid "Outpost" msgstr "" @@ -2276,6 +2251,10 @@ msgstr "" msgid "Outpost Service-connection" msgstr "" +#: src/pages/admin-overview/AdminOverviewPage.ts:71 +msgid "Outpost status" +msgstr "" + #: src/interfaces/AdminInterface.ts:49 #: src/interfaces/AdminInterface.ts:51 #: src/pages/outposts/OutpostListPage.ts:29 @@ -2349,18 +2328,15 @@ msgid "Please enter your password" msgstr "" #: src/interfaces/AdminInterface.ts:74 +#: src/pages/admin-overview/AdminOverviewPage.ts:56 #: src/pages/flows/FlowListPage.ts:50 #: src/pages/policies/PolicyListPage.ts:38 msgid "Policies" msgstr "" -#: src/pages/admin-overview/cards/PolicyUnboundStatusCard.ts:25 -msgid "Policies without binding exist." -msgstr "" - -#: src/pages/policies/PolicyBindingForm.ts:108 -#: src/pages/policies/PolicyBindingForm.ts:117 -#: src/pages/policies/PolicyBindingForm.ts:148 +#: src/pages/policies/PolicyBindingForm.ts:107 +#: src/pages/policies/PolicyBindingForm.ts:116 +#: src/pages/policies/PolicyBindingForm.ts:147 #: src/pages/policies/PolicyListPage.ts:108 msgid "Policy" msgstr "" @@ -2482,7 +2458,7 @@ msgstr "" #: src/pages/providers/proxy/ProxyProviderForm.ts:123 #: src/pages/providers/saml/SAMLProviderForm.ts:78 #: src/pages/sources/oauth/OAuthSourceForm.ts:144 -#: src/pages/sources/plex/PlexSourceForm.ts:131 +#: src/pages/sources/plex/PlexSourceForm.ts:134 #: src/pages/sources/saml/SAMLSourceForm.ts:76 msgid "Protocol settings" msgstr "" @@ -2515,10 +2491,6 @@ msgstr "" msgid "Providers" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:46 -msgid "Providers without application" -msgstr "" - #: src/pages/outposts/OutpostForm.ts:57 msgid "Proxy" msgstr "" @@ -2793,7 +2765,7 @@ msgstr "" msgid "Select which scopes can be used by the client. The client stil has to specify the scope to access the data." msgstr "" -#: src/pages/sources/plex/PlexSourceForm.ts:153 +#: src/pages/sources/plex/PlexSourceForm.ts:164 msgid "Select which server a user has to be a member of to be allowed to authenticate." msgstr "" @@ -2933,7 +2905,7 @@ msgstr "" #: src/pages/flows/FlowForm.ts:94 #: src/pages/sources/ldap/LDAPSourceForm.ts:60 #: src/pages/sources/oauth/OAuthSourceForm.ts:106 -#: src/pages/sources/plex/PlexSourceForm.ts:93 +#: src/pages/sources/plex/PlexSourceForm.ts:96 #: src/pages/sources/saml/SAMLSourceForm.ts:60 msgid "Slug" msgstr "" @@ -3075,14 +3047,6 @@ msgstr "" msgid "Successful" msgstr "" -#: src/pages/admin-overview/cards/FlowCacheStatusCard.ts:34 -msgid "Successfully cleared flow cache" -msgstr "" - -#: src/pages/admin-overview/cards/PolicyCacheStatusCard.ts:35 -msgid "Successfully cleared policy cache" -msgstr "" - #: src/flows/stages/authenticator_totp/AuthenticatorTOTPStage.ts:63 msgid "Successfully copied TOTP Config." msgstr "" @@ -3154,7 +3118,7 @@ msgstr "" #: src/pages/sources/ldap/LDAPSourceForm.ts:47 #: src/pages/sources/oauth/OAuthSourceForm.ts:51 -#: src/pages/sources/plex/PlexSourceForm.ts:60 +#: src/pages/sources/plex/PlexSourceForm.ts:63 #: src/pages/sources/saml/SAMLSourceForm.ts:47 msgid "Successfully created source." msgstr "" @@ -3292,7 +3256,7 @@ msgstr "" #: src/pages/sources/ldap/LDAPSourceForm.ts:44 #: src/pages/sources/oauth/OAuthSourceForm.ts:48 -#: src/pages/sources/plex/PlexSourceForm.ts:57 +#: src/pages/sources/plex/PlexSourceForm.ts:60 #: src/pages/sources/saml/SAMLSourceForm.ts:44 msgid "Successfully updated source." msgstr "" @@ -3349,10 +3313,6 @@ msgstr "" msgid "Sync" msgstr "" -#: src/pages/admin-overview/cards/LDAPSyncStatusCard.ts:31 -msgid "Sync failed." -msgstr "" - #: src/pages/sources/ldap/LDAPSourceForm.ts:94 msgid "Sync groups" msgstr "" @@ -3365,7 +3325,7 @@ msgstr "" msgid "Sync users" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:35 +#: src/pages/admin-overview/AdminOverviewPage.ts:49 msgid "System Overview" msgstr "" @@ -3485,7 +3445,7 @@ msgid "Time-based One-Time Passwords" msgstr "" #: src/pages/policies/BoundPoliciesList.ts:43 -#: src/pages/policies/PolicyBindingForm.ts:210 +#: src/pages/policies/PolicyBindingForm.ts:209 #: src/pages/stages/email/EmailStageForm.ts:101 msgid "Timeout" msgstr "" @@ -3527,6 +3487,14 @@ msgstr "" msgid "Tokens are used throughout authentik for Email validation stages, Recovery keys and API access." msgstr "" +#: src/pages/admin-overview/graphs/FlowStatusCard.ts:53 +msgid "Total flows" +msgstr "" + +#: src/pages/admin-overview/graphs/PolicyStatusCard.ts:58 +msgid "Total policies" +msgstr "" + #: src/flows/stages/authenticator_validate/AuthenticatorValidateStage.ts:80 msgid "Traditional authenticator" msgstr "" @@ -3583,7 +3551,7 @@ msgstr "" msgid "URL used to request the initial token. This URL is only required for OAuth 1." msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:48 +#: src/pages/admin-overview/graphs/PolicyStatusCard.ts:60 msgid "Unbound policies" msgstr "" @@ -3595,10 +3563,18 @@ msgstr "" msgid "Unhealthy" msgstr "" +#: src/pages/admin-overview/graphs/OutpostStatusCard.ts:72 +msgid "Unhealthy outposts" +msgstr "" + #: src/pages/system-tasks/SystemTaskListPage.ts:70 msgid "Unknown" msgstr "" +#: src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts:77 +msgid "Unsynced sources" +msgstr "" + #: src/pages/admin-overview/cards/VersionStatusCard.ts:32 msgid "Up-to-date!" msgstr "" @@ -3768,12 +3744,12 @@ msgid "Use global settings" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:131 -#: src/pages/sources/plex/PlexSourceForm.ts:118 +#: src/pages/sources/plex/PlexSourceForm.ts:121 msgid "Use the user's email address, but deny enrollment when the email address already exists." msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:137 -#: src/pages/sources/plex/PlexSourceForm.ts:124 +#: src/pages/sources/plex/PlexSourceForm.ts:127 msgid "Use the user's username, but deny enrollment when the username already exists." msgstr "" @@ -3781,8 +3757,8 @@ msgstr "" #: src/elements/events/UserEvents.ts:36 #: src/pages/events/EventInfo.ts:83 #: src/pages/events/EventListPage.ts:44 -#: src/pages/policies/PolicyBindingForm.ts:133 -#: src/pages/policies/PolicyBindingForm.ts:177 +#: src/pages/policies/PolicyBindingForm.ts:132 +#: src/pages/policies/PolicyBindingForm.ts:176 #: src/pages/policies/PolicyTestForm.ts:61 #: src/pages/property-mappings/PropertyMappingTestForm.ts:51 #: src/pages/tokens/TokenListPage.ts:45 @@ -3818,7 +3794,7 @@ msgid "User fields" msgstr "" #: src/pages/sources/oauth/OAuthSourceForm.ts:120 -#: src/pages/sources/plex/PlexSourceForm.ts:107 +#: src/pages/sources/plex/PlexSourceForm.ts:110 msgid "User matching mode" msgstr "" @@ -3869,7 +3845,7 @@ msgid "Username: Same as Text input, but checks for and prevents duplicate usern msgstr "" #: src/interfaces/AdminInterface.ts:100 -#: src/pages/admin-overview/AdminOverviewPage.ts:50 +#: src/pages/admin-overview/AdminOverviewPage.ts:88 #: src/pages/users/UserListPage.ts:33 msgid "Users" msgstr "" @@ -3918,7 +3894,7 @@ msgstr "" msgid "Verify the user's email address by sending them a one-time-link. Can also be used for recovery to verify the user's authenticity." msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:52 +#: src/pages/admin-overview/AdminOverviewPage.ts:80 msgid "Version" msgstr "" @@ -4021,7 +3997,7 @@ msgstr "" msgid "Windows" msgstr "" -#: src/pages/admin-overview/AdminOverviewPage.ts:54 +#: src/pages/admin-overview/AdminOverviewPage.ts:92 msgid "Workers" msgstr "" diff --git a/web/src/pages/admin-overview/AdminOverviewPage.ts b/web/src/pages/admin-overview/AdminOverviewPage.ts index a2c59efb7..734a78cb6 100644 --- a/web/src/pages/admin-overview/AdminOverviewPage.ts +++ b/web/src/pages/admin-overview/AdminOverviewPage.ts @@ -1,5 +1,5 @@ import { t } from "@lingui/macro"; -import { CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element"; +import { css, CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element"; import "../../elements/charts/AdminLoginsChart"; import "../../elements/cards/AggregatePromiseCard"; @@ -7,18 +7,19 @@ import "./TopApplicationsTable"; import "./cards/AdminStatusCard"; import "./cards/BackupStatusCard"; -import "./cards/FlowCacheStatusCard"; -import "./cards/LDAPSyncStatusCardContainer"; -import "./cards/PolicyCacheStatusCard"; -import "./cards/PolicyUnboundStatusCard"; import "./cards/ProviderStatusCard"; import "./cards/UserCountStatusCard"; import "./cards/VersionStatusCard"; import "./cards/WorkerStatusCard"; +import "./graphs/FlowStatusCard"; +import "./graphs/LDAPSyncStatusCard"; +import "./graphs/OutpostStatusCard"; +import "./graphs/PolicyStatusCard"; + import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css"; -import PFGallery from "@patternfly/patternfly/layouts/Gallery/gallery.css"; +import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; import AKGlobal from "../../authentik.css"; import "../../elements/PageHeader"; @@ -26,7 +27,21 @@ import "../../elements/PageHeader"; export class AdminOverviewPage extends LitElement { static get styles(): CSSResult[] { - return [PFGallery, PFPage, PFContent, AKGlobal]; + return [PFGrid, PFPage, PFContent, AKGlobal, css` + .row-divider { + margin-top: -4px; + margin-bottom: -4px; + } + .graph-container { + height: 20em; + } + .big-graph-container { + height: 35em; + } + .card-container { + height: 10em; + } + `]; } render(): TemplateResult { @@ -37,31 +52,62 @@ export class AdminOverviewPage extends LitElement { description=${t`General system status`}>
-
`; } diff --git a/web/src/pages/admin-overview/TopApplicationsTable.ts b/web/src/pages/admin-overview/TopApplicationsTable.ts index 3793147e1..9c42c8f9b 100644 --- a/web/src/pages/admin-overview/TopApplicationsTable.ts +++ b/web/src/pages/admin-overview/TopApplicationsTable.ts @@ -20,6 +20,7 @@ export class TopApplicationsTable extends LitElement { firstUpdated(): void { new EventsApi(DEFAULT_CONFIG).eventsEventsTopPerUser({ action: "authorize_application", + topN: 11, }).then((events) => { this.topN = events; }); diff --git a/web/src/pages/admin-overview/cards/FlowCacheStatusCard.ts b/web/src/pages/admin-overview/cards/FlowCacheStatusCard.ts deleted file mode 100644 index b9dfecd37..000000000 --- a/web/src/pages/admin-overview/cards/FlowCacheStatusCard.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { t } from "@lingui/macro"; -import { customElement, html, TemplateResult } from "lit-element"; -import { AdminStatus, AdminStatusCard } from "./AdminStatusCard"; -import { FlowsApi } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../../api/Config"; -import "../../../elements/forms/ConfirmationForm"; - -@customElement("ak-admin-status-card-flow-cache") -export class FlowCacheStatusCard extends AdminStatusCard { - - getPrimaryValue(): Promise { - return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheInfo().then((value) => { - return value.count || 0; - }); - } - - getStatus(value: number): Promise { - if (value < 1) { - return Promise.resolve({ - icon: "fa fa-exclamation-triangle pf-m-warning", - message: t`No flows cached.`, - }); - } else { - return Promise.resolve({ - icon: "fa fa-check-circle pf-m-success" - }); - } - } - - renderHeaderLink(): TemplateResult { - return html` { - return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheClear(); - }}> - - ${t`Clear Flow cache`} - -

- ${t`Are you sure you want to clear the flow cache? - This will cause all flows to be re-evaluated on their next usage.`} -

- - - -
-
`; - } - -} diff --git a/web/src/pages/admin-overview/cards/LDAPSyncStatusCard.ts b/web/src/pages/admin-overview/cards/LDAPSyncStatusCard.ts deleted file mode 100644 index 54073da9d..000000000 --- a/web/src/pages/admin-overview/cards/LDAPSyncStatusCard.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { t } from "@lingui/macro"; -import { customElement, html, property, TemplateResult } from "lit-element"; -import { AdminStatus, AdminStatusCard } from "./AdminStatusCard"; -import { SourcesApi, Task, TaskStatusEnum } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../../api/Config"; -import "../../../elements/forms/ConfirmationForm"; - -@customElement("ak-admin-status-card-ldap-sync") -export class LDAPSyncStatusCard extends AdminStatusCard { - - @property() - slug!: string; - - getPrimaryValue(): Promise { - return new SourcesApi(DEFAULT_CONFIG).sourcesLdapSyncStatus({ - slug: this.slug - }).then((value) => { - return value; - }).catch(() => { - return { status: TaskStatusEnum.Error } as Task; - }); - } - - renderValue(): TemplateResult { - return html`${t`Last sync: ${this.value?.taskFinishTimestamp?.toLocaleTimeString() || "-"}`}`; - } - - getStatus(value: Task): Promise { - if (value.status !== TaskStatusEnum.Successful) { - return Promise.resolve({ - icon: "fa fas fa-times-circle pf-m-danger", - message: t`Sync failed.`, - }); - } - const now = new Date().getTime(); - const maxDelta = 3600000; // 1 hour - if (!value || (now - value.taskFinishTimestamp.getTime()) > maxDelta) { - // No sync or last sync was over maxDelta ago - return Promise.resolve({ - icon: "fa fa-exclamation-triangle pf-m-warning", - message: t`Not synced.`, - }); - } else { - return Promise.resolve({ - icon: "fa fa-check-circle pf-m-success", - }); - } - } - - renderHeaderLink(): TemplateResult { - return html` - - `; - } - -} diff --git a/web/src/pages/admin-overview/cards/LDAPSyncStatusCardContainer.ts b/web/src/pages/admin-overview/cards/LDAPSyncStatusCardContainer.ts deleted file mode 100644 index 00adf63dc..000000000 --- a/web/src/pages/admin-overview/cards/LDAPSyncStatusCardContainer.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { SourcesApi } from "authentik-api"; -import { customElement, html, LitElement, TemplateResult } from "lit-element"; -import { until } from "lit-html/directives/until"; -import "./LDAPSyncStatusCard"; -import { t } from "@lingui/macro"; -import { DEFAULT_CONFIG } from "../../../api/Config"; - -@customElement("ak-admin-status-card-ldap-sync-container") -export class LDAPSyncStatusCardContainer extends LitElement { - - createRenderRoot(): Element | ShadowRoot { - return this; - } - - render(): TemplateResult { - return html` - ${until(new SourcesApi(DEFAULT_CONFIG).sourcesLdapList({}).then(sources => { - return sources.results.map(source => { - return html` - `; - }); - }))} - `; - } - -} diff --git a/web/src/pages/admin-overview/cards/PolicyCacheStatusCard.ts b/web/src/pages/admin-overview/cards/PolicyCacheStatusCard.ts deleted file mode 100644 index a8e06390f..000000000 --- a/web/src/pages/admin-overview/cards/PolicyCacheStatusCard.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { t } from "@lingui/macro"; -import { customElement } from "lit-element"; -import { TemplateResult, html } from "lit-html"; -import { AdminStatusCard, AdminStatus } from "./AdminStatusCard"; -import { PoliciesApi } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../../api/Config"; -import "../../../elements/forms/ConfirmationForm"; - -@customElement("ak-admin-status-card-policy-cache") -export class PolicyCacheStatusCard extends AdminStatusCard { - - getPrimaryValue(): Promise { - return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheInfo().then((value) => { - return value.count || 0; - }); - } - - getStatus(value: number): Promise { - if (value < 1) { - return Promise.resolve({ - icon: "fa fa-exclamation-triangle pf-m-warning", - message: t`No policies cached. Users may experience slow response times.`, - }); - } else { - return Promise.resolve({ - icon: "fa fa-check-circle pf-m-success" - }); - } - } - - renderHeaderLink(): TemplateResult { - return html` { - return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheClear(); - }}> - - ${t`Clear Policy cache`} - -

- ${t`Are you sure you want to clear the policy cache? - This will cause all policies to be re-evaluated on their next usage.`} -

- - - -
-
`; - } - -} diff --git a/web/src/pages/admin-overview/cards/PolicyUnboundStatusCard.ts b/web/src/pages/admin-overview/cards/PolicyUnboundStatusCard.ts deleted file mode 100644 index 155813070..000000000 --- a/web/src/pages/admin-overview/cards/PolicyUnboundStatusCard.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { t } from "@lingui/macro"; -import { customElement } from "lit-element"; -import { PoliciesApi } from "authentik-api"; -import { DEFAULT_CONFIG } from "../../../api/Config"; -import { AdminStatusCard, AdminStatus } from "./AdminStatusCard"; - -@customElement("ak-admin-status-card-policy-unbound") -export class PolicyUnboundStatusCard extends AdminStatusCard { - - getPrimaryValue(): Promise { - return new PoliciesApi(DEFAULT_CONFIG).policiesAllList({ - bindingsIsnull: "true", - promptstageIsnull: "true", - }).then((value) => { - return value.pagination.count; - }); - } - - getStatus(value: number): Promise { - if (value > 0) { - return Promise.resolve({ - icon: "fa fa-exclamation-triangle pf-m-warning", - message: t`Policies without binding exist.`, - }); - } else { - return Promise.resolve({ - icon: "fa fa-check-circle pf-m-success" - }); - } - } - -} diff --git a/web/src/pages/admin-overview/graphs/FlowStatusCard.ts b/web/src/pages/admin-overview/graphs/FlowStatusCard.ts new file mode 100644 index 000000000..8eb474da5 --- /dev/null +++ b/web/src/pages/admin-overview/graphs/FlowStatusCard.ts @@ -0,0 +1,67 @@ +import { t } from "@lingui/macro"; +import { customElement } from "lit-element"; +import { FlowsApi } from "authentik-api"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import "../../../elements/forms/ConfirmationForm"; +import { AKChart } from "../../../elements/charts/Chart"; +import { ChartData, ChartOptions } from "chart.js"; + +interface FlowMetrics { + count: number; + cached: number; +} + +@customElement("ak-admin-status-card-flow") +export class PolicyStatusCard extends AKChart { + + getChartType(): string { + return "doughnut"; + } + + getOptions(): ChartOptions { + return { + plugins: { + legend: { + display: false, + }, + }, + maintainAspectRatio: false, + }; + } + + async apiRequest(): Promise { + const api = new FlowsApi(DEFAULT_CONFIG); + const cached = (await api.flowsInstancesCacheInfo()).count || 0; + const count = (await api.flowsInstancesList({ + pageSize: 1 + })).pagination.count; + this.centerText = count.toString(); + return { + count: count - cached, + cached: cached, + }; + } + + getChartData(data: FlowMetrics): ChartData { + return { + labels: [ + t`Total flows`, + t`Cached flows`, + ], + datasets: [ + { + backgroundColor: [ + "#2b9af3", + "#3e8635", + ], + spanGaps: true, + data: [ + data.count, + data.cached, + ], + }, + ] + }; + } + +} diff --git a/web/src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts b/web/src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts new file mode 100644 index 000000000..712eedf4c --- /dev/null +++ b/web/src/pages/admin-overview/graphs/LDAPSyncStatusCard.ts @@ -0,0 +1,91 @@ +import { t } from "@lingui/macro"; +import { customElement } from "lit-element"; +import { SourcesApi, TaskStatusEnum } from "authentik-api"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import "../../../elements/forms/ConfirmationForm"; +import { AKChart } from "../../../elements/charts/Chart"; +import { ChartOptions, ChartData } from "chart.js"; + +interface LDAPSyncStats { + healthy: number; + failed: number; + unsynced: number; +} + +@customElement("ak-admin-status-card-ldap-sync") +export class LDAPSyncStatusCard extends AKChart { + + getChartType(): string { + return "doughnut"; + } + + getOptions(): ChartOptions { + return { + plugins: { + legend: { + display: false, + }, + }, + maintainAspectRatio: false, + }; + } + + async apiRequest(): Promise { + const api = new SourcesApi(DEFAULT_CONFIG); + const sources = await api.sourcesLdapList({}); + let healthy = 0; + let failed = 0; + let unsynced = 0; + await Promise.all(sources.results.map(async (element) => { + try { + const health = await api.sourcesLdapSyncStatus({ + slug: element.slug, + }); + if (health.status !== TaskStatusEnum.Successful) { + failed += 1; + } + const now = new Date().getTime(); + const maxDelta = 3600000; // 1 hour + if (!health || (now - health.taskFinishTimestamp.getTime()) > maxDelta) { + unsynced += 1; + } else { + healthy += 1; + } + } catch { + unsynced += 1; + } + })); + this.centerText = sources.pagination.count.toString(); + return { + healthy, + failed, + unsynced + }; + } + + getChartData(data: LDAPSyncStats): ChartData { + return { + labels: [ + t`Healthy sources`, + t`Failed sources`, + t`Unsynced sources`, + ], + datasets: [ + { + backgroundColor: [ + "#3e8635", + "#C9190B", + "#2b9af3", + ], + spanGaps: true, + data: [ + data.healthy, + data.failed, + data.unsynced + ], + }, + ] + }; + } + +} diff --git a/web/src/pages/admin-overview/graphs/OutpostStatusCard.ts b/web/src/pages/admin-overview/graphs/OutpostStatusCard.ts new file mode 100644 index 000000000..572775c64 --- /dev/null +++ b/web/src/pages/admin-overview/graphs/OutpostStatusCard.ts @@ -0,0 +1,87 @@ +import { t } from "@lingui/macro"; +import { customElement } from "lit-element"; +import { OutpostsApi } from "authentik-api"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import "../../../elements/forms/ConfirmationForm"; +import { AKChart } from "../../../elements/charts/Chart"; +import { ChartOptions, ChartData } from "chart.js"; + +interface OutpostStats { + healthy: number; + outdated: number; + unhealthy: number; +} + +@customElement("ak-admin-status-card-outpost") +export class OutpostStatusCard extends AKChart { + + getChartType(): string { + return "doughnut"; + } + + getOptions(): ChartOptions { + return { + plugins: { + legend: { + display: false, + }, + }, + maintainAspectRatio: false, + }; + } + + async apiRequest(): Promise { + const api = new OutpostsApi(DEFAULT_CONFIG); + const outposts = await api.outpostsInstancesList({}); + let healthy = 0; + let outdated = 0; + let unhealthy = 0; + await Promise.all(outposts.results.map(async (element) => { + const health = await api.outpostsOutpostsHealth({ + uuid: element.pk || "", + }); + if (health.length === 0) { + unhealthy += 1; + } + health.forEach(h => { + if (h.versionOutdated) { + outdated += 1; + } else { + healthy += 1; + } + }); + })); + this.centerText = outposts.pagination.count.toString(); + return { + healthy, + outdated, + unhealthy + }; + } + + getChartData(data: OutpostStats): ChartData { + return { + labels: [ + t`Healthy outposts`, + t`Outdated outposts`, + t`Unhealthy outposts`, + ], + datasets: [ + { + backgroundColor: [ + "#3e8635", + "#f0ab00", + "#C9190B", + ], + spanGaps: true, + data: [ + data.healthy, + data.outdated, + data.unhealthy + ], + }, + ] + }; + } + +} diff --git a/web/src/pages/admin-overview/graphs/PolicyStatusCard.ts b/web/src/pages/admin-overview/graphs/PolicyStatusCard.ts new file mode 100644 index 000000000..0952d4e04 --- /dev/null +++ b/web/src/pages/admin-overview/graphs/PolicyStatusCard.ts @@ -0,0 +1,76 @@ +import { t } from "@lingui/macro"; +import { customElement } from "lit-element"; +import { PoliciesApi } from "authentik-api"; +import { DEFAULT_CONFIG } from "../../../api/Config"; +import "../../../elements/forms/ConfirmationForm"; +import { AKChart } from "../../../elements/charts/Chart"; +import { ChartData, ChartOptions } from "chart.js"; + +interface PolicyMetrics { + count: number; + cached: number; + unbound: number; +} + +@customElement("ak-admin-status-card-policy") +export class PolicyStatusCard extends AKChart { + + getChartType(): string { + return "doughnut"; + } + + getOptions(): ChartOptions { + return { + plugins: { + legend: { + display: false, + }, + }, + maintainAspectRatio: false, + }; + } + + async apiRequest(): Promise { + const api = new PoliciesApi(DEFAULT_CONFIG); + const cached = (await api.policiesAllCacheInfo()).count || 0; + const count = (await api.policiesAllList({ + pageSize: 1 + })).pagination.count; + const unbound = (await api.policiesAllList({ + bindingsIsnull: "true", + promptstageIsnull: "true", + })).pagination.count; + this.centerText = count.toString(); + return { + count: count - cached - unbound, + cached: cached, + unbound: unbound, + }; + } + + getChartData(data: PolicyMetrics): ChartData { + return { + labels: [ + t`Total policies`, + t`Cached policies`, + t`Unbound policies`, + ], + datasets: [ + { + backgroundColor: [ + "#2b9af3", + "#3e8635", + "#f0ab00", + ], + spanGaps: true, + data: [ + data.count, + data.cached, + data.unbound + ], + }, + ] + }; + } + +} diff --git a/web/src/pages/policies/PolicyBindingForm.ts b/web/src/pages/policies/PolicyBindingForm.ts index 830d6449a..834ed74e8 100644 --- a/web/src/pages/policies/PolicyBindingForm.ts +++ b/web/src/pages/policies/PolicyBindingForm.ts @@ -105,7 +105,6 @@ export class PolicyBindingForm extends Form { } renderModeSelector(): TemplateResult { - console.log(this.policyOnly); if (this.policyOnly) { this.policyGroupUser = target.policy; return html`