From 6f9dd8e40b49e5e8eceb28bbe1032bdcaa572d72 Mon Sep 17 00:00:00 2001 From: Jacob Shandling <61553566+jacobshandling@users.noreply.github.com> Date: Wed, 15 Mar 2023 15:44:48 -0700 Subject: [PATCH] Generalize logic to ensure macos_settings always filtered with a team_id; Apply to 3 places (#10472) ## Addresses [this discussion](https://github.com/fleetdm/fleet/pull/10385#discussion_r1134668601) ## Implements Abstract logic to ensure a team_id is always passed with the macos_settings filter, allowing general usage and keeping that logic in sync everywhere it is used. Uses this in 3 places. ## Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Added/updated tests - [x] Manual QA --------- Co-authored-by: Jacob Shandling --- frontend/services/entities/host_count.ts | 6 +++- frontend/services/entities/hosts.ts | 15 ++++---- frontend/utilities/url/index.ts | 18 ++++++++++ frontend/utilities/url/url.tests.ts | 45 ++++++++++++++++++++++-- 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/frontend/services/entities/host_count.ts b/frontend/services/entities/host_count.ts index 2366235fb4..e606f1ea01 100644 --- a/frontend/services/entities/host_count.ts +++ b/frontend/services/entities/host_count.ts @@ -6,7 +6,9 @@ import { buildQueryStringFromParams, getLabelParam, reconcileMutuallyExclusiveHostParams, + reconcileMutuallyInclusiveHostParams, } from "utilities/url"; +import { MacSettingsStatusQueryParam } from "./hosts"; export interface ISortOption { key: string; @@ -22,6 +24,7 @@ export interface IHostCountLoadOptions { teamId?: number; policyId?: number; policyResponse?: string; + macSettingsStatus?: MacSettingsStatusQueryParam; softwareId?: number; lowDiskSpaceHosts?: number; mdmId?: number; @@ -40,6 +43,7 @@ export default { const globalFilter = options?.globalFilter || ""; const teamId = options?.teamId; const softwareId = options?.softwareId; + const macSettingsStatus = options?.macSettingsStatus; const status = options?.status; const mdmId = options?.mdmId; const mdmEnrollmentStatus = options?.mdmEnrollmentStatus; @@ -52,7 +56,7 @@ export default { const queryParams = { query: globalFilter, - team_id: teamId, + ...reconcileMutuallyInclusiveHostParams({ teamId, macSettingsStatus }), ...reconcileMutuallyExclusiveHostParams({ label, policyId, diff --git a/frontend/services/entities/hosts.ts b/frontend/services/entities/hosts.ts index 7ca91c01bd..e4aeb57dfc 100644 --- a/frontend/services/entities/hosts.ts +++ b/frontend/services/entities/hosts.ts @@ -6,6 +6,7 @@ import { buildQueryStringFromParams, getLabelParam, reconcileMutuallyExclusiveHostParams, + reconcileMutuallyInclusiveHostParams, } from "utilities/url"; import { ISelectedPlatform } from "interfaces/platform"; @@ -161,7 +162,7 @@ export default { order_key: sortBy[0].key, order_direction: sortBy[0].direction, query: globalFilter, - team_id: teamId, + ...reconcileMutuallyInclusiveHostParams({ teamId, macSettingsStatus }), ...reconcileMutuallyExclusiveHostParams({ label, policyId, @@ -208,22 +209,18 @@ export default { const label = getLabel(selectedLabels); const sortParams = getSortParams(sortBy); - // ensure macos_settings filter is always applied in - // conjuction with a team_id, 0 (no teams) by default - if (macSettingsStatus) { - teamId = teamId ?? 0; - } - const queryParams = { page, per_page: perPage, query: globalFilter, - team_id: teamId, device_mapping, order_key: sortParams.order_key, order_direction: sortParams.order_direction, status, - macos_settings: macSettingsStatus, + ...reconcileMutuallyInclusiveHostParams({ + teamId, + macSettingsStatus, + }), ...reconcileMutuallyExclusiveHostParams({ label, policyId, diff --git a/frontend/utilities/url/index.ts b/frontend/utilities/url/index.ts index ea939e4549..46daf8aa61 100644 --- a/frontend/utilities/url/index.ts +++ b/frontend/utilities/url/index.ts @@ -1,10 +1,16 @@ import { isEmpty, reduce, omitBy, Dictionary } from "lodash"; +import { MacSettingsStatusQueryParam } from "services/entities/hosts"; type QueryValues = string | number | boolean | undefined | null; export type QueryParams = Record; type FilteredQueryValues = string | number | boolean; type FilteredQueryParams = Record; +interface IMutuallyInclusiveHostParams { + teamId?: number; + macSettingsStatus?: MacSettingsStatusQueryParam; +} + interface IMutuallyExclusiveHostParams { label?: string; policyId?: number; @@ -54,6 +60,18 @@ export const buildQueryStringFromParams = (queryParams: QueryParams) => { return queryString; }; +export const reconcileMutuallyInclusiveHostParams = ({ + teamId, + macSettingsStatus, +}: IMutuallyInclusiveHostParams): Record => { + // ensure macos_settings filter is always applied in + // conjuction with a team_id, 0 (no teams) by default + const reconciled = { macos_settings: macSettingsStatus, team_id: teamId }; + if (macSettingsStatus) { + reconciled.team_id = teamId ?? 0; + } + return reconciled; +}; export const reconcileMutuallyExclusiveHostParams = ({ label, policyId, diff --git a/frontend/utilities/url/url.tests.ts b/frontend/utilities/url/url.tests.ts index bf2e8f1f1d..ed0dd87382 100644 --- a/frontend/utilities/url/url.tests.ts +++ b/frontend/utilities/url/url.tests.ts @@ -1,6 +1,47 @@ -import { buildQueryStringFromParams } from "."; +import { + buildQueryStringFromParams, + reconcileMutuallyInclusiveHostParams, +} from "."; -describe("url utilites", () => { +describe("url utilities > reconcileMutuallyInclusiveHostParams", () => { + it("leaves macSettingsStatus and teamId unchanged when both are present", () => { + const [macSettingsStatus, teamId] = ["pending" as const, 1]; + expect( + reconcileMutuallyInclusiveHostParams({ macSettingsStatus, teamId }) + ).toEqual({ + macos_settings: "pending", + team_id: 1, + }); + }); + + it("adds team_id: 0 when macSettingsStatus is present and teamId is not", () => { + const [macSettingsStatus, teamId] = ["pending" as const, undefined]; + expect( + reconcileMutuallyInclusiveHostParams({ + macSettingsStatus, + teamId, + }) + ).toEqual({ macos_settings: "pending", team_id: 0 }); + }); + + it("does not add macos_settings when teamId is present and macSettingsStatus is not", () => { + const [macSettingsStatus, teamId] = [undefined, 1]; + expect( + reconcileMutuallyInclusiveHostParams({ macSettingsStatus, teamId }) + ).toEqual({ + team_id: 1, + }); + }); + + it("adds nothing when neither macSettingsStatus nor teamId are present", () => { + const [macSettingsStatus, teamId] = [undefined, undefined]; + expect( + reconcileMutuallyInclusiveHostParams({ macSettingsStatus, teamId }) + ).toEqual({}); + }); +}); + +describe("url utilites > buildQueryStringFromParams", () => { it("creates a query string from a params object", () => { const params = { query: "test",