diff --git a/web/package.json b/web/package.json index 62db7e6a4..a306cf4f2 100644 --- a/web/package.json +++ b/web/package.json @@ -15,7 +15,7 @@ "build-proxy": "run-s build-locales rollup:build-proxy", "watch": "run-s build-locales rollup:watch", "lint": "eslint . --max-warnings 0 --fix", - "lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain | cut -c2- | grep '^[M?]' | cut -c7- | grep -E '\\.(ts|js|tsx|jsx)$') ", + "lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain | grep '^[M?][M?]' | cut -c8- | grep -E '\\.(ts|js|tsx|jsx)$') ", "lint:spelling": "codespell -D - -D ../.github/codespell-dictionary.txt -I ../.github/codespell-words.txt -S './src/locales/**' ./src -s", "lit-analyse": "lit-analyzer src", "precommit": "run-s tsc lit-analyse lint:precommit lint:spelling prettier", diff --git a/web/src/elements/user/UserDevicesList.ts b/web/src/admin/users/UserDevicesList.ts similarity index 66% rename from web/src/elements/user/UserDevicesList.ts rename to web/src/admin/users/UserDevicesList.ts index 1c7190dc4..df5ecd83e 100644 --- a/web/src/elements/user/UserDevicesList.ts +++ b/web/src/admin/users/UserDevicesList.ts @@ -1,8 +1,8 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { deviceTypeName } from "@goauthentik/common/labels"; import "@goauthentik/elements/forms/DeleteBulkForm"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; -import { TableColumn } from "@goauthentik/elements/table/Table"; -import { MFADevicesPage, deviceTypeName } from "@goauthentik/user/user-settings/mfa/MFADevicesPage"; +import { Table, TableColumn } from "@goauthentik/elements/table/Table"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -11,7 +11,7 @@ import { customElement, property } from "lit/decorators.js"; import { AuthenticatorsApi, Device } from "@goauthentik/api"; @customElement("ak-user-device-list") -export class UserDeviceList extends MFADevicesPage { +export class UserDeviceList extends Table { @property({ type: Number }) userId?: number; @@ -36,41 +36,34 @@ export class UserDeviceList extends MFADevicesPage { }); } + columns(): TableColumn[] { + // prettier-ignore + return [ + msg("Name"), + msg("Type"), + msg("Confirmed") + ].map((th) => new TableColumn(th, "")) + } + async deleteWrapper(device: Device) { + const api = new AuthenticatorsApi(DEFAULT_CONFIG); + const id = { id: device.pk }; switch (device.type) { case "authentik_stages_authenticator_duo.DuoDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAdminDuoDestroy({ - id: device.pk, - }); + return api.authenticatorsAdminDuoDestroy(id); case "authentik_stages_authenticator_sms.SMSDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAdminSmsDestroy({ - id: device.pk, - }); + return api.authenticatorsAdminSmsDestroy(id); case "authentik_stages_authenticator_totp.TOTPDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAdminTotpDestroy({ - id: device.pk, - }); + return api.authenticatorsAdminTotpDestroy(id); case "authentik_stages_authenticator_static.StaticDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAdminStaticDestroy({ - id: device.pk, - }); + return api.authenticatorsAdminStaticDestroy(id); case "authentik_stages_authenticator_webauthn.WebAuthnDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsAdminWebauthnDestroy({ - id: device.pk, - }); + return api.authenticatorsAdminWebauthnDestroy(id); default: break; } } - columns(): TableColumn[] { - return [ - new TableColumn(msg("Name"), ""), - new TableColumn(msg("Type"), ""), - new TableColumn(msg("Confirmed"), ""), - ]; - } - renderToolbar(): TemplateResult { return html` { diff --git a/web/src/admin/users/UserViewPage.ts b/web/src/admin/users/UserViewPage.ts index dccc34101..7b5b35d29 100644 --- a/web/src/admin/users/UserViewPage.ts +++ b/web/src/admin/users/UserViewPage.ts @@ -21,7 +21,6 @@ import { showMessage } from "@goauthentik/elements/messages/MessageContainer"; import "@goauthentik/elements/oauth/UserRefreshList"; import "@goauthentik/elements/user/SessionList"; import "@goauthentik/elements/user/UserConsentList"; -import "@goauthentik/elements/user/UserDevicesList"; import { msg, str } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; @@ -40,6 +39,8 @@ import PFSizing from "@patternfly/patternfly/utilities/Sizing/sizing.css"; import { CapabilitiesEnum, CoreApi, User } from "@goauthentik/api"; +import "./UserDevicesList"; + @customElement("ak-user-view") export class UserViewPage extends AKElement { @property({ type: Number }) diff --git a/web/src/common/labels.ts b/web/src/common/labels.ts index c352c27ae..f2d9d1376 100644 --- a/web/src/common/labels.ts +++ b/web/src/common/labels.ts @@ -1,6 +1,6 @@ import { msg } from "@lit/localize"; -import { EventActions, IntentEnum, SeverityEnum } from "@goauthentik/api"; +import { Device, EventActions, IntentEnum, SeverityEnum } from "@goauthentik/api"; /* Various tables in the API for which we need to supply labels */ @@ -56,3 +56,12 @@ export const severityEnumToLabel = new Map severityEnumToLabel.get(severity) ?? msg("Unknown severity"); + +// TODO: Add verbose_name field to now vendored OTP devices +export const deviceTypeToLabel = new Map([ + ["authentik_stages_authenticator_static.StaticDevice", msg("Static tokens")], + ["authentik_stages_authenticator_totp.TOTPDevice", msg("TOTP Device")], +]); + +export const deviceTypeName = (device: Device) => + deviceTypeToLabel.get(device.type) ?? device?.verboseName ?? ""; diff --git a/web/src/user/user-settings/mfa/MFADevicesPage.ts b/web/src/user/user-settings/mfa/MFADevicesPage.ts index eb29a13de..5b26d152e 100644 --- a/web/src/user/user-settings/mfa/MFADevicesPage.ts +++ b/web/src/user/user-settings/mfa/MFADevicesPage.ts @@ -1,4 +1,5 @@ import { AndNext, DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import { deviceTypeName } from "@goauthentik/common/labels"; import "@goauthentik/elements/buttons/Dropdown"; import "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/TokenCopyButton"; @@ -15,23 +16,8 @@ import { ifDefined } from "lit/directives/if-defined.js"; import { AuthenticatorsApi, Device, UserSetting } from "@goauthentik/api"; -export function stageToAuthenticatorName(stage: UserSetting): string { - if (stage.title) { - return stage.title; - } - return `Invalid stage component ${stage.component}`; -} - -export function deviceTypeName(device: Device): string { - switch (device.type) { - case "authentik_stages_authenticator_static.StaticDevice": - return msg("Static tokens"); - case "authentik_stages_authenticator_totp.TOTPDevice": - return msg("TOTP Device"); - default: - return device.verboseName; - } -} +export const stageToAuthenticatorName = (stage: UserSetting) => + stage.title ?? `Invalid stage component ${stage.component}`; @customElement("ak-user-settings-mfa") export class MFADevicesPage extends Table { @@ -57,7 +43,12 @@ export class MFADevicesPage extends Table { } columns(): TableColumn[] { - return [new TableColumn(msg("Name")), new TableColumn(msg("Type")), new TableColumn("")]; + // prettier-ignore + return [ + msg("Name"), + msg("Type"), + "" + ].map((th) => new TableColumn(th, "")); } renderToolbar(): TemplateResult { @@ -93,27 +84,19 @@ export class MFADevicesPage extends Table { } async deleteWrapper(device: Device) { + const api = new AuthenticatorsApi(DEFAULT_CONFIG); + const id = { id: device.pk }; switch (device.type) { case "authentik_stages_authenticator_duo.DuoDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsDuoDestroy({ - id: device.pk, - }); + return api.authenticatorsDuoDestroy(id); case "authentik_stages_authenticator_sms.SMSDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsSmsDestroy({ - id: device.pk, - }); + return api.authenticatorsSmsDestroy(id); case "authentik_stages_authenticator_totp.TOTPDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsTotpDestroy({ - id: device.pk, - }); + return api.authenticatorsTotpDestroy(id); case "authentik_stages_authenticator_static.StaticDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsStaticDestroy({ - id: device.pk, - }); + return api.authenticatorsStaticDestroy(id); case "authentik_stages_authenticator_webauthn.WebAuthnDevice": - return new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorsWebauthnDestroy({ - id: device.pk, - }); + return api.authenticatorsWebauthnDestroy(id); default: break; }