From d4cfd0b6ede625a12033f2ebd71813b5e1bed3bb Mon Sep 17 00:00:00 2001 From: = Date: Sat, 16 Nov 2024 00:37:57 +0530 Subject: [PATCH 1/2] fix: migration in loop due to cornercase --- ...14084900_identity-multiple-auth-methods.ts | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts b/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts index 821132e1e8..dc83d231eb 100644 --- a/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts +++ b/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts @@ -2,7 +2,7 @@ import { Knex } from "knex"; import { TableName } from "../schemas"; -const BATCH_SIZE = 30_000; +const BATCH_SIZE = 10_000; export async function up(knex: Knex): Promise { const hasAuthMethodColumnAccessToken = await knex.schema.hasColumn(TableName.IdentityAccessToken, "authMethod"); @@ -12,7 +12,25 @@ export async function up(knex: Knex): Promise { t.string("authMethod").nullable(); }); - let nullableAccessTokens = await knex(TableName.IdentityAccessToken).whereNull("authMethod").limit(BATCH_SIZE); + // first we remove identities without auth method that is unused + let nullableAuthMethodIdentities = []; + do { + const findNullableAuthMethodIdentities = knex(TableName.Identity) + .whereNull("authMethod") + .limit(BATCH_SIZE) + .select("id"); + + // eslint-disable-next-line no-await-in-loop + nullableAuthMethodIdentities = await knex(TableName.Identity) + .whereIn("id", findNullableAuthMethodIdentities) + .del() + .returning("id"); + } while (nullableAuthMethodIdentities.length > 0); + + let nullableAccessTokens = await knex(TableName.IdentityAccessToken) + .whereNull("authMethod") + .limit(BATCH_SIZE) + .select("id"); let totalUpdated = 0; do { @@ -33,7 +51,10 @@ export async function up(knex: Knex): Promise { }); // eslint-disable-next-line no-await-in-loop - nullableAccessTokens = await knex(TableName.IdentityAccessToken).whereNull("authMethod").limit(BATCH_SIZE); + nullableAccessTokens = await knex(TableName.IdentityAccessToken) + .whereNull("authMethod") + .limit(BATCH_SIZE) + .select("id"); totalUpdated += batchIds.length; console.log(`Updated ${batchIds.length} access tokens in batch <> Total updated: ${totalUpdated}`); From 2027d4b44e932ab04bcd3b377ae5ecd73f0a7a9c Mon Sep 17 00:00:00 2001 From: = Date: Tue, 19 Nov 2024 02:17:25 +0530 Subject: [PATCH 2/2] feat: moved auth method deletion to top --- ...14084900_identity-multiple-auth-methods.ts | 31 ++++--------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts b/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts index dc83d231eb..7a6bd3e1fe 100644 --- a/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts +++ b/backend/src/db/migrations/20241014084900_identity-multiple-auth-methods.ts @@ -13,19 +13,12 @@ export async function up(knex: Knex): Promise { }); // first we remove identities without auth method that is unused - let nullableAuthMethodIdentities = []; - do { - const findNullableAuthMethodIdentities = knex(TableName.Identity) - .whereNull("authMethod") - .limit(BATCH_SIZE) - .select("id"); - - // eslint-disable-next-line no-await-in-loop - nullableAuthMethodIdentities = await knex(TableName.Identity) - .whereIn("id", findNullableAuthMethodIdentities) - .del() - .returning("id"); - } while (nullableAuthMethodIdentities.length > 0); + // ! We delete all access tokens where the identity has no auth method set! + // ! Which means un-configured identities that for some reason have access tokens, will have their access tokens deleted. + await knex(TableName.IdentityAccessToken) + .leftJoin(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityAccessToken}.identityId`) + .whereNull(`${TableName.Identity}.authMethod`) + .delete(); let nullableAccessTokens = await knex(TableName.IdentityAccessToken) .whereNull("authMethod") @@ -60,18 +53,6 @@ export async function up(knex: Knex): Promise { console.log(`Updated ${batchIds.length} access tokens in batch <> Total updated: ${totalUpdated}`); } while (nullableAccessTokens.length > 0); - // ! We delete all access tokens where the identity has no auth method set! - // ! Which means un-configured identities that for some reason have access tokens, will have their access tokens deleted. - await knex(TableName.IdentityAccessToken) - .whereNotExists((queryBuilder) => { - void queryBuilder - .select("id") - .from(TableName.Identity) - .whereRaw(`${TableName.IdentityAccessToken}."identityId" = ${TableName.Identity}.id`) - .whereNotNull("authMethod"); - }) - .delete(); - // Finally we set the authMethod to notNullable after populating the column. // This will fail if the data is not populated correctly, so it's safe. await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => {