diff --git a/src/main/java/io/supertokens/inmemorydb/Start.java b/src/main/java/io/supertokens/inmemorydb/Start.java index 35bf45ce0..2ce5aee4a 100644 --- a/src/main/java/io/supertokens/inmemorydb/Start.java +++ b/src/main/java/io/supertokens/inmemorydb/Start.java @@ -26,6 +26,7 @@ import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; import io.supertokens.pluginInterface.authRecipe.LoginMethod; import io.supertokens.pluginInterface.authRecipe.sqlStorage.AuthRecipeSQLStorage; +import io.supertokens.pluginInterface.bulkimport.BulkImportStorage; import io.supertokens.pluginInterface.dashboard.DashboardSearchTags; import io.supertokens.pluginInterface.dashboard.DashboardSessionInfo; import io.supertokens.pluginInterface.dashboard.DashboardUser; @@ -733,6 +734,8 @@ public void addInfoToNonAuthRecipesBasedOnUserId(TenantIdentifier tenantIdentifi } } else if (className.equals(JWTRecipeStorage.class.getName())) { /* Since JWT recipe tables do not store userId we do not add any data to them */ + } else if (className.equals(BulkImportStorage.class.getName())){ + //ignore } else if (className.equals(ActiveUsersStorage.class.getName())) { try { ActiveUsersQueries.updateUserLastActive(this, tenantIdentifier.toAppIdentifier(), userId); diff --git a/src/test/java/io/supertokens/test/CronjobTest.java b/src/test/java/io/supertokens/test/CronjobTest.java index 6d72addb8..24e8ce7a5 100644 --- a/src/test/java/io/supertokens/test/CronjobTest.java +++ b/src/test/java/io/supertokens/test/CronjobTest.java @@ -22,6 +22,7 @@ import io.supertokens.cronjobs.CronTask; import io.supertokens.cronjobs.CronTaskTest; import io.supertokens.cronjobs.Cronjobs; +import io.supertokens.cronjobs.bulkimport.ProcessBulkImportUsers; import io.supertokens.cronjobs.syncCoreConfigWithDb.SyncCoreConfigWithDb; import io.supertokens.exceptions.QuitProgramException; import io.supertokens.featureflag.EE_FEATURES; @@ -965,7 +966,7 @@ public void testThatCronJobsHaveTenantsInfoAfterRestart() throws Exception { { List>> tenantsInfos = Cronjobs.getInstance(process.getProcess()) .getTenantInfos(); - assertEquals(10, tenantsInfos.size()); + assertEquals(11, tenantsInfos.size()); int count = 0; for (List> tenantsInfo : tenantsInfos) { if (tenantsInfo != null) { @@ -975,7 +976,7 @@ public void testThatCronJobsHaveTenantsInfoAfterRestart() throws Exception { count++; } } - assertEquals(9, count); + assertEquals(10, count); } process.kill(false); @@ -992,7 +993,7 @@ public void testThatCronJobsHaveTenantsInfoAfterRestart() throws Exception { { List>> tenantsInfos = Cronjobs.getInstance(process.getProcess()) .getTenantInfos(); - assertEquals(10, tenantsInfos.size()); + assertEquals(11, tenantsInfos.size()); int count = 0; for (List> tenantsInfo : tenantsInfos) { if (tenantsInfo != null) { @@ -1002,7 +1003,7 @@ public void testThatCronJobsHaveTenantsInfoAfterRestart() throws Exception { count++; } } - assertEquals(9, count); + assertEquals(10, count); } process.kill(); @@ -1049,6 +1050,7 @@ public void testThatThereAreTasksOfAllCronTaskClassesAndHaveCorrectIntervals() t intervals.put("io.supertokens.cronjobs.telemetry.Telemetry", 86400); intervals.put("io.supertokens.cronjobs.deleteExpiredAccessTokenSigningKeys.DeleteExpiredAccessTokenSigningKeys", 86400); + intervals.put("io.supertokens.cronjobs.bulkimport.ProcessBulkImportUsers", 60); Map delays = new HashMap<>(); delays.put("io.supertokens.ee.cronjobs.EELicenseCheck", 86400); @@ -1063,9 +1065,10 @@ public void testThatThereAreTasksOfAllCronTaskClassesAndHaveCorrectIntervals() t delays.put("io.supertokens.cronjobs.telemetry.Telemetry", 0); delays.put("io.supertokens.cronjobs.deleteExpiredAccessTokenSigningKeys.DeleteExpiredAccessTokenSigningKeys", 0); + delays.put("io.supertokens.cronjobs.bulkimport.ProcessBulkImportUsers", 0); List allTasks = Cronjobs.getInstance(process.getProcess()).getTasks(); - assertEquals(10, allTasks.size()); + assertEquals(11, allTasks.size()); for (CronTask task : allTasks) { assertEquals(intervals.get(task.getClass().getName()).intValue(), task.getIntervalTimeSeconds()); diff --git a/src/test/java/io/supertokens/test/bulkimport/ProcessBulkImportUsersCronJobTest.java b/src/test/java/io/supertokens/test/bulkimport/ProcessBulkImportUsersCronJobTest.java index 97f14daf4..c948a9457 100644 --- a/src/test/java/io/supertokens/test/bulkimport/ProcessBulkImportUsersCronJobTest.java +++ b/src/test/java/io/supertokens/test/bulkimport/ProcessBulkImportUsersCronJobTest.java @@ -259,7 +259,7 @@ public void shouldProcessBulkImportUsersInMultipleTenantsWithDifferentStorages() @Test public void shouldProcessBulkImportUsersInLargeNumberInMultipleTenantsWithDifferentStorages() throws Exception { - Utils.setValueInConfig("bulk_migration_parallelism", "8"); + Utils.setValueInConfig("bulk_migration_parallelism", "12"); TestingProcess process = startCronProcess(); Main main = process.getProcess(); diff --git a/src/test/java/io/supertokens/test/multitenant/AppTenantUserTest.java b/src/test/java/io/supertokens/test/multitenant/AppTenantUserTest.java index 0dc0f0565..b2913796d 100644 --- a/src/test/java/io/supertokens/test/multitenant/AppTenantUserTest.java +++ b/src/test/java/io/supertokens/test/multitenant/AppTenantUserTest.java @@ -27,6 +27,7 @@ import io.supertokens.pluginInterface.STORAGE_TYPE; import io.supertokens.pluginInterface.Storage; import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; +import io.supertokens.pluginInterface.bulkimport.BulkImportStorage; import io.supertokens.pluginInterface.multitenancy.*; import io.supertokens.pluginInterface.nonAuthRecipe.NonAuthRecipeStorage; import io.supertokens.storageLayer.StorageLayer; @@ -77,7 +78,8 @@ public void testDeletingAppDeleteNonAuthRecipeData() throws Exception { // this list contains the package names for recipes which dont use UserIdMapping ArrayList classesToSkip = new ArrayList<>( - List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName())); + List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName(), + BulkImportStorage.class.getName())); Reflections reflections = new Reflections("io.supertokens.pluginInterface"); Set> classes = reflections.getSubTypesOf(NonAuthRecipeStorage.class); @@ -182,7 +184,8 @@ public void testDisassociationOfUserDeletesNonAuthRecipeData() throws Exception // this list contains the package names for recipes which dont use UserIdMapping ArrayList classesToSkip = new ArrayList<>( - List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName())); + List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName(), + BulkImportStorage.class.getName())); Reflections reflections = new Reflections("io.supertokens.pluginInterface"); Set> classes = reflections.getSubTypesOf(NonAuthRecipeStorage.class); diff --git a/src/test/java/io/supertokens/test/multitenant/TestAppData.java b/src/test/java/io/supertokens/test/multitenant/TestAppData.java index dd2315aed..14047a72e 100644 --- a/src/test/java/io/supertokens/test/multitenant/TestAppData.java +++ b/src/test/java/io/supertokens/test/multitenant/TestAppData.java @@ -21,6 +21,7 @@ import io.supertokens.ActiveUsers; import io.supertokens.Main; import io.supertokens.ProcessState; +import io.supertokens.bulkimport.BulkImport; import io.supertokens.dashboard.Dashboard; import io.supertokens.emailpassword.EmailPassword; import io.supertokens.emailverification.EmailVerification; @@ -31,6 +32,8 @@ import io.supertokens.pluginInterface.STORAGE_TYPE; import io.supertokens.pluginInterface.Storage; import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; +import io.supertokens.pluginInterface.bulkimport.BulkImportStorage; +import io.supertokens.pluginInterface.bulkimport.BulkImportUser; import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.*; import io.supertokens.pluginInterface.totp.TOTPDevice; @@ -38,6 +41,7 @@ import io.supertokens.storageLayer.StorageLayer; import io.supertokens.test.TestingProcessManager; import io.supertokens.test.Utils; +import io.supertokens.test.bulkimport.BulkImportTestUtils; import io.supertokens.thirdparty.ThirdParty; import io.supertokens.totp.Totp; import io.supertokens.useridmapping.UserIdMapping; @@ -55,6 +59,7 @@ import java.security.Key; import java.time.Duration; import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; import static org.junit.Assert.assertEquals; @@ -174,6 +179,8 @@ null, null, new JsonObject() UserIdMapping.createUserIdMapping(process.getProcess(), app.toAppIdentifier(), appStorage, plUser.user.getSupertokensUserId(), "externalid", null, false); + BulkImport.addUsers(app.toAppIdentifier(), appStorage, BulkImportTestUtils.generateBulkImportUser(1)); + String[] tablesThatHaveData = appStorage .getAllTablesInTheDatabaseThatHasDataForAppId(app.getAppId()); tablesThatHaveData = removeStrings(tablesThatHaveData, tablesToIgnore); diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestTenantUserAssociation.java b/src/test/java/io/supertokens/test/multitenant/api/TestTenantUserAssociation.java index 6907017cb..ccc4c6181 100644 --- a/src/test/java/io/supertokens/test/multitenant/api/TestTenantUserAssociation.java +++ b/src/test/java/io/supertokens/test/multitenant/api/TestTenantUserAssociation.java @@ -31,6 +31,7 @@ import io.supertokens.pluginInterface.STORAGE_TYPE; import io.supertokens.pluginInterface.Storage; import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; +import io.supertokens.pluginInterface.bulkimport.BulkImportStorage; import io.supertokens.pluginInterface.exceptions.InvalidConfigException; import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.jwt.JWTRecipeStorage; @@ -199,10 +200,12 @@ public void testUserDisassociationForNotAuthRecipes() throws Exception { if (name.equals(UserMetadataStorage.class.getName()) || name.equals(JWTRecipeStorage.class.getName()) || name.equals(ActiveUsersStorage.class.getName()) + || name.equals(BulkImportStorage.class.getName()) ) { // user metadata is app specific and does not have any tenant specific data // JWT storage does not have any user specific data // Active users storage does not have tenant specific data + // BulkImportStorage continue; } diff --git a/src/test/java/io/supertokens/test/userIdMapping/UserIdMappingTest.java b/src/test/java/io/supertokens/test/userIdMapping/UserIdMappingTest.java index 014c1c6e9..13868666e 100644 --- a/src/test/java/io/supertokens/test/userIdMapping/UserIdMappingTest.java +++ b/src/test/java/io/supertokens/test/userIdMapping/UserIdMappingTest.java @@ -25,6 +25,7 @@ import io.supertokens.pluginInterface.ActiveUsersStorage; import io.supertokens.pluginInterface.STORAGE_TYPE; import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; +import io.supertokens.pluginInterface.bulkimport.BulkImportStorage; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; import io.supertokens.pluginInterface.nonAuthRecipe.NonAuthRecipeStorage; @@ -800,7 +801,8 @@ public void checkThatCreateUserIdMappingHasAllNonAuthRecipeChecks() throws Excep // this list contains the package names for recipes which dont use UserIdMapping ArrayList nonAuthRecipesWhichDontNeedUserIdMapping = new ArrayList<>( - List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName())); + List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName(), + BulkImportStorage.class.getName())); Reflections reflections = new Reflections("io.supertokens.pluginInterface"); Set> classes = reflections.getSubTypesOf(NonAuthRecipeStorage.class); @@ -881,7 +883,7 @@ public void checkThatDeleteUserIdMappingHasAllNonAuthRecipeChecks() throws Excep } ArrayList nonAuthRecipesWhichDontNeedUserIdMapping = new ArrayList<>( - List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName())); + List.of("io.supertokens.pluginInterface.jwt.JWTRecipeStorage", ActiveUsersStorage.class.getName(), BulkImportStorage.class.getName())); Reflections reflections = new Reflections("io.supertokens.pluginInterface"); Set> classes = reflections.getSubTypesOf(NonAuthRecipeStorage.class); List names = classes.stream().map(Class::getCanonicalName).collect(Collectors.toList());