From cb6c47678b3b41dc89034af5353d5366d712ab5c Mon Sep 17 00:00:00 2001 From: Owen Date: Mon, 30 Mar 2026 14:43:49 -0700 Subject: [PATCH] Add regions to blueprints --- server/lib/blueprints/proxyResources.ts | 5 +++++ server/lib/blueprints/types.ts | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/server/lib/blueprints/proxyResources.ts b/server/lib/blueprints/proxyResources.ts index 2696b68c8..e16da2ea5 100644 --- a/server/lib/blueprints/proxyResources.ts +++ b/server/lib/blueprints/proxyResources.ts @@ -31,6 +31,7 @@ import { pickPort } from "@server/routers/target/helpers"; import { resourcePassword } from "@server/db"; import { hashPassword } from "@server/auth/password"; import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators"; +import { isValidRegionId } from "@server/db/regions"; import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed"; import { tierMatrix } from "../billing/tierMatrix"; @@ -863,6 +864,10 @@ function validateRule(rule: any) { if (!isValidUrlGlobPattern(rule.value)) { throw new Error(`Invalid URL glob pattern: ${rule.value}`); } + } else if (rule.match === "region") { + if (!isValidRegionId(rule.value)) { + throw new Error(`Invalid region ID provided: ${rule.value}`); + } } } diff --git a/server/lib/blueprints/types.ts b/server/lib/blueprints/types.ts index 2239e4f9a..6ebc509b8 100644 --- a/server/lib/blueprints/types.ts +++ b/server/lib/blueprints/types.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { portRangeStringSchema } from "@server/lib/ip"; import { MaintenanceSchema } from "#dynamic/lib/blueprints/MaintenanceSchema"; +import { isValidRegionId } from "@server/db/regions"; export const SiteSchema = z.object({ name: z.string().min(1).max(100), @@ -77,7 +78,7 @@ export const AuthSchema = z.object({ export const RuleSchema = z .object({ action: z.enum(["allow", "deny", "pass"]), - match: z.enum(["cidr", "path", "ip", "country", "asn"]), + match: z.enum(["cidr", "path", "ip", "country", "asn", "region"]), value: z.string(), priority: z.int().optional() }) @@ -137,6 +138,19 @@ export const RuleSchema = z message: "Value must be 'AS' format or 'ALL' when match is 'asn'" } + ) + .refine( + (rule) => { + if (rule.match === "region") { + return isValidRegionId(rule.value); + } + return true; + }, + { + path: ["value"], + message: + "Value must be a valid UN M.49 region or subregion ID when match is 'region'" + } ); export const HeaderSchema = z.object({