diff --git a/server/lib/readConfigFile.ts b/server/lib/readConfigFile.ts index f3057128..07203213 100644 --- a/server/lib/readConfigFile.ts +++ b/server/lib/readConfigFile.ts @@ -174,8 +174,11 @@ export const configSchema = z .optional() .default({}), orgs: z.object({ - block_size: z.number().positive().gt(0), - subnet_group: z.string() + block_size: z.number().positive().gt(0).optional().default(24), + subnet_group: z.string().optional().default("100.90.128.0/24") + }).optional().default({ + block_size: 24, + subnet_group: "100.90.128.0/24" }), rate_limits: z .object({ diff --git a/server/setup/scriptsPg/1.7.0.ts b/server/setup/scriptsPg/1.7.0.ts index cbe6db16..3cb799e0 100644 --- a/server/setup/scriptsPg/1.7.0.ts +++ b/server/setup/scriptsPg/1.7.0.ts @@ -7,7 +7,9 @@ export default async function migration() { console.log(`Running setup script ${version}...`); try { - db.execute(sql` + await db.execute(sql` + BEGIN; + CREATE TABLE "clientSites" ( "clientId" integer NOT NULL, "siteId" integer NOT NULL, @@ -106,6 +108,8 @@ export default async function migration() { ALTER TABLE "userClients" ADD CONSTRAINT "userClients_clientId_clients_id_fk" FOREIGN KEY ("clientId") REFERENCES "public"."clients"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "webauthnChallenge" ADD CONSTRAINT "webauthnChallenge_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "resources" DROP COLUMN "isBaseDomain"; + + COMMIT; `); console.log(`Migrated database schema`); @@ -115,5 +119,45 @@ export default async function migration() { throw e; } + try { + await db.execute(sql`BEGIN`); + + // Update all existing orgs to have the default subnet + await db.execute(sql`UPDATE "orgs" SET "subnet" = '100.90.128.0/24'`); + + // Get all orgs and their sites to assign sequential IP addresses + const orgsQuery = await db.execute(sql`SELECT "orgId" FROM "orgs"`); + + const orgs = orgsQuery.rows as { orgId: string }[]; + + for (const org of orgs) { + const sitesQuery = await db.execute(sql` + SELECT "siteId" FROM "sites" + WHERE "orgId" = ${org.orgId} + ORDER BY "siteId" + `); + + const sites = sitesQuery.rows as { siteId: number }[]; + + let ipIndex = 1; + for (const site of sites) { + const address = `100.90.128.${ipIndex}/24`; + await db.execute(sql` + UPDATE "sites" SET "address" = ${address} + WHERE "siteId" = ${site.siteId} + `); + ipIndex++; + } + } + + await db.execute(sql`COMMIT`); + console.log(`Updated org subnets and site addresses`); + } catch (e) { + await db.execute(sql`ROLLBACK`); + console.log("Unable to update org subnets"); + console.log(e); + throw e; + } + console.log(`${version} migration complete`); } diff --git a/server/setup/scriptsSqlite/1.7.0.ts b/server/setup/scriptsSqlite/1.7.0.ts index e7df9d81..e4be598b 100644 --- a/server/setup/scriptsSqlite/1.7.0.ts +++ b/server/setup/scriptsSqlite/1.7.0.ts @@ -155,5 +155,32 @@ export default async function migration() { throw e; } + db.transaction(() => { + // Update all existing orgs to have the default subnet + db.exec(`UPDATE 'orgs' SET 'subnet' = '100.90.128.0/24'`); + + // Get all orgs and their sites to assign sequential IP addresses + const orgs = db.prepare(`SELECT orgId FROM 'orgs'`).all() as { + orgId: string; + }[]; + + for (const org of orgs) { + const sites = db + .prepare( + `SELECT siteId FROM 'sites' WHERE orgId = ? ORDER BY siteId` + ) + .all(org.orgId) as { siteId: number }[]; + + let ipIndex = 1; + for (const site of sites) { + const address = `100.90.128.${ipIndex}/24`; + db.prepare( + `UPDATE 'sites' SET 'address' = ? WHERE siteId = ?` + ).run(address, site.siteId); + ipIndex++; + } + } + })(); + console.log(`${version} migration complete`); }