diff --git a/web/scripts/eslint.nightmare.mjs b/web/scripts/eslint.nightmare.mjs index 484621b01b..7835bcc8f0 100644 --- a/web/scripts/eslint.nightmare.mjs +++ b/web/scripts/eslint.nightmare.mjs @@ -13,6 +13,7 @@ const MAX_PARAMS = 5; // const MAX_COGNITIVE_COMPLEXITY = 9; const rules = { + "no-param-reassign": "error", "accessor-pairs": "error", "array-callback-return": "error", "block-scoped-var": "error", @@ -84,7 +85,6 @@ const rules = { "no-obj-calls": "error", "no-octal": "error", "no-octal-escape": "error", - "no-param-reassign": "error", "no-proto": "error", "no-redeclare": "error", "no-regex-spaces": "error", @@ -134,6 +134,7 @@ const rules = { // "sonarjs/cognitive-complexity": ["off", MAX_COGNITIVE_COMPLEXITY], // "sonarjs/no-duplicate-string": "off", // "sonarjs/no-nested-template-literals": "off", + " @typescript-eslint/no-namespace": "off", "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-unused-vars": [ "error", diff --git a/web/scripts/eslint.precommit.mjs b/web/scripts/eslint.precommit.mjs index 1a1d8e2148..0df6a0da74 100644 --- a/web/scripts/eslint.precommit.mjs +++ b/web/scripts/eslint.precommit.mjs @@ -48,6 +48,7 @@ export default [ // "sonarjs/no-duplicate-string": "off", // "sonarjs/no-nested-template-literals": "off", "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-unused-vars": [ "error", { diff --git a/web/src/admin/AdminInterface/AboutModal.ts b/web/src/admin/AdminInterface/AboutModal.ts index b575d5f111..e432499db0 100644 --- a/web/src/admin/AdminInterface/AboutModal.ts +++ b/web/src/admin/AdminInterface/AboutModal.ts @@ -19,7 +19,7 @@ import { AdminApi, CapabilitiesEnum, LicenseSummaryStatusEnum } from "@goauthent @customElement("ak-about-modal") export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton)) { static get styles() { - return super.styles.concat( + return ModalButton.styles.concat( PFAbout, css` .pf-c-about-modal-box__hero { @@ -59,7 +59,7 @@ export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton)) renderModal() { let product = globalAK().brand.brandingTitle || DefaultBrand.brandingTitle; - if (this.licenseSummary.status != LicenseSummaryStatusEnum.Unlicensed) { + if (this.licenseSummary.status !== LicenseSummaryStatusEnum.Unlicensed) { product += ` ${msg("Enterprise")}`; } return html`
{ return; } const outpost = outposts.results[0]; - outpost.config["authentik_host"] = window.location.origin; + outpost.config.authentik_host = window.location.origin; await new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesUpdate({ uuid: outpost.pk, outpostRequest: outpost, diff --git a/web/src/admin/admin-overview/cards/WorkerStatusCard.ts b/web/src/admin/admin-overview/cards/WorkerStatusCard.ts index f4f640382f..179b582788 100644 --- a/web/src/admin/admin-overview/cards/WorkerStatusCard.ts +++ b/web/src/admin/admin-overview/cards/WorkerStatusCard.ts @@ -28,16 +28,18 @@ export class WorkersStatusCard extends AdminStatusCard { icon: "fa fa-times-circle pf-m-danger", message: html`${msg("No workers connected. Background tasks will not run.")}`, }); - } else if (value.filter((w) => !w.versionMatching).length > 0) { + } + + if (value.filter((w) => !w.versionMatching).length > 0) { return Promise.resolve({ icon: "fa fa-times-circle pf-m-danger", message: html`${msg("Worker with incorrect version connected.")}`, }); - } else { - return Promise.resolve({ - icon: "fa fa-check-circle pf-m-success", - }); } + + return Promise.resolve({ + icon: "fa fa-check-circle pf-m-success", + }); } renderValue() { diff --git a/web/src/admin/admin-overview/charts/SyncStatusChart.ts b/web/src/admin/admin-overview/charts/SyncStatusChart.ts index 7855823133..3777b4570b 100644 --- a/web/src/admin/admin-overview/charts/SyncStatusChart.ts +++ b/web/src/admin/admin-overview/charts/SyncStatusChart.ts @@ -127,7 +127,7 @@ export class SyncStatusChart extends AKChart { msg("LDAP Source"), ), ]; - this.centerText = statuses.reduce((total, el) => (total += el.total), 0).toString(); + this.centerText = statuses.reduce((total, el) => total + el.total, 0).toString(); return statuses; } diff --git a/web/src/admin/admin-settings/stories/AdminSettingsFooterLinks.test.ts b/web/src/admin/admin-settings/stories/AdminSettingsFooterLinks.test.ts index 8458b77d01..77863fbdbc 100644 --- a/web/src/admin/admin-settings/stories/AdminSettingsFooterLinks.test.ts +++ b/web/src/admin/admin-settings/stories/AdminSettingsFooterLinks.test.ts @@ -6,26 +6,26 @@ import { html } from "lit"; import "../AdminSettingsFooterLinks.js"; describe("ak-admin-settings-footer-link", () => { - afterEach(async () => { - await browser.execute(async () => { - await document.body.querySelector("ak-admin-settings-footer-link")?.remove(); - if (document.body["_$litPart$"]) { - // @ts-expect-error expression of type '"_$litPart$"' is added by Lit - await delete document.body["_$litPart$"]; + afterEach(() => { + return browser.execute(() => { + document.body.querySelector("ak-admin-settings-footer-link")?.remove(); + + if ("_$litPart$" in document.body) { + delete document.body._$litPart$; } }); }); it("should render an empty control", async () => { render(html``); - const link = await $("ak-admin-settings-footer-link"); + const link = $("ak-admin-settings-footer-link"); await expect(await link.getProperty("isValid")).toStrictEqual(false); await expect(await link.getProperty("toJson")).toEqual({ name: "", href: "" }); }); it("should not be valid if just a name is filled in", async () => { render(html``); - const link = await $("ak-admin-settings-footer-link"); + const link = $("ak-admin-settings-footer-link"); await link.$('input[name="name"]').setValue("foo"); await expect(await link.getProperty("isValid")).toStrictEqual(false); await expect(await link.getProperty("toJson")).toEqual({ name: "foo", href: "" }); @@ -33,7 +33,7 @@ describe("ak-admin-settings-footer-link", () => { it("should be valid if just a URL is filled in", async () => { render(html``); - const link = await $("ak-admin-settings-footer-link"); + const link = $("ak-admin-settings-footer-link"); await link.$('input[name="href"]').setValue("https://foo.com"); await expect(await link.getProperty("isValid")).toStrictEqual(true); await expect(await link.getProperty("toJson")).toEqual({ @@ -44,7 +44,7 @@ describe("ak-admin-settings-footer-link", () => { it("should be valid if both are filled in", async () => { render(html``); - const link = await $("ak-admin-settings-footer-link"); + const link = $("ak-admin-settings-footer-link"); await link.$('input[name="name"]').setValue("foo"); await link.$('input[name="href"]').setValue("https://foo.com"); await expect(await link.getProperty("isValid")).toStrictEqual(true); @@ -56,7 +56,7 @@ describe("ak-admin-settings-footer-link", () => { it("should not be valid if the URL is not valid", async () => { render(html``); - const link = await $("ak-admin-settings-footer-link"); + const link = $("ak-admin-settings-footer-link"); await link.$('input[name="name"]').setValue("foo"); await link.$('input[name="href"]').setValue("never://foo.com"); await expect(await link.getProperty("toJson")).toEqual({ diff --git a/web/src/admin/applications/ApplicationForm.ts b/web/src/admin/applications/ApplicationForm.ts index 54340e1659..cc8d75fd01 100644 --- a/web/src/admin/applications/ApplicationForm.ts +++ b/web/src/admin/applications/ApplicationForm.ts @@ -79,7 +79,7 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm) } static get styles(): CSSResult[] { - return super.styles.concat(PFCard, applicationListStyle); + return TablePage.styles.concat(PFCard, applicationListStyle); } columns(): TableColumn[] { diff --git a/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts b/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts index 7a602dca32..134b94234f 100644 --- a/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts +++ b/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts @@ -6,7 +6,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/SearchSelect"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { CSSResult } from "lit"; @@ -31,9 +31,8 @@ export class ApplicationEntitlementForm extends ModelForm (typeof v === "string" ? v.trim() : v); +/** + * Plucks the specified keys from an object, trimming their values if they are strings. + * + * @template T - The type of the input object. + * @template K - The keys to be plucked from the input object. + * + * @param {T} input - The input object. + * @param {Array} keys - The keys to be plucked from the input object. + */ +function trimMany(input: T, keys: Array): Pick { + const result: Partial = {}; -const trimMany = (o: KeyUnknown, vs: string[]) => - Object.fromEntries(vs.map((v) => [v, autoTrim(o[v])])); + for (const key of keys) { + const value = input[key]; + result[key] = (typeof value === "string" ? value.trim() : value) as T[K]; + } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const isStr = (v: any): v is string => typeof v === "string"; + return result as Pick; +} @customElement("ak-application-wizard-application-step") export class ApplicationWizardApplicationStep extends ApplicationWizardStep { @@ -37,7 +48,7 @@ export class ApplicationWizardApplicationStep extends ApplicationWizardStep { errors = new Map(); @query("form#applicationform") - form!: HTMLFormElement; + declare form: HTMLFormElement; constructor() { super(); @@ -54,27 +65,34 @@ export class ApplicationWizardApplicationStep extends ApplicationWizardStep { } get buttons(): WizardButton[] { - return [{ kind: "next", destination: "provider-choice" }, { kind: "cancel" }]; + return [ + // --- + { kind: "next", destination: "provider-choice" }, + { kind: "cancel" }, + ]; } get valid() { this.errors = new Map(); - const values = trimMany(this.formValues ?? {}, ["metaLaunchUrl", "name", "slug"]); - if (values["name"] === "") { + const trimmed = trimMany((this.formValues || {}) as Partial, [ + "name", + "slug", + "metaLaunchUrl", + ]); + + if (!trimmed.name) { this.errors.set("name", msg("An application name is required")); } - if ( - !( - isStr(values["metaLaunchUrl"]) && - (values["metaLaunchUrl"] === "" || URL.canParse(values["metaLaunchUrl"])) - ) - ) { + + if (!isURLInput(trimmed.metaLaunchUrl)) { this.errors.set("metaLaunchUrl", msg("Not a valid URL")); } - if (!(isStr(values["slug"]) && values["slug"] !== "" && isSlug(values["slug"]))) { + + if (!isSlug(trimmed.slug)) { this.errors.set("slug", msg("Not a valid slug")); } + return this.errors.size === 0; } @@ -82,27 +100,39 @@ export class ApplicationWizardApplicationStep extends ApplicationWizardStep { if (button.kind === "next") { if (!this.valid) { this.handleEnabling({ - disabled: ["provider-choice", "provider", "bindings", "submit"], + disabled: [ + // --- + "provider-choice", + "provider", + "bindings", + "submit", + ], }); + return; } + const app: Partial = this.formValues as Partial; let payload: ApplicationWizardStateUpdate = { app: this.formValues, errors: this.removeErrors("app"), }; + if (app.name && (this.wizard.provider?.name ?? "").trim() === "") { payload = { ...payload, provider: { name: `Provider for ${app.name}` }, }; } + this.handleUpdate(payload, button.destination, { enable: "provider-choice", }); + return; } + super.handleButton(button); } @@ -181,6 +211,7 @@ export class ApplicationWizardApplicationStep extends ApplicationWizardStep { if (!(this.wizard.app && this.wizard.errors)) { throw new Error("Application Step received uninitialized wizard context."); } + return this.renderForm( this.wizard.app as ApplicationRequest, this.wizard.errors?.app ?? {}, diff --git a/web/src/admin/applications/wizard/steps/ak-application-wizard-edit-binding-step.ts b/web/src/admin/applications/wizard/steps/ak-application-wizard-edit-binding-step.ts index 70e761354f..f6c107826d 100644 --- a/web/src/admin/applications/wizard/steps/ak-application-wizard-edit-binding-step.ts +++ b/web/src/admin/applications/wizard/steps/ak-application-wizard-edit-binding-step.ts @@ -45,7 +45,7 @@ export class ApplicationWizardEditBindingStep extends ApplicationWizardStep { hide = true; @query("form#bindingform") - form!: HTMLFormElement; + declare form: HTMLFormElement; @query(".policy-search-select") searchSelect!: SearchSelectBase | SearchSelectBase | SearchSelectBase; diff --git a/web/src/admin/applications/wizard/steps/providers/ak-application-wizard-provider-for-saml.ts b/web/src/admin/applications/wizard/steps/providers/ak-application-wizard-provider-for-saml.ts index 0e2a3845c8..ea493f99bf 100644 --- a/web/src/admin/applications/wizard/steps/providers/ak-application-wizard-provider-for-saml.ts +++ b/web/src/admin/applications/wizard/steps/providers/ak-application-wizard-provider-for-saml.ts @@ -22,7 +22,7 @@ export class ApplicationWizardProviderSamlForm extends ApplicationWizardProvider const setHasSigningKp = (ev: InputEvent) => { const target = ev.target as AkCryptoCertificateSearch; if (!target) return; - this.hasSigningKp = !!target.selectedKeypair; + this.hasSigningKp = Boolean(target.selectedKeypair); }; return html` ${this.label} diff --git a/web/src/admin/blueprints/BlueprintForm.ts b/web/src/admin/blueprints/BlueprintForm.ts index ad2ef15523..16665a7d58 100644 --- a/web/src/admin/blueprints/BlueprintForm.ts +++ b/web/src/admin/blueprints/BlueprintForm.ts @@ -8,7 +8,7 @@ import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/SearchSelect"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; @@ -59,11 +59,10 @@ export class BlueprintForm extends ModelForm { instanceUuid: this.instance.pk, blueprintInstanceRequest: data, }); - } else { - return new ManagedApi(DEFAULT_CONFIG).managedBlueprintsCreate({ - blueprintInstanceRequest: data, - }); } + return new ManagedApi(DEFAULT_CONFIG).managedBlueprintsCreate({ + blueprintInstanceRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/brands/BrandForm.ts b/web/src/admin/brands/BrandForm.ts index c610ef975b..36e7a6daf4 100644 --- a/web/src/admin/brands/BrandForm.ts +++ b/web/src/admin/brands/BrandForm.ts @@ -9,7 +9,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/SearchSelect"; import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -43,11 +43,10 @@ export class BrandForm extends ModelForm { brandUuid: this.instance.brandUuid, brandRequest: data, }); - } else { - return new CoreApi(DEFAULT_CONFIG).coreBrandsCreate({ - brandRequest: data, - }); } + return new CoreApi(DEFAULT_CONFIG).coreBrandsCreate({ + brandRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/common/ak-crypto-certificate-search.ts b/web/src/admin/common/ak-crypto-certificate-search.ts index 45926c101e..d2c3b73a89 100644 --- a/web/src/admin/common/ak-crypto-certificate-search.ts +++ b/web/src/admin/common/ak-crypto-certificate-search.ts @@ -107,7 +107,7 @@ export class AkCryptoCertificateSearch extends CustomListenerElement(AKElement) selected(item: CertificateKeyPair, items: CertificateKeyPair[]) { return ( (this.singleton && !this.certificate && items.length === 1) || - (!!this.certificate && this.certificate === item.pk) + (Boolean(this.certificate) && this.certificate === item.pk) ); } diff --git a/web/src/admin/common/stories/ak-crypto-certificate-search.stories.ts b/web/src/admin/common/stories/ak-crypto-certificate-search.stories.ts index ac31ec2b9e..76e356705b 100644 --- a/web/src/admin/common/stories/ak-crypto-certificate-search.stories.ts +++ b/web/src/admin/common/stories/ak-crypto-certificate-search.stories.ts @@ -29,7 +29,7 @@ const metadata: Meta = { argTypes: { // Typescript is unaware that arguments for components are treated as properties, and // properties are typically renamed to lower case, even if the variable is not. - // @ts-expect-error + // @ts-expect-error TODO: Explain. nokey: { control: "boolean", description: @@ -75,7 +75,7 @@ export const CryptoCertificateSearch = () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const showMessage = (ev: CustomEvent) => { const detail = ev.detail; - delete detail["target"]; + delete detail.target; document.getElementById("message-pad")!.innerText = `Event: ${JSON.stringify( detail, null, diff --git a/web/src/admin/crypto/CertificateKeyPairForm.ts b/web/src/admin/crypto/CertificateKeyPairForm.ts index bfa2d4ca48..942c3b8e24 100644 --- a/web/src/admin/crypto/CertificateKeyPairForm.ts +++ b/web/src/admin/crypto/CertificateKeyPairForm.ts @@ -30,11 +30,10 @@ export class CertificateKeyPairForm extends ModelForm { pbmUuid: this.instance.pk || "", notificationRuleRequest: data, }); - } else { - return new EventsApi(DEFAULT_CONFIG).eventsRulesCreate({ - notificationRuleRequest: data, - }); } + return new EventsApi(DEFAULT_CONFIG).eventsRulesCreate({ + notificationRuleRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/events/TransportForm.ts b/web/src/admin/events/TransportForm.ts index cce51bd8ca..8402a192f8 100644 --- a/web/src/admin/events/TransportForm.ts +++ b/web/src/admin/events/TransportForm.ts @@ -47,11 +47,10 @@ export class TransportForm extends ModelForm { uuid: this.instance.pk || "", notificationTransportRequest: data, }); - } else { - return new EventsApi(DEFAULT_CONFIG).eventsTransportsCreate({ - notificationTransportRequest: data, - }); } + return new EventsApi(DEFAULT_CONFIG).eventsTransportsCreate({ + notificationTransportRequest: data, + }); } onModeChange(mode: string | undefined): void { diff --git a/web/src/admin/flows/FlowForm.ts b/web/src/admin/flows/FlowForm.ts index 511c1ac5b0..b733db27d9 100644 --- a/web/src/admin/flows/FlowForm.ts +++ b/web/src/admin/flows/FlowForm.ts @@ -58,7 +58,7 @@ export class FlowForm extends WithCapabilitiesConfig(ModelForm) { } if (this.can(CapabilitiesEnum.CanSaveMedia)) { - const icon = this.getFormFiles()["background"]; + const icon = this.getFormFiles().background; if (icon || this.clearBackground) { await new FlowsApi(DEFAULT_CONFIG).flowsInstancesSetBackgroundCreate({ slug: flow.slug, diff --git a/web/src/admin/flows/FlowImportForm.ts b/web/src/admin/flows/FlowImportForm.ts index 783f51217e..0765582350 100644 --- a/web/src/admin/flows/FlowImportForm.ts +++ b/web/src/admin/flows/FlowImportForm.ts @@ -27,7 +27,7 @@ export class FlowImportForm extends Form { } async send(): Promise { - const file = this.getFormFiles()["flow"]; + const file = this.getFormFiles().flow; if (!file) { throw new SentryIgnoredError("No form data"); } diff --git a/web/src/admin/flows/StageBindingForm.ts b/web/src/admin/flows/StageBindingForm.ts index 488cddf732..1d31bb6def 100644 --- a/web/src/admin/flows/StageBindingForm.ts +++ b/web/src/admin/flows/StageBindingForm.ts @@ -39,9 +39,8 @@ export class StageBindingForm extends ModelForm { getSuccessMessage(): string { if (this.instance?.pk) { return msg("Successfully updated binding."); - } else { - return msg("Successfully created binding."); } + return msg("Successfully created binding."); } send(data: FlowStageBinding): Promise { @@ -50,14 +49,13 @@ export class StageBindingForm extends ModelForm { fsbUuid: this.instance.pk, patchedFlowStageBindingRequest: data, }); - } else { - if (this.targetPk) { - data.target = this.targetPk; - } - return new FlowsApi(DEFAULT_CONFIG).flowsBindingsCreate({ - flowStageBindingRequest: data, - }); } + if (this.targetPk) { + data.target = this.targetPk; + } + return new FlowsApi(DEFAULT_CONFIG).flowsBindingsCreate({ + flowStageBindingRequest: data, + }); } async getOrder(): Promise { diff --git a/web/src/admin/groups/GroupForm.ts b/web/src/admin/groups/GroupForm.ts index eec1d0e54a..f460b7a925 100644 --- a/web/src/admin/groups/GroupForm.ts +++ b/web/src/admin/groups/GroupForm.ts @@ -10,7 +10,7 @@ import "@goauthentik/elements/chips/ChipGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/SearchSelect"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, css, html } from "lit"; @@ -55,12 +55,11 @@ export class GroupForm extends ModelForm { groupUuid: this.instance.pk, patchedGroupRequest: data, }); - } else { - data.users = []; - return new CoreApi(DEFAULT_CONFIG).coreGroupsCreate({ - groupRequest: data, - }); } + data.users = []; + return new CoreApi(DEFAULT_CONFIG).coreGroupsCreate({ + groupRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/groups/RelatedGroupList.ts b/web/src/admin/groups/RelatedGroupList.ts index ca7ce9d20a..e129c52c33 100644 --- a/web/src/admin/groups/RelatedGroupList.ts +++ b/web/src/admin/groups/RelatedGroupList.ts @@ -125,7 +125,8 @@ export class RelatedGroupList extends Table { buttonLabel=${msg("Remove")} .objects=${this.selectedElements} .delete=${(item: Group) => { - if (!this.targetUser) return; + if (!this.targetUser) return null; + return new CoreApi(DEFAULT_CONFIG).coreGroupsRemoveUserCreate({ groupUuid: item.pk, userAccountRequest: { diff --git a/web/src/admin/groups/RelatedUserList.ts b/web/src/admin/groups/RelatedUserList.ts index ed133ede3d..91a707d445 100644 --- a/web/src/admin/groups/RelatedUserList.ts +++ b/web/src/admin/groups/RelatedUserList.ts @@ -46,8 +46,12 @@ import { User, } from "@goauthentik/api"; +interface AddUsersToGroupFormData { + users: number[]; +} + @customElement("ak-user-related-add") -export class RelatedUserAdd extends Form<{ users: number[] }> { +export class RelatedUserAdd extends Form { @property({ attribute: false }) group?: Group; @@ -58,7 +62,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> { return msg("Successfully added user(s)."); } - async send(data: { users: number[] }): Promise<{ users: number[] }> { + async send(data: AddUsersToGroupFormData): Promise { await Promise.all( data.users.map((user) => { return new CoreApi(DEFAULT_CONFIG).coreGroupsAddUserCreate({ @@ -69,6 +73,7 @@ export class RelatedUserAdd extends Form<{ users: number[] }> { }); }), ); + return data; } @@ -133,7 +138,7 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl me?: SessionUser; static get styles(): CSSResult[] { - return super.styles.concat(PFDescriptionList, PFAlert, PFBanner); + return Table.styles.concat(PFDescriptionList, PFAlert, PFBanner); } async apiEndpoint(): Promise> { diff --git a/web/src/admin/outposts/OutpostDeploymentModal.ts b/web/src/admin/outposts/OutpostDeploymentModal.ts index fcbd4bb36e..0990588f96 100644 --- a/web/src/admin/outposts/OutpostDeploymentModal.ts +++ b/web/src/admin/outposts/OutpostDeploymentModal.ts @@ -65,7 +65,7 @@ export class OutpostDeploymentModal extends ModalButton {
- ${this.outpost?.type == OutpostTypeEnum.Proxy + ${this.outpost?.type === OutpostTypeEnum.Proxy ? html`

${msg( diff --git a/web/src/admin/outposts/OutpostForm.ts b/web/src/admin/outposts/OutpostForm.ts index 3c276caaf7..487aa2a9e1 100644 --- a/web/src/admin/outposts/OutpostForm.ts +++ b/web/src/admin/outposts/OutpostForm.ts @@ -10,7 +10,7 @@ import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/SearchSelect"; import { PaginatedResponse } from "@goauthentik/elements/table/Table"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -129,11 +129,10 @@ export class OutpostForm extends ModelForm { uuid: this.instance.pk || "", outpostRequest: data, }); - } else { - return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesCreate({ - outpostRequest: data, - }); } + return new OutpostsApi(DEFAULT_CONFIG).outpostsInstancesCreate({ + outpostRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/outposts/ServiceConnectionDockerForm.ts b/web/src/admin/outposts/ServiceConnectionDockerForm.ts index ec1eae2d83..40c70fdf3f 100644 --- a/web/src/admin/outposts/ServiceConnectionDockerForm.ts +++ b/web/src/admin/outposts/ServiceConnectionDockerForm.ts @@ -32,11 +32,10 @@ export class ServiceConnectionDockerForm extends ModelForm { return msg(str`Group ${item.groupObj?.name}`); } else if (item.user) { return msg(str`User ${item.userObj?.name}`); - } else { - return msg("-"); } + return msg("-"); } getPolicyUserGroupRow(item: PolicyBinding): TemplateResult { @@ -123,9 +122,8 @@ export class BoundPoliciesList extends Table { ${msg("Edit User")} `; - } else { - return html``; } + return html``; } renderToolbarSelected(): TemplateResult { diff --git a/web/src/admin/policies/PolicyBindingForm.ts b/web/src/admin/policies/PolicyBindingForm.ts index d27ed3af50..92e902f608 100644 --- a/web/src/admin/policies/PolicyBindingForm.ts +++ b/web/src/admin/policies/PolicyBindingForm.ts @@ -72,9 +72,8 @@ export class PolicyBindingForm extends ModelForm { getSuccessMessage(): string { if (this.instance?.pk) { return msg("Successfully updated binding."); - } else { - return msg("Successfully created binding."); } + return msg("Successfully created binding."); } static get styles(): CSSResult[] { @@ -111,11 +110,10 @@ export class PolicyBindingForm extends ModelForm { policyBindingUuid: this.instance.pk, policyBindingRequest: data, }); - } else { - return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsCreate({ - policyBindingRequest: data, - }); } + return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsCreate({ + policyBindingRequest: data, + }); } async getOrder(): Promise { diff --git a/web/src/admin/policies/PolicyTestForm.ts b/web/src/admin/policies/PolicyTestForm.ts index d612d7e4a3..f736a9d9f4 100644 --- a/web/src/admin/policies/PolicyTestForm.ts +++ b/web/src/admin/policies/PolicyTestForm.ts @@ -7,7 +7,7 @@ import "@goauthentik/elements/events/LogViewer"; import { Form } from "@goauthentik/elements/forms/Form"; import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/SearchSelect"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { CSSResult, TemplateResult, html } from "lit"; diff --git a/web/src/admin/policies/dummy/DummyPolicyForm.ts b/web/src/admin/policies/dummy/DummyPolicyForm.ts index 8801ec3b37..f15332fa28 100644 --- a/web/src/admin/policies/dummy/DummyPolicyForm.ts +++ b/web/src/admin/policies/dummy/DummyPolicyForm.ts @@ -25,11 +25,11 @@ export class DummyPolicyForm extends BasePolicyForm { policyUuid: this.instance.pk || "", dummyPolicyRequest: data, }); - } else { - return new PoliciesApi(DEFAULT_CONFIG).policiesDummyCreate({ - dummyPolicyRequest: data, - }); } + + return new PoliciesApi(DEFAULT_CONFIG).policiesDummyCreate({ + dummyPolicyRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/policies/event_matcher/EventMatcherPolicyForm.ts b/web/src/admin/policies/event_matcher/EventMatcherPolicyForm.ts index 9e1f2b08b4..1a2148573a 100644 --- a/web/src/admin/policies/event_matcher/EventMatcherPolicyForm.ts +++ b/web/src/admin/policies/event_matcher/EventMatcherPolicyForm.ts @@ -37,11 +37,10 @@ export class EventMatcherPolicyForm extends BasePolicyForm { policyUuid: this.instance.pk || "", eventMatcherPolicyRequest: data, }); - } else { - return new PoliciesApi(DEFAULT_CONFIG).policiesEventMatcherCreate({ - eventMatcherPolicyRequest: data, - }); } + return new PoliciesApi(DEFAULT_CONFIG).policiesEventMatcherCreate({ + eventMatcherPolicyRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/policies/expiry/ExpiryPolicyForm.ts b/web/src/admin/policies/expiry/ExpiryPolicyForm.ts index e35f4431ac..9c4b45d4a8 100644 --- a/web/src/admin/policies/expiry/ExpiryPolicyForm.ts +++ b/web/src/admin/policies/expiry/ExpiryPolicyForm.ts @@ -25,11 +25,10 @@ export class PasswordExpiryPolicyForm extends BasePolicyForm { policyUuid: this.instance.pk || "", expressionPolicyRequest: data, }); - } else { - return new PoliciesApi(DEFAULT_CONFIG).policiesExpressionCreate({ - expressionPolicyRequest: data, - }); } + return new PoliciesApi(DEFAULT_CONFIG).policiesExpressionCreate({ + expressionPolicyRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/policies/geoip/GeoIPPolicyForm.ts b/web/src/admin/policies/geoip/GeoIPPolicyForm.ts index d59936c1ab..20a4dc9c82 100644 --- a/web/src/admin/policies/geoip/GeoIPPolicyForm.ts +++ b/web/src/admin/policies/geoip/GeoIPPolicyForm.ts @@ -39,11 +39,10 @@ export class GeoIPPolicyForm extends BasePolicyForm { policyUuid: this.instance.pk || "", geoIPPolicyRequest: data, }); - } else { - return new PoliciesApi(DEFAULT_CONFIG).policiesGeoipCreate({ - geoIPPolicyRequest: data, - }); } + return new PoliciesApi(DEFAULT_CONFIG).policiesGeoipCreate({ + geoIPPolicyRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/policies/password/PasswordPolicyForm.ts b/web/src/admin/policies/password/PasswordPolicyForm.ts index a3913a5d8f..486df0a928 100644 --- a/web/src/admin/policies/password/PasswordPolicyForm.ts +++ b/web/src/admin/policies/password/PasswordPolicyForm.ts @@ -38,11 +38,10 @@ export class PasswordPolicyForm extends BasePolicyForm { policyUuid: this.instance.pk || "", passwordPolicyRequest: data, }); - } else { - return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordCreate({ - passwordPolicyRequest: data, - }); } + return new PoliciesApi(DEFAULT_CONFIG).policiesPasswordCreate({ + passwordPolicyRequest: data, + }); } renderStaticRules(): TemplateResult { diff --git a/web/src/admin/policies/reputation/ReputationPolicyForm.ts b/web/src/admin/policies/reputation/ReputationPolicyForm.ts index 2f85502ef7..5e635233e5 100644 --- a/web/src/admin/policies/reputation/ReputationPolicyForm.ts +++ b/web/src/admin/policies/reputation/ReputationPolicyForm.ts @@ -25,11 +25,10 @@ export class ReputationPolicyForm extends BasePolicyForm { policyUuid: this.instance.pk || "", reputationPolicyRequest: data, }); - } else { - return new PoliciesApi(DEFAULT_CONFIG).policiesReputationCreate({ - reputationPolicyRequest: data, - }); } + return new PoliciesApi(DEFAULT_CONFIG).policiesReputationCreate({ + reputationPolicyRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/property-mappings/PropertyMappingNotification.ts b/web/src/admin/property-mappings/PropertyMappingNotification.ts index 891555d717..dff00b822d 100644 --- a/web/src/admin/property-mappings/PropertyMappingNotification.ts +++ b/web/src/admin/property-mappings/PropertyMappingNotification.ts @@ -21,11 +21,10 @@ export class PropertyMappingNotification extends BasePropertyMappingForm { id: this.instance.pk, oAuth2ProviderRequest: data, }); - } else { - return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Create({ - oAuth2ProviderRequest: data, - }); } + return new ProvidersApi(DEFAULT_CONFIG).providersOauth2Create({ + oAuth2ProviderRequest: data, + }); } renderForm() { diff --git a/web/src/admin/providers/proxy/ProxyProviderForm.ts b/web/src/admin/providers/proxy/ProxyProviderForm.ts index 31a2c1105b..8e3c527719 100644 --- a/web/src/admin/providers/proxy/ProxyProviderForm.ts +++ b/web/src/admin/providers/proxy/ProxyProviderForm.ts @@ -45,11 +45,10 @@ export class ProxyProviderFormPage extends BaseProviderForm { id: this.instance.pk, proxyProviderRequest: data, }); - } else { - return new ProvidersApi(DEFAULT_CONFIG).providersProxyCreate({ - proxyProviderRequest: data, - }); } + return new ProvidersApi(DEFAULT_CONFIG).providersProxyCreate({ + proxyProviderRequest: data, + }); } renderForm() { diff --git a/web/src/admin/providers/proxy/ProxyProviderViewPage.ts b/web/src/admin/providers/proxy/ProxyProviderViewPage.ts index 06fdfb6734..1643a2a33a 100644 --- a/web/src/admin/providers/proxy/ProxyProviderViewPage.ts +++ b/web/src/admin/providers/proxy/ProxyProviderViewPage.ts @@ -60,6 +60,9 @@ export function ModeToLabel(action?: ProxyMode): string { } } +/** + * Predicate to determine if a given proxy mode should forward. + */ export function isForward(mode: ProxyMode): boolean { switch (mode) { case ProxyMode.Proxy: @@ -156,13 +159,12 @@ export class ProxyProviderViewPage extends AKElement { (input: string): string => { // The generated config is pretty unreliable currently so // put it behind a flag - if (!getURLParam("generatedConfig", false)) { - return input; - } - if (!this.provider) { - return input; - } + if (!getURLParam("generatedConfig", false)) return input; + + if (!this.provider) return input; + const extHost = new URL(this.provider.externalHost); + // See website/docs/add-secure-apps/providers/proxy/forward_auth.mdx if (this.provider?.mode === ProxyMode.ForwardSingle) { return input @@ -170,13 +172,16 @@ export class ProxyProviderViewPage extends AKElement { .replaceAll("outpost.company:9000", window.location.hostname) .replaceAll("https://app.company", extHost.toString()) .replaceAll("app.company", extHost.hostname); - } else if (this.provider?.mode == ProxyMode.ForwardDomain) { + } + + if (this.provider?.mode === ProxyMode.ForwardDomain) { return input .replaceAll("authentik.company", window.location.hostname) .replaceAll("outpost.company:9000", extHost.toString()) .replaceAll("https://app.company", extHost.toString()) .replaceAll("app.company", extHost.hostname); } + return input; }, ]; diff --git a/web/src/admin/providers/rac/EndpointForm.ts b/web/src/admin/providers/rac/EndpointForm.ts index 2c039b85fd..4a9dacf20e 100644 --- a/web/src/admin/providers/rac/EndpointForm.ts +++ b/web/src/admin/providers/rac/EndpointForm.ts @@ -6,7 +6,7 @@ import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-pro import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -46,11 +46,10 @@ export class EndpointForm extends ModelForm { pbmUuid: this.instance.pk || "", patchedEndpointRequest: data, }); - } else { - return new RacApi(DEFAULT_CONFIG).racEndpointsCreate({ - endpointRequest: data, - }); } + return new RacApi(DEFAULT_CONFIG).racEndpointsCreate({ + endpointRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/providers/rac/RACProviderForm.ts b/web/src/admin/providers/rac/RACProviderForm.ts index c558506c72..febf75c90f 100644 --- a/web/src/admin/providers/rac/RACProviderForm.ts +++ b/web/src/admin/providers/rac/RACProviderForm.ts @@ -10,7 +10,7 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/utils/TimeDeltaHelp"; -import YAML from "yaml"; +import * as YAML from "yaml"; import { msg } from "@lit/localize"; import { TemplateResult, html } from "lit"; @@ -32,9 +32,8 @@ export class RACProviderFormPage extends ModelForm { getSuccessMessage(): string { if (this.instance) { return msg("Successfully updated provider."); - } else { - return msg("Successfully created provider."); } + return msg("Successfully created provider."); } async send(data: RACProvider): Promise { @@ -43,11 +42,10 @@ export class RACProviderFormPage extends ModelForm { id: this.instance.pk, rACProviderRequest: data, }); - } else { - return new ProvidersApi(DEFAULT_CONFIG).providersRacCreate({ - rACProviderRequest: data, - }); } + return new ProvidersApi(DEFAULT_CONFIG).providersRacCreate({ + rACProviderRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/providers/radius/RadiusProviderForm.ts b/web/src/admin/providers/radius/RadiusProviderForm.ts index e1832f7fc7..69fc12cdcc 100644 --- a/web/src/admin/providers/radius/RadiusProviderForm.ts +++ b/web/src/admin/providers/radius/RadiusProviderForm.ts @@ -22,11 +22,10 @@ export class RadiusProviderFormPage extends WithBrandConfig(BaseProviderForm { const provider = await new ProvidersApi(DEFAULT_CONFIG).providersSamlRetrieve({ id: pk, }); - this.hasSigningKp = !!provider.signingKp; + this.hasSigningKp = Boolean(provider.signingKp); return provider; } @@ -27,18 +27,17 @@ export class SAMLProviderFormPage extends BaseProviderForm { id: this.instance.pk, sAMLProviderRequest: data, }); - } else { - return new ProvidersApi(DEFAULT_CONFIG).providersSamlCreate({ - sAMLProviderRequest: data, - }); } + return new ProvidersApi(DEFAULT_CONFIG).providersSamlCreate({ + sAMLProviderRequest: data, + }); } renderForm() { const setHasSigningKp = (ev: InputEvent) => { const target = ev.target as AkCryptoCertificateSearch; if (!target) return; - this.hasSigningKp = !!target.selectedKeypair; + this.hasSigningKp = Boolean(target.selectedKeypair); }; return renderForm(this.instance ?? {}, [], setHasSigningKp, this.hasSigningKp); diff --git a/web/src/admin/providers/saml/SAMLProviderImportForm.ts b/web/src/admin/providers/saml/SAMLProviderImportForm.ts index 3241e24b66..cc635d8d2f 100644 --- a/web/src/admin/providers/saml/SAMLProviderImportForm.ts +++ b/web/src/admin/providers/saml/SAMLProviderImportForm.ts @@ -18,7 +18,7 @@ export class SAMLProviderImportForm extends Form { } async send(data: SAMLProvider): Promise { - const file = this.getFormFiles()["metadata"]; + const file = this.getFormFiles().metadata; if (!file) { throw new SentryIgnoredError("No form data"); } diff --git a/web/src/admin/providers/scim/SCIMProviderForm.ts b/web/src/admin/providers/scim/SCIMProviderForm.ts index bfdcd3736d..4f88bee8d5 100644 --- a/web/src/admin/providers/scim/SCIMProviderForm.ts +++ b/web/src/admin/providers/scim/SCIMProviderForm.ts @@ -21,11 +21,10 @@ export class SCIMProviderFormPage extends BaseProviderForm { id: this.instance.pk, sCIMProviderRequest: data, }); - } else { - return new ProvidersApi(DEFAULT_CONFIG).providersScimCreate({ - sCIMProviderRequest: data, - }); } + return new ProvidersApi(DEFAULT_CONFIG).providersScimCreate({ + sCIMProviderRequest: data, + }); } renderForm() { diff --git a/web/src/admin/providers/ssf/SSFProviderFormPage.ts b/web/src/admin/providers/ssf/SSFProviderFormPage.ts index 5494cdde6b..95c7c28399 100644 --- a/web/src/admin/providers/ssf/SSFProviderFormPage.ts +++ b/web/src/admin/providers/ssf/SSFProviderFormPage.ts @@ -43,11 +43,10 @@ export class SSFProviderFormPage extends BaseProviderForm { id: this.instance.pk, sSFProviderRequest: data, }); - } else { - return new ProvidersApi(DEFAULT_CONFIG).providersSsfCreate({ - sSFProviderRequest: data, - }); } + return new ProvidersApi(DEFAULT_CONFIG).providersSsfCreate({ + sSFProviderRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/roles/RoleForm.ts b/web/src/admin/roles/RoleForm.ts index 80cb5355cf..5a4d2f537c 100644 --- a/web/src/admin/roles/RoleForm.ts +++ b/web/src/admin/roles/RoleForm.ts @@ -32,11 +32,10 @@ export class RoleForm extends ModelForm { uuid: this.instance.pk, patchedRoleRequest: data, }); - } else { - return new RbacApi(DEFAULT_CONFIG).rbacRolesCreate({ - roleRequest: data, - }); } + return new RbacApi(DEFAULT_CONFIG).rbacRolesCreate({ + roleRequest: data, + }); } renderForm(): TemplateResult { diff --git a/web/src/admin/sources/BaseSourceForm.ts b/web/src/admin/sources/BaseSourceForm.ts index f8c68c4bd1..cb5a91098d 100644 --- a/web/src/admin/sources/BaseSourceForm.ts +++ b/web/src/admin/sources/BaseSourceForm.ts @@ -3,7 +3,10 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { msg } from "@lit/localize"; export abstract class BaseSourceForm extends ModelForm { - getSuccessMessage(): string { + /** + * Success message to display after a successful form submission. + */ + public getSuccessMessage(): string { return this.instance ? msg("Successfully updated source.") : msg("Successfully created source."); diff --git a/web/src/admin/sources/kerberos/KerberosSourceForm.ts b/web/src/admin/sources/kerberos/KerberosSourceForm.ts index 9c18fbd0f1..939a9c3717 100644 --- a/web/src/admin/sources/kerberos/KerberosSourceForm.ts +++ b/web/src/admin/sources/kerberos/KerberosSourceForm.ts @@ -42,6 +42,7 @@ export class KerberosSourceForm extends WithCapabilitiesConfig(BaseSourceForm[]) => mappings.filter( ([_0, _1, _2, mapping]: DualSelectPair) => - object == "user" && + object === "user" && mapping?.managed?.startsWith("goauthentik.io/sources/kerberos/user/default/"), ); } diff --git a/web/src/admin/sources/oauth/OAuthSourceForm.ts b/web/src/admin/sources/oauth/OAuthSourceForm.ts index 7429fd6b87..ba7d98de5c 100644 --- a/web/src/admin/sources/oauth/OAuthSourceForm.ts +++ b/web/src/admin/sources/oauth/OAuthSourceForm.ts @@ -73,7 +73,7 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm { const selected = Array.from(this.instance?.allowedServers || []).some( (server) => { - return server == r.clientIdentifier; + return server === r.clientIdentifier; }, ); return html`