From b01d2666290f36b9dc992b4c2c001c26fa58eda0 Mon Sep 17 00:00:00 2001 From: Owen Date: Mon, 30 Mar 2026 16:38:19 -0700 Subject: [PATCH] Migration 1.17 first pass --- server/setup/scriptsPg/1.17.0.ts | 138 ++++++++++++++++++++++++++- server/setup/scriptsSqlite/1.17.0.ts | 119 ++++++++++++++++++++++- 2 files changed, 251 insertions(+), 6 deletions(-) diff --git a/server/setup/scriptsPg/1.17.0.ts b/server/setup/scriptsPg/1.17.0.ts index 81c42e1a9..d953b24fb 100644 --- a/server/setup/scriptsPg/1.17.0.ts +++ b/server/setup/scriptsPg/1.17.0.ts @@ -23,6 +23,66 @@ export default async function migration() { try { await db.execute(sql`BEGIN`); + await db.execute(sql` + CREATE TABLE "bannedEmails" ( + "email" varchar(255) PRIMARY KEY NOT NULL + ); + `); + + await db.execute(sql` + CREATE TABLE "bannedIps" ( + "ip" varchar(255) PRIMARY KEY NOT NULL + ); + `); + + await db.execute(sql` + CREATE TABLE "connectionAuditLog" ( + "id" serial PRIMARY KEY NOT NULL, + "sessionId" text NOT NULL, + "siteResourceId" integer, + "orgId" text, + "siteId" integer, + "clientId" integer, + "userId" text, + "sourceAddr" text NOT NULL, + "destAddr" text NOT NULL, + "protocol" text NOT NULL, + "startedAt" integer NOT NULL, + "endedAt" integer, + "bytesTx" integer, + "bytesRx" integer + ); + `); + + await db.execute(sql` + CREATE TABLE "siteProvisioningKeyOrg" ( + "siteProvisioningKeyId" varchar(255) NOT NULL, + "orgId" varchar(255) NOT NULL, + CONSTRAINT "siteProvisioningKeyOrg_siteProvisioningKeyId_orgId_pk" PRIMARY KEY("siteProvisioningKeyId","orgId") + ); + `); + await db.execute(sql` + CREATE TABLE "siteProvisioningKeys" ( + "siteProvisioningKeyId" varchar(255) PRIMARY KEY NOT NULL, + "name" varchar(255) NOT NULL, + "siteProvisioningKeyHash" text NOT NULL, + "lastChars" varchar(4) NOT NULL, + "dateCreated" varchar(255) NOT NULL, + "lastUsed" varchar(255), + "maxBatchSize" integer, + "numUsed" integer DEFAULT 0 NOT NULL, + "validUntil" varchar(255) + ); + `); + + await db.execute(sql` + CREATE TABLE "userInviteRoles" ( + "inviteId" varchar NOT NULL, + "roleId" integer NOT NULL, + CONSTRAINT "userInviteRoles_inviteId_roleId_pk" PRIMARY KEY("inviteId","roleId") + ); + `); + await db.execute(sql` CREATE TABLE "userOrgRoles" ( "userId" varchar NOT NULL, @@ -31,12 +91,80 @@ export default async function migration() { CONSTRAINT "userOrgRoles_userId_orgId_roleId_unique" UNIQUE("userId","orgId","roleId") ); `); - await db.execute(sql`ALTER TABLE "userOrgs" DROP CONSTRAINT "userOrgs_roleId_roles_roleId_fk";`); - await db.execute(sql`ALTER TABLE "userOrgRoles" ADD CONSTRAINT "userOrgRoles_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;`); - await db.execute(sql`ALTER TABLE "userOrgRoles" ADD CONSTRAINT "userOrgRoles_orgId_orgs_orgId_fk" FOREIGN KEY ("orgId") REFERENCES "public"."orgs"("orgId") ON DELETE cascade ON UPDATE no action;`); - await db.execute(sql`ALTER TABLE "userOrgRoles" ADD CONSTRAINT "userOrgRoles_roleId_roles_roleId_fk" FOREIGN KEY ("roleId") REFERENCES "public"."roles"("roleId") ON DELETE cascade ON UPDATE no action;`); + await db.execute( + sql`ALTER TABLE "userOrgs" DROP CONSTRAINT "userOrgs_roleId_roles_roleId_fk";` + ); + await db.execute( + sql`ALTER TABLE "userOrgRoles" ADD CONSTRAINT "userOrgRoles_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "userOrgRoles" ADD CONSTRAINT "userOrgRoles_orgId_orgs_orgId_fk" FOREIGN KEY ("orgId") REFERENCES "public"."orgs"("orgId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "userOrgRoles" ADD CONSTRAINT "userOrgRoles_roleId_roles_roleId_fk" FOREIGN KEY ("roleId") REFERENCES "public"."roles"("roleId") ON DELETE cascade ON UPDATE no action;` + ); await db.execute(sql`ALTER TABLE "userOrgs" DROP COLUMN "roleId";`); + await db.execute( + sql`ALTER TABLE "userInvites" DROP CONSTRAINT "userInvites_roleId_roles_roleId_fk";` + ); + await db.execute( + sql`ALTER TABLE "accessAuditLog" ADD COLUMN "siteResourceId" integer;` + ); + await db.execute( + sql`ALTER TABLE "clientSitesAssociationsCache" ADD COLUMN "isJitMode" boolean DEFAULT false NOT NULL;` + ); + await db.execute( + sql`ALTER TABLE "domains" ADD COLUMN "errorMessage" text;` + ); + await db.execute( + sql`ALTER TABLE "orgs" ADD COLUMN "settingsLogRetentionDaysConnection" integer DEFAULT 0 NOT NULL;` + ); + await db.execute( + sql`ALTER TABLE "sites" ADD COLUMN "lastPing" integer;` + ); + await db.execute( + sql`ALTER TABLE "user" ADD COLUMN "marketingEmailConsent" boolean DEFAULT false;` + ); + await db.execute(sql`ALTER TABLE "user" ADD COLUMN "locale" varchar;`); + await db.execute( + sql`ALTER TABLE "connectionAuditLog" ADD CONSTRAINT "connectionAuditLog_siteResourceId_siteResources_siteResourceId_fk" FOREIGN KEY ("siteResourceId") REFERENCES "public"."siteResources"("siteResourceId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "connectionAuditLog" ADD CONSTRAINT "connectionAuditLog_orgId_orgs_orgId_fk" FOREIGN KEY ("orgId") REFERENCES "public"."orgs"("orgId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "connectionAuditLog" ADD CONSTRAINT "connectionAuditLog_siteId_sites_siteId_fk" FOREIGN KEY ("siteId") REFERENCES "public"."sites"("siteId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "connectionAuditLog" ADD CONSTRAINT "connectionAuditLog_clientId_clients_clientId_fk" FOREIGN KEY ("clientId") REFERENCES "public"."clients"("clientId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "connectionAuditLog" ADD CONSTRAINT "connectionAuditLog_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "siteProvisioningKeyOrg" ADD CONSTRAINT "siteProvisioningKeyOrg_siteProvisioningKeyId_siteProvisioningKeys_siteProvisioningKeyId_fk" FOREIGN KEY ("siteProvisioningKeyId") REFERENCES "public"."siteProvisioningKeys"("siteProvisioningKeyId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "siteProvisioningKeyOrg" ADD CONSTRAINT "siteProvisioningKeyOrg_orgId_orgs_orgId_fk" FOREIGN KEY ("orgId") REFERENCES "public"."orgs"("orgId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "userInviteRoles" ADD CONSTRAINT "userInviteRoles_inviteId_userInvites_inviteId_fk" FOREIGN KEY ("inviteId") REFERENCES "public"."userInvites"("inviteId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`ALTER TABLE "userInviteRoles" ADD CONSTRAINT "userInviteRoles_roleId_roles_roleId_fk" FOREIGN KEY ("roleId") REFERENCES "public"."roles"("roleId") ON DELETE cascade ON UPDATE no action;` + ); + await db.execute( + sql`CREATE INDEX "idx_accessAuditLog_startedAt" ON "connectionAuditLog" USING btree ("startedAt");` + ); + await db.execute( + sql`CREATE INDEX "idx_accessAuditLog_org_startedAt" ON "connectionAuditLog" USING btree ("orgId","startedAt");` + ); + await db.execute( + sql`CREATE INDEX "idx_accessAuditLog_siteResourceId" ON "connectionAuditLog" USING btree ("siteResourceId");` + ); + await db.execute(sql`ALTER TABLE "userInvites" DROP COLUMN "roleId";`); + await db.execute(sql`COMMIT`); console.log("Migrated database"); } catch (e) { @@ -70,4 +198,4 @@ export default async function migration() { } console.log(`${version} migration complete`); -} \ No newline at end of file +} diff --git a/server/setup/scriptsSqlite/1.17.0.ts b/server/setup/scriptsSqlite/1.17.0.ts index fe7d82de0..866eb8fe5 100644 --- a/server/setup/scriptsSqlite/1.17.0.ts +++ b/server/setup/scriptsSqlite/1.17.0.ts @@ -25,6 +25,77 @@ export default async function migration() { ); db.transaction(() => { + db.prepare( + ` + CREATE TABLE 'bannedEmails' ( + 'email' text PRIMARY KEY NOT NULL + ); + ` + ).run(); + db.prepare( + ` + CREATE TABLE 'bannedIps' ( + 'ip' text PRIMARY KEY NOT NULL + ); + ` + ).run(); + db.prepare( + ` + CREATE TABLE 'connectionAuditLog' ( + 'id' integer PRIMARY KEY AUTOINCREMENT NOT NULL, + 'sessionId' text NOT NULL, + 'siteResourceId' integer, + 'orgId' text, + 'siteId' integer, + 'clientId' integer, + 'userId' text, + 'sourceAddr' text NOT NULL, + 'destAddr' text NOT NULL, + 'protocol' text NOT NULL, + 'startedAt' integer NOT NULL, + 'endedAt' integer, + 'bytesTx' integer, + 'bytesRx' integer, + FOREIGN KEY ('siteResourceId') REFERENCES 'siteResources'('siteResourceId') ON UPDATE no action ON DELETE cascade, + FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade, + FOREIGN KEY ('siteId') REFERENCES 'sites'('siteId') ON UPDATE no action ON DELETE cascade, + FOREIGN KEY ('clientId') REFERENCES 'clients'('clientId') ON UPDATE no action ON DELETE cascade, + FOREIGN KEY ('userId') REFERENCES 'user'('id') ON UPDATE no action ON DELETE cascade + ); + ` + ).run(); + + db.prepare(`CREATE INDEX 'idx_accessAuditLog_startedAt' ON 'connectionAuditLog' ('startedAt');`).run(); + db.prepare(`CREATE INDEX 'idx_accessAuditLog_org_startedAt' ON 'connectionAuditLog' ('orgId','startedAt');`).run(); + db.prepare(`CREATE INDEX 'idx_accessAuditLog_siteResourceId' ON 'connectionAuditLog' ('siteResourceId');`).run(); + + db.prepare( + ` + CREATE TABLE 'siteProvisioningKeyOrg' ( + 'siteProvisioningKeyId' text NOT NULL, + 'orgId' text NOT NULL, + PRIMARY KEY('siteProvisioningKeyId', 'orgId'), + FOREIGN KEY ('siteProvisioningKeyId') REFERENCES 'siteProvisioningKeys'('siteProvisioningKeyId') ON UPDATE no action ON DELETE cascade, + FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade + ); + ` + ).run(); + db.prepare( + ` + CREATE TABLE 'siteProvisioningKeys' ( + 'siteProvisioningKeyId' text PRIMARY KEY NOT NULL, + 'name' text NOT NULL, + 'siteProvisioningKeyHash' text NOT NULL, + 'lastChars' text NOT NULL, + 'dateCreated' text NOT NULL, + 'lastUsed' text, + 'maxBatchSize' integer, + 'numUsed' integer DEFAULT 0 NOT NULL, + 'validUntil' text + ); + ` + ).run(); + db.prepare( ` CREATE TABLE 'userOrgRoles' ( @@ -63,6 +134,52 @@ export default async function migration() { db.prepare( `ALTER TABLE '__new_userOrgs' RENAME TO 'userOrgs';` ).run(); + db.prepare( + ` + CREATE TABLE 'userInviteRoles' ( + 'inviteId' text NOT NULL, + 'roleId' integer NOT NULL, + PRIMARY KEY('inviteId', 'roleId'), + FOREIGN KEY ('inviteId') REFERENCES 'userInvites'('inviteId') ON UPDATE no action ON DELETE cascade, + FOREIGN KEY ('roleId') REFERENCES 'roles'('roleId') ON UPDATE no action ON DELETE cascade + ); + ` + ).run(); + db.prepare( + ` + CREATE TABLE '__new_userInvites' ( + 'inviteId' text PRIMARY KEY NOT NULL, + 'orgId' text NOT NULL, + 'email' text NOT NULL, + 'expiresAt' integer NOT NULL, + 'token' text NOT NULL, + FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade + ); + ` + ).run(); + db.prepare( + `INSERT INTO '__new_userInvites'("inviteId", "orgId", "email", "expiresAt", "token") SELECT "inviteId", "orgId", "email", "expiresAt", "token" FROM 'userInvites';` + ).run(); + db.prepare(`DROP TABLE 'userInvites';`).run(); + db.prepare( + `ALTER TABLE '__new_userInvites' RENAME TO 'userInvites';` + ).run(); + + db.prepare( + `ALTER TABLE 'accessAuditLog' ADD 'siteResourceId' integer;` + ).run(); + db.prepare( + `ALTER TABLE 'clientSitesAssociationsCache' ADD 'isJitMode' integer DEFAULT false NOT NULL;` + ).run(); + db.prepare(`ALTER TABLE 'domains' ADD 'errorMessage' text;`).run(); + db.prepare( + `ALTER TABLE 'orgs' ADD 'settingsLogRetentionDaysConnection' integer DEFAULT 0 NOT NULL;` + ).run(); + db.prepare(`ALTER TABLE 'sites' ADD 'lastPing' integer;`).run(); + db.prepare( + `ALTER TABLE 'user' ADD 'marketingEmailConsent' integer DEFAULT false;` + ).run(); + db.prepare(`ALTER TABLE 'user' ADD 'locale' text;`).run(); })(); db.pragma("foreign_keys = ON"); @@ -93,4 +210,4 @@ export default async function migration() { } console.log(`${version} migration complete`); -} \ No newline at end of file +}