diff --git a/web/.eslintrc.precommit.json b/web/.eslintrc.precommit.json index 92ae45402..1e2b810a1 100644 --- a/web/.eslintrc.precommit.json +++ b/web/.eslintrc.precommit.json @@ -23,6 +23,7 @@ "quotes": ["error", "double", { "avoidEscape": true }], "semi": ["error", "always"], "@typescript-eslint/ban-ts-comment": "off", - "sonarjs/cognitive-complexity": ["error", 9] + "sonarjs/cognitive-complexity": ["error", 9], + "sonarjs/no-nested-template-literals": "off" } } diff --git a/web/src/admin/admin-overview/cards/RecentEventsCard.ts b/web/src/admin/admin-overview/cards/RecentEventsCard.ts index e0b75d970..b02c992b2 100644 --- a/web/src/admin/admin-overview/cards/RecentEventsCard.ts +++ b/web/src/admin/admin-overview/cards/RecentEventsCard.ts @@ -1,7 +1,8 @@ import "@goauthentik/admin/events/EventInfo"; -import { ActionToLabel, EventGeo } from "@goauthentik/admin/events/utils"; +import { EventGeo } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; +import { actionToLabel } from "@goauthentik/common/labels"; import { truncate } from "@goauthentik/common/utils"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/Dropdown"; @@ -68,7 +69,7 @@ export class RecentEventsCard extends Table { row(item: EventWithContext): TemplateResult[] { return [ - html`
${ActionToLabel(item.action)}
+ html`
${actionToLabel(item.action)}
${item.app}`, item.user?.username ? html`
diff --git a/web/src/admin/applications/ApplicationListPage.ts b/web/src/admin/applications/ApplicationListPage.ts index 8d37e5d52..b29ac0df5 100644 --- a/web/src/admin/applications/ApplicationListPage.ts +++ b/web/src/admin/applications/ApplicationListPage.ts @@ -3,6 +3,7 @@ import "@goauthentik/admin/applications/wizard/ApplicationWizard"; import { PFSize } from "@goauthentik/app/elements/Spinner"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { uiConfig } from "@goauthentik/common/ui/config"; +import "@goauthentik/components/ak-app-icon"; import MDApplication from "@goauthentik/docs/core/applications.md"; import "@goauthentik/elements/Markdown"; import "@goauthentik/elements/buttons/SpinnerButton"; @@ -12,7 +13,6 @@ import { getURLParam } from "@goauthentik/elements/router/RouteMatch"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table"; import { TablePage } from "@goauthentik/elements/table/TablePage"; -import "@goauthentik/user/LibraryApplication/AppIcon"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg } from "@lit/localize"; diff --git a/web/src/admin/applications/ApplicationViewPage.ts b/web/src/admin/applications/ApplicationViewPage.ts index 56f9fcb64..1881c0f04 100644 --- a/web/src/admin/applications/ApplicationViewPage.ts +++ b/web/src/admin/applications/ApplicationViewPage.ts @@ -4,13 +4,13 @@ import "@goauthentik/admin/applications/ApplicationForm"; import "@goauthentik/admin/policies/BoundPoliciesList"; import { PFSize } from "@goauthentik/app/elements/Spinner"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import "@goauthentik/components/ak-app-icon"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/EmptyState"; import "@goauthentik/elements/PageHeader"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/events/ObjectChangelog"; -import "@goauthentik/user/LibraryApplication/AppIcon"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; diff --git a/web/src/admin/events/EventListPage.ts b/web/src/admin/events/EventListPage.ts index 83e11b9b9..38b310106 100644 --- a/web/src/admin/events/EventListPage.ts +++ b/web/src/admin/events/EventListPage.ts @@ -1,7 +1,8 @@ import "@goauthentik/admin/events/EventInfo"; -import { ActionToLabel, EventGeo } from "@goauthentik/admin/events/utils"; +import { EventGeo } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; +import { actionToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; import { TableColumn } from "@goauthentik/elements/table/Table"; @@ -56,7 +57,7 @@ export class EventListPage extends TablePage { row(item: EventWithContext): TemplateResult[] { return [ - html`
${ActionToLabel(item.action)}
+ html`
${actionToLabel(item.action)}
${item.app}`, item.user?.username ? html`
diff --git a/web/src/admin/events/EventViewPage.ts b/web/src/admin/events/EventViewPage.ts index 77479d215..ad23514eb 100644 --- a/web/src/admin/events/EventViewPage.ts +++ b/web/src/admin/events/EventViewPage.ts @@ -1,7 +1,8 @@ import "@goauthentik/admin/events/EventInfo"; -import { ActionToLabel, EventGeo } from "@goauthentik/admin/events/utils"; +import { EventGeo } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; +import { actionToLabel } from "@goauthentik/common/labels"; import { AKElement } from "@goauthentik/elements/Base"; import "@goauthentik/elements/PageHeader"; @@ -62,7 +63,7 @@ export class EventViewPage extends AKElement {
- ${ActionToLabel(this.event.action)} + ${actionToLabel(this.event.action)}
diff --git a/web/src/admin/events/RuleForm.ts b/web/src/admin/events/RuleForm.ts index d69a62035..b0d0c017c 100644 --- a/web/src/admin/events/RuleForm.ts +++ b/web/src/admin/events/RuleForm.ts @@ -1,5 +1,5 @@ -import { SeverityToLabel } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { severityToLabel } from "@goauthentik/common/labels"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/Radio"; @@ -125,16 +125,16 @@ export class RuleForm extends ModelForm { { row(item: NotificationRule): TemplateResult[] { return [ html`${item.name}`, - html`${SeverityToLabel(item.severity)}`, + html`${severityToLabel(item.severity)}`, html`${item.groupObj ? html`${item.groupObj.name}` : msg("None (rule disabled)")}`, diff --git a/web/src/admin/events/utils.ts b/web/src/admin/events/utils.ts index 5f5563ddd..d6aac8e3a 100644 --- a/web/src/admin/events/utils.ts +++ b/web/src/admin/events/utils.ts @@ -1,11 +1,8 @@ import { EventWithContext } from "@goauthentik/common/events"; import { KeyUnknown } from "@goauthentik/elements/forms/Form"; -import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; -import { EventActions, SeverityEnum } from "@goauthentik/api"; - export function EventGeo(event: EventWithContext): TemplateResult { let geo: KeyUnknown | undefined = undefined; if (Object.hasOwn(event.context, "geo")) { @@ -17,76 +14,3 @@ export function EventGeo(event: EventWithContext): TemplateResult { } return html``; } - -export function ActionToLabel(action?: EventActions): string { - if (!action) return ""; - switch (action) { - case EventActions.Login: - return msg("Login"); - case EventActions.LoginFailed: - return msg("Failed login"); - case EventActions.Logout: - return msg("Logout"); - case EventActions.UserWrite: - return msg("User was written to"); - case EventActions.SuspiciousRequest: - return msg("Suspicious request"); - case EventActions.PasswordSet: - return msg("Password set"); - case EventActions.SecretView: - return msg("Secret was viewed"); - case EventActions.SecretRotate: - return msg("Secret was rotated"); - case EventActions.InvitationUsed: - return msg("Invitation used"); - case EventActions.AuthorizeApplication: - return msg("Application authorized"); - case EventActions.SourceLinked: - return msg("Source linked"); - case EventActions.ImpersonationStarted: - return msg("Impersonation started"); - case EventActions.ImpersonationEnded: - return msg("Impersonation ended"); - case EventActions.FlowExecution: - return msg("Flow execution"); - case EventActions.PolicyExecution: - return msg("Policy execution"); - case EventActions.PolicyException: - return msg("Policy exception"); - case EventActions.PropertyMappingException: - return msg("Property Mapping exception"); - case EventActions.SystemTaskExecution: - return msg("System task execution"); - case EventActions.SystemTaskException: - return msg("System task exception"); - case EventActions.SystemException: - return msg("General system exception"); - case EventActions.ConfigurationError: - return msg("Configuration error"); - case EventActions.ModelCreated: - return msg("Model created"); - case EventActions.ModelUpdated: - return msg("Model updated"); - case EventActions.ModelDeleted: - return msg("Model deleted"); - case EventActions.EmailSent: - return msg("Email sent"); - case EventActions.UpdateAvailable: - return msg("Update available"); - default: - return action; - } -} - -export function SeverityToLabel(severity: SeverityEnum | null | undefined): string { - if (!severity) return msg("Unknown severity"); - switch (severity) { - case SeverityEnum.Alert: - return msg("Alert"); - case SeverityEnum.Notice: - return msg("Notice"); - case SeverityEnum.Warning: - return msg("Warning"); - } - return msg("Unknown severity"); -} diff --git a/web/src/admin/tokens/TokenListPage.ts b/web/src/admin/tokens/TokenListPage.ts index ad4eadc2c..ea6c979df 100644 --- a/web/src/admin/tokens/TokenListPage.ts +++ b/web/src/admin/tokens/TokenListPage.ts @@ -1,5 +1,6 @@ import "@goauthentik/admin/tokens/TokenForm"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { intentToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; import { PFColor } from "@goauthentik/elements/Label"; import "@goauthentik/elements/buttons/Dropdown"; @@ -17,21 +18,6 @@ import { customElement, property } from "lit/decorators.js"; import { CoreApi, IntentEnum, Token } from "@goauthentik/api"; -export function IntentToLabel(intent: IntentEnum): string { - switch (intent) { - case IntentEnum.Api: - return msg("API Access"); - case IntentEnum.AppPassword: - return msg("App password"); - case IntentEnum.Recovery: - return msg("Recovery"); - case IntentEnum.Verification: - return msg("Verification"); - case IntentEnum.UnknownDefaultOpenApi: - return msg("Unknown intent"); - } -} - @customElement("ak-token-list") export class TokenListPage extends TablePage { searchEnabled(): boolean { @@ -121,7 +107,7 @@ export class TokenListPage extends TablePage { ${item.expiring ? msg("Yes") : msg("No")} `, html`${item.expiring ? item.expires?.toLocaleString() : msg("-")}`, - html`${IntentToLabel(item.intent || IntentEnum.Api)}`, + html`${intentToLabel(item.intent ?? IntentEnum.Api)}`, html` ${!item.managed ? html` diff --git a/web/src/common/labels.ts b/web/src/common/labels.ts new file mode 100644 index 000000000..c352c27ae --- /dev/null +++ b/web/src/common/labels.ts @@ -0,0 +1,58 @@ +import { msg } from "@lit/localize"; + +import { EventActions, IntentEnum, SeverityEnum } from "@goauthentik/api"; + +/* Various tables in the API for which we need to supply labels */ + +export const intentEnumToLabel = new Map([ + [IntentEnum.Api, msg("API Access")], + [IntentEnum.AppPassword, msg("App password")], + [IntentEnum.Recovery, msg("Recovery")], + [IntentEnum.Verification, msg("Verification")], + [IntentEnum.UnknownDefaultOpenApi, msg("Unknown intent")], +]); + +export const intentToLabel = (intent: IntentEnum) => intentEnumToLabel.get(intent); + +export const eventActionToLabel = new Map([ + [EventActions.Login, msg("Login")], + [EventActions.LoginFailed, msg("Failed login")], + [EventActions.Logout, msg("Logout")], + [EventActions.UserWrite, msg("User was written to")], + [EventActions.SuspiciousRequest, msg("Suspicious request")], + [EventActions.PasswordSet, msg("Password set")], + [EventActions.SecretView, msg("Secret was viewed")], + [EventActions.SecretRotate, msg("Secret was rotated")], + [EventActions.InvitationUsed, msg("Invitation used")], + [EventActions.AuthorizeApplication, msg("Application authorized")], + [EventActions.SourceLinked, msg("Source linked")], + [EventActions.ImpersonationStarted, msg("Impersonation started")], + [EventActions.ImpersonationEnded, msg("Impersonation ended")], + [EventActions.FlowExecution, msg("Flow execution")], + // These are different: look closely. + [EventActions.PolicyExecution, msg("Policy execution")], + [EventActions.PolicyException, msg("Policy exception")], + [EventActions.PropertyMappingException, msg("Property Mapping exception")], + // These are different: look closely. + [EventActions.SystemTaskExecution, msg("System task execution")], + [EventActions.SystemTaskException, msg("System task exception")], + [EventActions.SystemException, msg("General system exception")], + [EventActions.ConfigurationError, msg("Configuration error")], + [EventActions.ModelCreated, msg("Model created")], + [EventActions.ModelUpdated, msg("Model updated")], + [EventActions.ModelDeleted, msg("Model deleted")], + [EventActions.EmailSent, msg("Email sent")], + [EventActions.UpdateAvailable, msg("Update available")], +]); + +export const actionToLabel = (action?: EventActions): string => + eventActionToLabel.get(action) ?? action ?? ""; + +export const severityEnumToLabel = new Map([ + [SeverityEnum.Alert, msg("Alert")], + [SeverityEnum.Notice, msg("Notice")], + [SeverityEnum.Warning, msg("Warning")], +]); + +export const severityToLabel = (severity: SeverityEnum | null | undefined) => + severityEnumToLabel.get(severity) ?? msg("Unknown severity"); diff --git a/web/src/user/LibraryApplication/AppIcon.ts b/web/src/components/ak-app-icon.ts similarity index 99% rename from web/src/user/LibraryApplication/AppIcon.ts rename to web/src/components/ak-app-icon.ts index fdefcf65a..5af288ad8 100644 --- a/web/src/user/LibraryApplication/AppIcon.ts +++ b/web/src/components/ak-app-icon.ts @@ -81,3 +81,5 @@ export class AppIcon extends AKElement { return html`${this.app?.name.charAt(0).toUpperCase()}`; } } + +export default AppIcon; diff --git a/web/src/elements/events/UserEvents.ts b/web/src/elements/events/UserEvents.ts index e8107b0f4..6820953d2 100644 --- a/web/src/elements/events/UserEvents.ts +++ b/web/src/elements/events/UserEvents.ts @@ -1,8 +1,8 @@ import "@goauthentik/admin/events/EventInfo"; import "@goauthentik/admin/events/EventInfo"; -import { ActionToLabel } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; +import { actionToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; import "@goauthentik/elements/Tabs"; import "@goauthentik/elements/buttons/Dropdown"; @@ -47,7 +47,7 @@ export class UserEvents extends Table { row(item: EventWithContext): TemplateResult[] { return [ - html`${ActionToLabel(item.action)}`, + html`${actionToLabel(item.action)}`, html`
${item.user?.username}
${item.user.on_behalf_of ? html` diff --git a/web/src/elements/notifications/NotificationDrawer.ts b/web/src/elements/notifications/NotificationDrawer.ts index d8d11c664..e15cf7307 100644 --- a/web/src/elements/notifications/NotificationDrawer.ts +++ b/web/src/elements/notifications/NotificationDrawer.ts @@ -1,6 +1,6 @@ -import { ActionToLabel } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_REFRESH } from "@goauthentik/common/constants"; +import { actionToLabel } from "@goauthentik/common/labels"; import { MessageLevel } from "@goauthentik/common/messages"; import { me } from "@goauthentik/common/users"; import { AKElement } from "@goauthentik/elements/Base"; @@ -90,7 +90,7 @@ export class NotificationDrawer extends AKElement {

- ${ActionToLabel(item.event?.action)} + ${actionToLabel(item.event?.action)}

diff --git a/web/src/user/LibraryApplication/index.ts b/web/src/user/LibraryApplication/index.ts index e4d9afc4f..54a611040 100644 --- a/web/src/user/LibraryApplication/index.ts +++ b/web/src/user/LibraryApplication/index.ts @@ -1,14 +1,16 @@ import { PFSize } from "@goauthentik/app/elements/Spinner"; import { truncateWords } from "@goauthentik/common/utils"; +import "@goauthentik/components/ak-app-icon"; import { AKElement, rootInterface } from "@goauthentik/elements/Base"; import "@goauthentik/elements/Expand"; -import "@goauthentik/user/LibraryApplication/AppIcon"; import { UserInterface } from "@goauthentik/user/UserInterface"; import { msg } from "@lit/localize"; -import { CSSResult, TemplateResult, css, html } from "lit"; +import { CSSResult, TemplateResult, css, html, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { classMap } from "lit/directives/class-map.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { styleMap } from "lit/directives/style-map.js"; import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFCard from "@patternfly/patternfly/components/Card/card.css"; @@ -62,23 +64,44 @@ export class LibraryApplication extends AKElement { ]; } + renderExpansion(application: Application) { + const me = rootInterface()?.me; + + return html` +
+ ${application.metaPublisher} +
+ ${truncateWords(application.metaDescription || "", 10)} + ${rootInterface()?.uiConfig?.enabledFeatures.applicationEdit && me?.user.isSuperuser + ? html` + +  ${msg("Edit")} + + ` + : html``} +
`; + } + render(): TemplateResult { if (!this.application) { return html``; } + const me = rootInterface()?.me; - let expandable = false; - if (rootInterface()?.uiConfig?.enabledFeatures.applicationEdit && me?.user.isSuperuser) { - expandable = true; - } - if (this.application.metaPublisher !== "" || this.application.metaDescription !== "") { - expandable = true; - } + const expandable = + (rootInterface()?.uiConfig?.enabledFeatures.applicationEdit && me?.user.isSuperuser) || + this.application.metaPublisher !== "" || + this.application.metaDescription !== ""; + + const classes = { "pf-m-selectable pf-m-selected": this.selected }; + const styles = this.background ? { background: this.background } : {}; + return html` `; } } diff --git a/web/src/user/user-settings/tokens/UserTokenList.ts b/web/src/user/user-settings/tokens/UserTokenList.ts index 63b6a5664..f32b06173 100644 --- a/web/src/user/user-settings/tokens/UserTokenList.ts +++ b/web/src/user/user-settings/tokens/UserTokenList.ts @@ -1,5 +1,5 @@ -import { IntentToLabel } from "@goauthentik/admin/tokens/TokenListPage"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { intentToLabel } from "@goauthentik/common/labels"; import { uiConfig } from "@goauthentik/common/ui/config"; import { me } from "@goauthentik/common/users"; import { PFColor } from "@goauthentik/elements/Label"; @@ -119,7 +119,7 @@ export class UserTokenList extends Table {
- ${IntentToLabel(item.intent || IntentEnum.Api)} + ${intentToLabel(item.intent ?? IntentEnum.Api)}