diff --git a/server/routers/resource/getResource.ts b/server/routers/resource/getResource.ts index 708351db1..e139ee58f 100644 --- a/server/routers/resource/getResource.ts +++ b/server/routers/resource/getResource.ts @@ -9,6 +9,7 @@ import { NextFunction, Request, Response } from "express"; import createHttpError from "http-errors"; import { z } from "zod"; import { fromError } from "zod-validation-error"; +import { applyInlinePolicyFields } from "./inlinePolicyFields"; const getResourceSchema = z.strictObject({ resourceId: z @@ -151,13 +152,7 @@ export async function getResource( const policy = await queryInlinePolicy( resource.defaultResourcePolicyId! ); - returnData = { - ...returnData, - sso: policy?.sso || null, - emailWhitelistEnabled: policy?.emailWhitelistEnabled || null, - applyRules: policy?.applyRules || null, - skipToIdpId: policy?.idpId || null - }; + returnData = applyInlinePolicyFields(returnData, policy); } return response(res, { diff --git a/server/routers/resource/inlinePolicyFields.test.ts b/server/routers/resource/inlinePolicyFields.test.ts new file mode 100644 index 000000000..3330e6073 --- /dev/null +++ b/server/routers/resource/inlinePolicyFields.test.ts @@ -0,0 +1,74 @@ +import { assertEquals } from "../../../test/assert"; +import { applyInlinePolicyFields } from "./inlinePolicyFields"; + +function runTests() { + const resource = { + resourceId: 1, + name: "dashboard", + sso: null, + emailWhitelistEnabled: null, + applyRules: null, + skipToIdpId: null + } as any; + + const enabledPolicy = { + sso: true, + emailWhitelistEnabled: true, + applyRules: true, + idpId: 42 + }; + + const enabledResult = applyInlinePolicyFields(resource, enabledPolicy); + assertEquals(enabledResult.sso, true, "sso should mirror policy true"); + assertEquals( + enabledResult.emailWhitelistEnabled, + true, + "email whitelist should mirror policy true" + ); + assertEquals( + enabledResult.applyRules, + true, + "applyRules should mirror policy true" + ); + assertEquals( + enabledResult.skipToIdpId, + 42, + "skipToIdpId should use policy idpId" + ); + + const disabledPolicy = { + sso: false, + emailWhitelistEnabled: false, + applyRules: false, + idpId: null + }; + + const disabledResult = applyInlinePolicyFields(resource, disabledPolicy); + assertEquals(disabledResult.sso, false, "sso false must not become null"); + assertEquals( + disabledResult.emailWhitelistEnabled, + false, + "email whitelist false must not become null" + ); + assertEquals( + disabledResult.applyRules, + false, + "applyRules false must not become null" + ); + assertEquals( + disabledResult.skipToIdpId, + null, + "missing idp should stay null" + ); + + const missingPolicyResult = applyInlinePolicyFields(resource, null); + assertEquals( + missingPolicyResult.sso, + null, + "missing policy should return nullable resource fields" + ); + + console.log("PASS: inline policy fields mirror policy values"); +} + +runTests(); diff --git a/server/routers/resource/inlinePolicyFields.ts b/server/routers/resource/inlinePolicyFields.ts new file mode 100644 index 000000000..9c006beda --- /dev/null +++ b/server/routers/resource/inlinePolicyFields.ts @@ -0,0 +1,19 @@ +import type { Resource, ResourcePolicy } from "@server/db"; + +type InlinePolicyFields = Pick< + ResourcePolicy, + "sso" | "emailWhitelistEnabled" | "applyRules" | "idpId" +>; + +export function applyInlinePolicyFields( + resource: T, + policy: InlinePolicyFields | null | undefined +): T { + return { + ...resource, + sso: policy?.sso ?? null, + emailWhitelistEnabled: policy?.emailWhitelistEnabled ?? null, + applyRules: policy?.applyRules ?? null, + skipToIdpId: policy?.idpId ?? null + }; +} diff --git a/server/routers/resource/updateResource.ts b/server/routers/resource/updateResource.ts index 77603fe9f..35995d517 100644 --- a/server/routers/resource/updateResource.ts +++ b/server/routers/resource/updateResource.ts @@ -47,6 +47,7 @@ import { build } from "@server/build"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { tierMatrix } from "@server/lib/billing/tierMatrix"; import { isSubscribed } from "#dynamic/lib/isSubscribed"; +import { applyInlinePolicyFields } from "./inlinePolicyFields"; const updateResourceParamsSchema = z.strictObject({ resourceId: z.coerce.number().int().positive() @@ -682,6 +683,12 @@ async function updateHttpResource( .where(eq(resourcePolicies.resourcePolicyId, policyId)); } + const [inlinePolicy] = await db + .select() + .from(resourcePolicies) + .where(eq(resourcePolicies.resourcePolicyId, policyId)) + .limit(1); + const updatedResource = await db .update(resources) .set({ ...resourceOnlyData, headers }) @@ -698,7 +705,7 @@ async function updateHttpResource( } return response(res, { - data: updatedResource[0], + data: applyInlinePolicyFields(updatedResource[0], inlinePolicy), success: true, error: false, message: "HTTP resource updated successfully",