From 595842c2c9cc5fee3bf4251e1779dab88d04e0e2 Mon Sep 17 00:00:00 2001 From: Fred KISSIE Date: Thu, 5 Mar 2026 18:48:33 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20finish=20create=20policy=20endpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../routers/policy/createResourcePolicy.ts | 106 +++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/server/private/routers/policy/createResourcePolicy.ts b/server/private/routers/policy/createResourcePolicy.ts index aa9500d1c..8e2757270 100644 --- a/server/private/routers/policy/createResourcePolicy.ts +++ b/server/private/routers/policy/createResourcePolicy.ts @@ -10,6 +10,11 @@ import { idpOrg, orgs, resourcePolicies, + resourcePolicyHeaderAuth, + resourcePolicyPassword, + resourcePolicyPincode, + resourcePolicyRules, + resourcePolicyWhiteList, rolePolicies, roles, userOrgs, @@ -21,6 +26,12 @@ import { and, eq, inArray, not, type InferInsertModel } from "drizzle-orm"; import logger from "@server/logger"; import { getUniqueResourcePolicyName } from "@server/db/names"; import response from "@server/lib/response"; +import { hashPassword } from "@server/auth/password"; +import { + isValidCIDR, + isValidIP, + isValidUrlGlobPattern +} from "@server/lib/validators"; const createResourcePolicyParamsSchema = z.strictObject({ orgId: z.string() @@ -164,7 +175,20 @@ export async function createResourcePolicy( ); } - const { name, sso, userIds, roleIds, skipToIdpId } = parsedBody.data; + const { + name, + sso, + userIds, + roleIds, + skipToIdpId, + applyRules, + emailWhitelistEnabled, + password, + pincode, + headerAuth, + emails, + rules + } = parsedBody.data; // Check if Identity provider in `skipToIdpId` exists if (skipToIdpId) { @@ -223,6 +247,31 @@ export async function createResourcePolicy( const niceId = await getUniqueResourcePolicyName(orgId); + for (const rule of rules) { + if (rule.match === "CIDR" && !isValidCIDR(rule.value)) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + "Invalid CIDR provided" + ) + ); + } else if (rule.match === "IP" && !isValidIP(rule.value)) { + return next( + createHttpError(HttpCode.BAD_REQUEST, "Invalid IP provided") + ); + } else if ( + rule.match === "PATH" && + !isValidUrlGlobPattern(rule.value) + ) { + return next( + createHttpError( + HttpCode.BAD_REQUEST, + "Invalid URL glob pattern provided" + ) + ); + } + } + const policy = await db.transaction(async (trx) => { const [newPolicy] = await trx .insert(resourcePolicies) @@ -231,7 +280,9 @@ export async function createResourcePolicy( orgId, name, sso, - idpId: skipToIdpId + idpId: skipToIdpId, + applyRules, + emailWhitelistEnabled }) .returning(); @@ -272,6 +323,57 @@ export async function createResourcePolicy( await trx.insert(userPolicies).values(usersToAdd); } + if (password) { + const passwordHash = await hashPassword(password); + + await trx.insert(resourcePolicyPassword).values({ + resourcePolicyId: newPolicy.resourcePolicyId, + passwordHash + }); + } + + if (pincode) { + const pincodeHash = await hashPassword(pincode); + + await trx.insert(resourcePolicyPincode).values({ + resourcePolicyId: newPolicy.resourcePolicyId, + pincodeHash, + digitLength: 6 + }); + } + + if (headerAuth) { + const headerAuthHash = await hashPassword( + Buffer.from( + `${headerAuth.user}:${headerAuth.password}` + ).toString("base64") + ); + + await trx.insert(resourcePolicyHeaderAuth).values({ + resourcePolicyId: newPolicy.resourcePolicyId, + headerAuthHash, + extendedCompatibility: headerAuth.extendedCompatibility + }); + } + + if (emailWhitelistEnabled && emails.length > 0) { + await trx.insert(resourcePolicyWhiteList).values( + emails.map((email) => ({ + email, + resourcePolicyId: newPolicy.resourcePolicyId + })) + ); + } + + if (rules.length > 0) { + await trx.insert(resourcePolicyRules).values( + rules.map((rule) => ({ + resourcePolicyId: newPolicy.resourcePolicyId, + ...rule + })) + ); + } + return newPolicy; });