From 9d88683fc50369c828788b3fe8bb6688e481d40c Mon Sep 17 00:00:00 2001 From: Owen Date: Tue, 9 Jun 2026 21:28:25 -0700 Subject: [PATCH] Reset resource info when on inline policy --- server/db/pg/schema/schema.ts | 8 +- server/db/queries/verifySessionQueries.ts | 6 +- server/db/sqlite/schema/schema.ts | 12 +- server/private/routers/hybrid.ts | 6 +- server/routers/badger/verifySession.ts | 6 +- server/routers/resource/getUserResources.ts | 4 +- server/routers/resource/updateResource.ts | 140 +++++++++----------- 7 files changed, 81 insertions(+), 101 deletions(-) diff --git a/server/db/pg/schema/schema.ts b/server/db/pg/schema/schema.ts index b7b34a5d7..025bdf923 100644 --- a/server/db/pg/schema/schema.ts +++ b/server/db/pg/schema/schema.ts @@ -147,12 +147,10 @@ export const resources = pgTable("resources", { }), ssl: boolean("ssl").notNull().default(false), blockAccess: boolean("blockAccess").notNull().default(false), - sso: boolean("sso").notNull().default(true), proxyPort: integer("proxyPort"), - emailWhitelistEnabled: boolean("emailWhitelistEnabled") - .notNull() - .default(false), - applyRules: boolean("applyRules").notNull().default(false), + sso: boolean("sso"), + emailWhitelistEnabled: boolean("emailWhitelistEnabled"), + applyRules: boolean("applyRules"), enabled: boolean("enabled").notNull().default(true), stickySession: boolean("stickySession").notNull().default(false), tlsServerName: varchar("tlsServerName"), diff --git a/server/db/queries/verifySessionQueries.ts b/server/db/queries/verifySessionQueries.ts index 302671b0d..0a22e8df3 100644 --- a/server/db/queries/verifySessionQueries.ts +++ b/server/db/queries/verifySessionQueries.ts @@ -45,9 +45,9 @@ export type ResourceWithAuth = { password: ResourcePassword | ResourcePolicyPassword | null; headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; - applyRules: boolean; - sso: boolean; - emailWhitelistEnabled: boolean; + applyRules: boolean | null; + sso: boolean | null; + emailWhitelistEnabled: boolean | null; org: Org; }; diff --git a/server/db/sqlite/schema/schema.ts b/server/db/sqlite/schema/schema.ts index 639e3cf4f..0c4a143f5 100644 --- a/server/db/sqlite/schema/schema.ts +++ b/server/db/sqlite/schema/schema.ts @@ -165,14 +165,12 @@ export const resources = sqliteTable("resources", { blockAccess: integer("blockAccess", { mode: "boolean" }) .notNull() .default(false), - sso: integer("sso", { mode: "boolean" }).notNull().default(true), proxyPort: integer("proxyPort"), - emailWhitelistEnabled: integer("emailWhitelistEnabled", { mode: "boolean" }) - .notNull() - .default(false), - applyRules: integer("applyRules", { mode: "boolean" }) - .notNull() - .default(false), + sso: integer("sso", { mode: "boolean" }), + emailWhitelistEnabled: integer("emailWhitelistEnabled", { + mode: "boolean" + }), + applyRules: integer("applyRules", { mode: "boolean" }), enabled: integer("enabled", { mode: "boolean" }).notNull().default(true), stickySession: integer("stickySession", { mode: "boolean" }) .notNull() diff --git a/server/private/routers/hybrid.ts b/server/private/routers/hybrid.ts index 445b6f318..c6be3e7d1 100644 --- a/server/private/routers/hybrid.ts +++ b/server/private/routers/hybrid.ts @@ -219,9 +219,9 @@ export type ResourceWithAuth = { password: ResourcePassword | ResourcePolicyPassword | null; headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; - applyRules: boolean; - sso: boolean; - emailWhitelistEnabled: boolean; + applyRules: boolean | null; + sso: boolean | null; + emailWhitelistEnabled: boolean | null; org: Org; }; diff --git a/server/routers/badger/verifySession.ts b/server/routers/badger/verifySession.ts index 0f1b1c23c..677fa281d 100644 --- a/server/routers/badger/verifySession.ts +++ b/server/routers/badger/verifySession.ts @@ -145,9 +145,9 @@ export async function verifyResourceSession( | ResourcePolicyHeaderAuth | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; - applyRules: boolean; - sso: boolean; - emailWhitelistEnabled: boolean; + applyRules: boolean | null; + sso: boolean | null; + emailWhitelistEnabled: boolean | null; org: Org; } | undefined = localCache.get(resourceCacheKey); diff --git a/server/routers/resource/getUserResources.ts b/server/routers/resource/getUserResources.ts index 8ba432fd6..c82dcac48 100644 --- a/server/routers/resource/getUserResources.ts +++ b/server/routers/resource/getUserResources.ts @@ -203,9 +203,9 @@ export async function getUserResources( fullDomain: string | null; ssl: boolean; enabled: boolean; - sso: boolean; + sso: boolean | null; mode: string; - emailWhitelistEnabled: boolean; + emailWhitelistEnabled: boolean | null; policyEmailWhitelistEnabled: boolean | null; }> = []; if (uniqueResourceIds.length > 0) { diff --git a/server/routers/resource/updateResource.ts b/server/routers/resource/updateResource.ts index 15b181152..fea830705 100644 --- a/server/routers/resource/updateResource.ts +++ b/server/routers/resource/updateResource.ts @@ -9,7 +9,8 @@ import { resourcePassword, resourcePincode, resourceRules, - resourceWhitelist + resourceWhitelist, + Transaction } from "@server/db"; import { domains, @@ -310,6 +311,36 @@ export async function updateResource( } } +async function clearResourceSpecificSettings( + resourceId: number, + trx: Transaction | typeof db +) { + // remove the resource specific pincode, password, header auth, rules, nad whitelist entries so that the resource will fall back to the policy settings + await Promise.all([ + db + .delete(resourcePassword) + .where(eq(resourcePassword.resourceId, resourceId)), + db + .delete(resourcePincode) + .where(eq(resourcePincode.resourceId, resourceId)), + db + .delete(resourceHeaderAuth) + .where(eq(resourceHeaderAuth.resourceId, resourceId)), + db + .delete(resourceHeaderAuthExtendedCompatibility) + .where( + eq( + resourceHeaderAuthExtendedCompatibility.resourceId, + resourceId + ) + ), + db + .delete(resourceWhitelist) + .where(eq(resourceWhitelist.resourceId, resourceId)), + db.delete(resourceRules).where(eq(resourceRules.resourceId, resourceId)) + ]); +} + async function updateHttpResource( route: { req: Request; @@ -372,6 +403,15 @@ async function updateHttpResource( } } + // catch when the resource policy changes or gets cleared + if ( + resource.resourcePolicyId != updateData.resourcePolicyId || + (updateData.resourcePolicyId === null && + resource.resourcePolicyId !== null) + ) { + await clearResourceSpecificSettings(resource.resourceId, db); + } + if (updateData.niceId) { const [existingResource] = await db .select() @@ -560,9 +600,17 @@ async function updateHttpResource( emailWhitelistEnabled, applyRules, skipToIdpId, - ...resourceOnlyData + ...resourceOnlyDataRest } = updateData; + const resourceOnlyData = { + ...resourceOnlyDataRest, + sso: null, // reset these because they are controlled by the inline policy + emailWhitelistEnabled: null, + applyRules: null, + skipToIdpId: null + }; + const policyUpdate: Record = {}; if (sso !== undefined) policyUpdate.sso = sso; if (emailWhitelistEnabled !== undefined) @@ -659,81 +707,6 @@ async function updateRawResource( .limit(1); await db.transaction(async (trx) => { - if (updateData.resourcePolicyId != null) { - const [existingPolicy] = await trx - .select() - .from(resourcePolicies) - .where( - eq( - resourcePolicies.resourcePolicyId, - updateData.resourcePolicyId - ) - ) - .limit(1); - - if (!existingPolicy) { - return next( - createHttpError( - HttpCode.NOT_FOUND, - `Resource policy with ID ${updateData.resourcePolicyId} not found` - ) - ); - } - } else { - // we are in an inline policy and we need to clear out the old tables - await Promise.all([ - trx - .delete(resourcePassword) - .where( - eq( - resourcePassword.resourceId, - existingResource.resourceId - ) - ), - trx - .delete(resourcePincode) - .where( - eq( - resourcePincode.resourceId, - existingResource.resourceId - ) - ), - trx - .delete(resourceHeaderAuth) - .where( - eq( - resourceHeaderAuth.resourceId, - existingResource.resourceId - ) - ), - trx - .delete(resourceHeaderAuthExtendedCompatibility) - .where( - eq( - resourceHeaderAuthExtendedCompatibility.resourceId, - existingResource.resourceId - ) - ), - trx - .delete(resourceWhitelist) - .where( - eq( - resourceWhitelist.resourceId, - existingResource.resourceId - ) - ), - - trx - .delete(resourceRules) - .where( - eq( - resourceRules.resourceId, - existingResource.resourceId - ) - ) - ]); - } - if (updateData.niceId) { const [existingResourceConflict] = await trx .select() @@ -758,9 +731,20 @@ async function updateRawResource( } } + await clearResourceSpecificSettings(resource.resourceId, trx); // none of these are supported on raw resources + + // we should make sure sso, emailWhitelistEnabled, and applyRules are null because this is a raw resource + const realUpdateData = { + ...updateData, + sso: null, + emailWhitelistEnabled: null, + applyRules: null, + skipToIdpId: null + }; + [updatedResource] = await trx .update(resources) - .set(updateData) + .set(realUpdateData) .where(eq(resources.resourceId, resource.resourceId)) .returning(); });