Reset resource info when on inline policy

This commit is contained in:
Owen
2026-06-09 21:28:25 -07:00
parent dd2c9f2a02
commit 9d88683fc5
7 changed files with 81 additions and 101 deletions

View File

@@ -147,12 +147,10 @@ export const resources = pgTable("resources", {
}), }),
ssl: boolean("ssl").notNull().default(false), ssl: boolean("ssl").notNull().default(false),
blockAccess: boolean("blockAccess").notNull().default(false), blockAccess: boolean("blockAccess").notNull().default(false),
sso: boolean("sso").notNull().default(true),
proxyPort: integer("proxyPort"), proxyPort: integer("proxyPort"),
emailWhitelistEnabled: boolean("emailWhitelistEnabled") sso: boolean("sso"),
.notNull() emailWhitelistEnabled: boolean("emailWhitelistEnabled"),
.default(false), applyRules: boolean("applyRules"),
applyRules: boolean("applyRules").notNull().default(false),
enabled: boolean("enabled").notNull().default(true), enabled: boolean("enabled").notNull().default(true),
stickySession: boolean("stickySession").notNull().default(false), stickySession: boolean("stickySession").notNull().default(false),
tlsServerName: varchar("tlsServerName"), tlsServerName: varchar("tlsServerName"),

View File

@@ -45,9 +45,9 @@ export type ResourceWithAuth = {
password: ResourcePassword | ResourcePolicyPassword | null; password: ResourcePassword | ResourcePolicyPassword | null;
headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null; headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null;
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
applyRules: boolean; applyRules: boolean | null;
sso: boolean; sso: boolean | null;
emailWhitelistEnabled: boolean; emailWhitelistEnabled: boolean | null;
org: Org; org: Org;
}; };

View File

@@ -165,14 +165,12 @@ export const resources = sqliteTable("resources", {
blockAccess: integer("blockAccess", { mode: "boolean" }) blockAccess: integer("blockAccess", { mode: "boolean" })
.notNull() .notNull()
.default(false), .default(false),
sso: integer("sso", { mode: "boolean" }).notNull().default(true),
proxyPort: integer("proxyPort"), proxyPort: integer("proxyPort"),
emailWhitelistEnabled: integer("emailWhitelistEnabled", { mode: "boolean" }) sso: integer("sso", { mode: "boolean" }),
.notNull() emailWhitelistEnabled: integer("emailWhitelistEnabled", {
.default(false), mode: "boolean"
applyRules: integer("applyRules", { mode: "boolean" }) }),
.notNull() applyRules: integer("applyRules", { mode: "boolean" }),
.default(false),
enabled: integer("enabled", { mode: "boolean" }).notNull().default(true), enabled: integer("enabled", { mode: "boolean" }).notNull().default(true),
stickySession: integer("stickySession", { mode: "boolean" }) stickySession: integer("stickySession", { mode: "boolean" })
.notNull() .notNull()

View File

@@ -219,9 +219,9 @@ export type ResourceWithAuth = {
password: ResourcePassword | ResourcePolicyPassword | null; password: ResourcePassword | ResourcePolicyPassword | null;
headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null; headerAuth: ResourceHeaderAuth | ResourcePolicyHeaderAuth | null;
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
applyRules: boolean; applyRules: boolean | null;
sso: boolean; sso: boolean | null;
emailWhitelistEnabled: boolean; emailWhitelistEnabled: boolean | null;
org: Org; org: Org;
}; };

View File

@@ -145,9 +145,9 @@ export async function verifyResourceSession(
| ResourcePolicyHeaderAuth | ResourcePolicyHeaderAuth
| null; | null;
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null; headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
applyRules: boolean; applyRules: boolean | null;
sso: boolean; sso: boolean | null;
emailWhitelistEnabled: boolean; emailWhitelistEnabled: boolean | null;
org: Org; org: Org;
} }
| undefined = localCache.get(resourceCacheKey); | undefined = localCache.get(resourceCacheKey);

View File

@@ -203,9 +203,9 @@ export async function getUserResources(
fullDomain: string | null; fullDomain: string | null;
ssl: boolean; ssl: boolean;
enabled: boolean; enabled: boolean;
sso: boolean; sso: boolean | null;
mode: string; mode: string;
emailWhitelistEnabled: boolean; emailWhitelistEnabled: boolean | null;
policyEmailWhitelistEnabled: boolean | null; policyEmailWhitelistEnabled: boolean | null;
}> = []; }> = [];
if (uniqueResourceIds.length > 0) { if (uniqueResourceIds.length > 0) {

View File

@@ -9,7 +9,8 @@ import {
resourcePassword, resourcePassword,
resourcePincode, resourcePincode,
resourceRules, resourceRules,
resourceWhitelist resourceWhitelist,
Transaction
} from "@server/db"; } from "@server/db";
import { import {
domains, 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( async function updateHttpResource(
route: { route: {
req: Request; 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) { if (updateData.niceId) {
const [existingResource] = await db const [existingResource] = await db
.select() .select()
@@ -560,9 +600,17 @@ async function updateHttpResource(
emailWhitelistEnabled, emailWhitelistEnabled,
applyRules, applyRules,
skipToIdpId, skipToIdpId,
...resourceOnlyData ...resourceOnlyDataRest
} = updateData; } = 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<string, unknown> = {}; const policyUpdate: Record<string, unknown> = {};
if (sso !== undefined) policyUpdate.sso = sso; if (sso !== undefined) policyUpdate.sso = sso;
if (emailWhitelistEnabled !== undefined) if (emailWhitelistEnabled !== undefined)
@@ -659,81 +707,6 @@ async function updateRawResource(
.limit(1); .limit(1);
await db.transaction(async (trx) => { 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) { if (updateData.niceId) {
const [existingResourceConflict] = await trx const [existingResourceConflict] = await trx
.select() .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 [updatedResource] = await trx
.update(resources) .update(resources)
.set(updateData) .set(realUpdateData)
.where(eq(resources.resourceId, resource.resourceId)) .where(eq(resources.resourceId, resource.resourceId))
.returning(); .returning();
}); });