Add migration

This commit is contained in:
Owen
2026-03-28 21:41:21 -07:00
parent 6f71af278e
commit 8e821b397f
2 changed files with 121 additions and 2 deletions

View File

@@ -6,9 +6,37 @@ const version = "1.17.0";
export default async function migration() {
console.log(`Running setup script ${version}...`);
// Query existing roleId data from userOrgs before the transaction destroys it
const existingRolesQuery = await db.execute(
sql`SELECT "userId", "orgId", "roleId" FROM "userOrgs" WHERE "roleId" IS NOT NULL`
);
const existingUserOrgRoles = existingRolesQuery.rows as {
userId: string;
orgId: string;
roleId: number;
}[];
console.log(
`Found ${existingUserOrgRoles.length} existing userOrgs role assignment(s) to migrate`
);
try {
await db.execute(sql`BEGIN`);
await db.execute(sql`
CREATE TABLE "userOrgRoles" (
"userId" varchar NOT NULL,
"orgId" varchar NOT NULL,
"roleId" integer NOT NULL,
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 COLUMN "roleId";`);
await db.execute(sql`COMMIT`);
console.log("Migrated database");
} catch (e) {
@@ -18,5 +46,28 @@ export default async function migration() {
throw e;
}
// Re-insert the preserved role assignments into the new userOrgRoles table
if (existingUserOrgRoles.length > 0) {
try {
for (const row of existingUserOrgRoles) {
await db.execute(sql`
INSERT INTO "userOrgRoles" ("userId", "orgId", "roleId")
VALUES (${row.userId}, ${row.orgId}, ${row.roleId})
ON CONFLICT DO NOTHING
`);
}
console.log(
`Migrated ${existingUserOrgRoles.length} role assignment(s) into userOrgRoles`
);
} catch (e) {
console.error(
"Error while migrating role assignments into userOrgRoles:",
e
);
throw e;
}
}
console.log(`${version} migration complete`);
}
}

View File

@@ -13,11 +13,79 @@ export default async function migration() {
try {
db.pragma("foreign_keys = OFF");
// Query existing roleId data from userOrgs before the transaction destroys it
const existingUserOrgRoles = db
.prepare(
`SELECT "userId", "orgId", "roleId" FROM 'userOrgs' WHERE "roleId" IS NOT NULL`
)
.all() as { userId: string; orgId: string; roleId: number }[];
console.log(
`Found ${existingUserOrgRoles.length} existing userOrgs role assignment(s) to migrate`
);
db.transaction(() => {
db.prepare(
`
CREATE TABLE 'userOrgRoles' (
'userId' text NOT NULL,
'orgId' text NOT NULL,
'roleId' integer NOT NULL,
FOREIGN KEY ('userId') REFERENCES 'user'('id') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('roleId') REFERENCES 'roles'('roleId') ON UPDATE no action ON DELETE cascade
);
`
).run();
db.prepare(
`CREATE UNIQUE INDEX 'userOrgRoles_userId_orgId_roleId_unique' ON 'userOrgRoles' ('userId','orgId','roleId');`
).run();
db.prepare(
`
CREATE TABLE '__new_userOrgs' (
'userId' text NOT NULL,
'orgId' text NOT NULL,
'isOwner' integer DEFAULT false NOT NULL,
'autoProvisioned' integer DEFAULT false,
'pamUsername' text,
FOREIGN KEY ('userId') REFERENCES 'user'('id') ON UPDATE no action ON DELETE cascade,
FOREIGN KEY ('orgId') REFERENCES 'orgs'('orgId') ON UPDATE no action ON DELETE cascade
);
`
).run();
db.prepare(
`INSERT INTO '__new_userOrgs'("userId", "orgId", "isOwner", "autoProvisioned", "pamUsername") SELECT "userId", "orgId", "isOwner", "autoProvisioned", "pamUsername" FROM 'userOrgs';`
).run();
db.prepare(`DROP TABLE 'userOrgs';`).run();
db.prepare(
`ALTER TABLE '__new_userOrgs' RENAME TO 'userOrgs';`
).run();
})();
db.pragma("foreign_keys = ON");
// Re-insert the preserved role assignments into the new userOrgRoles table
if (existingUserOrgRoles.length > 0) {
const insertUserOrgRole = db.prepare(
`INSERT OR IGNORE INTO 'userOrgRoles' ("userId", "orgId", "roleId") VALUES (?, ?, ?)`
);
const insertAll = db.transaction(() => {
for (const row of existingUserOrgRoles) {
insertUserOrgRole.run(row.userId, row.orgId, row.roleId);
}
});
insertAll();
console.log(
`Migrated ${existingUserOrgRoles.length} role assignment(s) into userOrgRoles`
);
}
console.log(`Migrated database`);
} catch (e) {
console.log("Failed to migrate db:", e);
@@ -25,4 +93,4 @@ export default async function migration() {
}
console.log(`${version} migration complete`);
}
}