From 8f6ba1416a74cee34c551dde1ec13ce5960e5e8e Mon Sep 17 00:00:00 2001 From: tamassoltesz Date: Fri, 22 Nov 2024 17:09:10 +0100 Subject: [PATCH] fix: fixes and error handling changes --- .../supertokens/pluginInterface/Storage.java | 4 ++ .../authRecipe/AuthRecipeStorage.java | 3 ++ .../sqlStorage/AuthRecipeSQLStorage.java | 7 ++++ .../BulkImportBatchInsertException.java | 40 +++++++++++++++++++ .../sqlStorage/BulkImportSQLStorage.java | 10 +++-- .../emailpassword/EmailPasswordStorage.java | 7 ---- .../sqlStorage/EmailPasswordSQLStorage.java | 7 ++++ .../EmailVerificationStorage.java | 5 +++ .../sqlStorage/PasswordlessSQLStorage.java | 7 ++-- .../sqlStorage/SQLStorage.java | 5 ++- .../sqlStorage/ThirdPartySQLStorage.java | 8 ++-- .../useridmapping/UserIdMappingStorage.java | 5 +++ .../sqlStorage/UserIdMappingSQLStorage.java | 6 +++ .../sqlStorage/UserRolesSQLStorage.java | 4 ++ 14 files changed, 101 insertions(+), 17 deletions(-) create mode 100644 src/main/java/io/supertokens/pluginInterface/bulkimport/exceptions/BulkImportBatchInsertException.java diff --git a/src/main/java/io/supertokens/pluginInterface/Storage.java b/src/main/java/io/supertokens/pluginInterface/Storage.java index 56f253f9..a5adca1d 100644 --- a/src/main/java/io/supertokens/pluginInterface/Storage.java +++ b/src/main/java/io/supertokens/pluginInterface/Storage.java @@ -26,6 +26,7 @@ import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import java.util.List; +import java.util.Map; import java.util.Set; public interface Storage { @@ -80,6 +81,9 @@ void setKeyValue(TenantIdentifier tenantIdentifier, String key, KeyValueInfo inf boolean isUserIdBeingUsedInNonAuthRecipe(AppIdentifier appIdentifier, String className, String userId) throws StorageQueryException; + Map> findNonAuthRecipesWhereForUserIdsUsed(AppIdentifier appIdentifier, List userIds) + throws StorageQueryException; + // to be used for testing purposes only. This function will add dummy data to non-auth tables. void addInfoToNonAuthRecipesBasedOnUserId(TenantIdentifier tenantIdentifier, String className, String userId) throws StorageQueryException; diff --git a/src/main/java/io/supertokens/pluginInterface/authRecipe/AuthRecipeStorage.java b/src/main/java/io/supertokens/pluginInterface/authRecipe/AuthRecipeStorage.java index 701b8130..9eeef263 100644 --- a/src/main/java/io/supertokens/pluginInterface/authRecipe/AuthRecipeStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/authRecipe/AuthRecipeStorage.java @@ -26,6 +26,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public interface AuthRecipeStorage extends Storage { @@ -45,6 +46,8 @@ AuthRecipeUserInfo[] getUsers(TenantIdentifier tenantIdentifier, @Nonnull Intege boolean doesUserIdExist(TenantIdentifier tenantIdentifierIdentifier, String userId) throws StorageQueryException; + List findExistingUserIds(AppIdentifier appIdentifier, List userIds) throws StorageQueryException; + AuthRecipeUserInfo getPrimaryUserById(AppIdentifier appIdentifier, String userId) throws StorageQueryException; String getPrimaryUserIdStrForUserId(AppIdentifier appIdentifier, String userId) throws StorageQueryException; diff --git a/src/main/java/io/supertokens/pluginInterface/authRecipe/sqlStorage/AuthRecipeSQLStorage.java b/src/main/java/io/supertokens/pluginInterface/authRecipe/sqlStorage/AuthRecipeSQLStorage.java index f8d30058..6e5352f7 100644 --- a/src/main/java/io/supertokens/pluginInterface/authRecipe/sqlStorage/AuthRecipeSQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/authRecipe/sqlStorage/AuthRecipeSQLStorage.java @@ -45,6 +45,13 @@ AuthRecipeUserInfo[] listPrimaryUsersByEmail_Transaction(AppIdentifier appIdenti String email) throws StorageQueryException; + //helper method for bulk import + AuthRecipeUserInfo[] listPrimaryUsersByMultipleEmailsOrPhoneNumbersOrThirdparty_Transaction(AppIdentifier appIdentifier, + TransactionConnection con, + List emails, List phones, + Map thirdpartyIdToThirdpartyUserId) + throws StorageQueryException; + // locks only passwordless table AuthRecipeUserInfo[] listPrimaryUsersByPhoneNumber_Transaction(AppIdentifier appIdentifier, TransactionConnection con, String phoneNumber) diff --git a/src/main/java/io/supertokens/pluginInterface/bulkimport/exceptions/BulkImportBatchInsertException.java b/src/main/java/io/supertokens/pluginInterface/bulkimport/exceptions/BulkImportBatchInsertException.java new file mode 100644 index 00000000..fb55e18a --- /dev/null +++ b/src/main/java/io/supertokens/pluginInterface/bulkimport/exceptions/BulkImportBatchInsertException.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved. + * + * This software is licensed under the Apache License, Version 2.0 (the + * "License") as published by the Apache Software Foundation. + * + * You may not use this file except in compliance with the License. You may + * obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.supertokens.pluginInterface.bulkimport.exceptions; + +import java.util.Map; + +//In case of batch inserting when one +public class BulkImportBatchInsertException extends Exception { + public Map exceptionByUserId; + + public BulkImportBatchInsertException(String message, Map exceptionByPosition) { + super(message); + this.exceptionByUserId = exceptionByPosition; + } + + public BulkImportBatchInsertException(String message, Throwable cause, + Map exceptionByPosition) { + super(message, cause); + this.exceptionByUserId = exceptionByPosition; + } + + public BulkImportBatchInsertException(Throwable cause, Map exceptionByPosition) { + super(cause); + this.exceptionByUserId = exceptionByPosition; + } +} diff --git a/src/main/java/io/supertokens/pluginInterface/bulkimport/sqlStorage/BulkImportSQLStorage.java b/src/main/java/io/supertokens/pluginInterface/bulkimport/sqlStorage/BulkImportSQLStorage.java index a7d1fff3..d8cb6f3f 100644 --- a/src/main/java/io/supertokens/pluginInterface/bulkimport/sqlStorage/BulkImportSQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/bulkimport/sqlStorage/BulkImportSQLStorage.java @@ -16,15 +16,16 @@ package io.supertokens.pluginInterface.bulkimport.sqlStorage; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import io.supertokens.pluginInterface.bulkimport.BulkImportStorage; import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.pluginInterface.sqlStorage.SQLStorage; import io.supertokens.pluginInterface.sqlStorage.TransactionConnection; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Map; + public interface BulkImportSQLStorage extends BulkImportStorage, SQLStorage { /** @@ -32,4 +33,7 @@ public interface BulkImportSQLStorage extends BulkImportStorage, SQLStorage { */ void updateBulkImportUserStatus_Transaction(AppIdentifier appIdentifier, TransactionConnection con, @Nonnull String bulkImportUserId, @Nonnull BULK_IMPORT_USER_STATUS status, @Nullable String errorMessage) throws StorageQueryException; + + void updateMultipleBulkImportUsersStatusToError_Transaction(AppIdentifier appIdentifier, + TransactionConnection con, @Nonnull Map bulkImportUserIdToErrorMessage) throws StorageQueryException; } diff --git a/src/main/java/io/supertokens/pluginInterface/emailpassword/EmailPasswordStorage.java b/src/main/java/io/supertokens/pluginInterface/emailpassword/EmailPasswordStorage.java index 2f9a2c0b..1d4aee84 100644 --- a/src/main/java/io/supertokens/pluginInterface/emailpassword/EmailPasswordStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/emailpassword/EmailPasswordStorage.java @@ -23,13 +23,10 @@ import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateUserIdException; import io.supertokens.pluginInterface.emailpassword.exceptions.UnknownUserIdException; import io.supertokens.pluginInterface.exceptions.StorageQueryException; -import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; -import java.util.List; - public interface EmailPasswordStorage extends AuthRecipeStorage { // we pass tenantIdentifier here cause this also adds to the userId <-> tenantId mapping @@ -38,10 +35,6 @@ AuthRecipeUserInfo signUp(TenantIdentifier tenantIdentifier, String id, String e throws StorageQueryException, DuplicateUserIdException, DuplicateEmailException, TenantOrAppNotFoundException; - void signUpMultiple(List users) - throws StorageQueryException, DuplicateUserIdException, DuplicateEmailException, - TenantOrAppNotFoundException, StorageTransactionLogicException; - // password reset stuff is app wide cause changing the password for a user affects all the tenants // across which it's shared. void addPasswordResetToken(AppIdentifier appIdentifier, PasswordResetTokenInfo passwordResetTokenInfo) diff --git a/src/main/java/io/supertokens/pluginInterface/emailpassword/sqlStorage/EmailPasswordSQLStorage.java b/src/main/java/io/supertokens/pluginInterface/emailpassword/sqlStorage/EmailPasswordSQLStorage.java index af47334f..d212d8e1 100644 --- a/src/main/java/io/supertokens/pluginInterface/emailpassword/sqlStorage/EmailPasswordSQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/emailpassword/sqlStorage/EmailPasswordSQLStorage.java @@ -16,14 +16,18 @@ package io.supertokens.pluginInterface.emailpassword.sqlStorage; +import io.supertokens.pluginInterface.emailpassword.EmailPasswordImportUser; import io.supertokens.pluginInterface.emailpassword.EmailPasswordStorage; import io.supertokens.pluginInterface.emailpassword.PasswordResetTokenInfo; import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateEmailException; import io.supertokens.pluginInterface.exceptions.StorageQueryException; +import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.pluginInterface.sqlStorage.SQLStorage; import io.supertokens.pluginInterface.sqlStorage.TransactionConnection; +import java.util.List; + public interface EmailPasswordSQLStorage extends EmailPasswordStorage, SQLStorage { // all password reset related stuff is app wide cause the same user ID can be shared across tenants, @@ -49,4 +53,7 @@ void updateUsersEmail_Transaction(AppIdentifier appIdentifier, TransactionConnec void deleteEmailPasswordUser_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId, boolean deleteUserIdMappingToo) throws StorageQueryException; + + void signUpMultipleViaBulkImport_Transaction(TransactionConnection connection, List users) + throws StorageQueryException, StorageTransactionLogicException; } diff --git a/src/main/java/io/supertokens/pluginInterface/emailverification/EmailVerificationStorage.java b/src/main/java/io/supertokens/pluginInterface/emailverification/EmailVerificationStorage.java index 55d8b298..ade6b091 100644 --- a/src/main/java/io/supertokens/pluginInterface/emailverification/EmailVerificationStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/emailverification/EmailVerificationStorage.java @@ -23,6 +23,8 @@ import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.pluginInterface.nonAuthRecipe.NonAuthRecipeStorage; +import java.util.Map; + public interface EmailVerificationStorage extends NonAuthRecipeStorage { void addEmailVerificationToken(TenantIdentifier tenantIdentifier, EmailVerificationTokenInfo emailVerificationInfo) @@ -49,4 +51,7 @@ EmailVerificationTokenInfo[] getAllEmailVerificationTokenInfoForUser(TenantIdent void updateIsEmailVerifiedToExternalUserId(AppIdentifier appIdentifier, String supertokensUserId, String externalUserId) throws StorageQueryException; + + void updateMultipleIsEmailVerifiedToExternalUserIds(AppIdentifier appIdentifier, + Map supertokensUserIdToExternalUserId) throws StorageQueryException; } \ No newline at end of file diff --git a/src/main/java/io/supertokens/pluginInterface/passwordless/sqlStorage/PasswordlessSQLStorage.java b/src/main/java/io/supertokens/pluginInterface/passwordless/sqlStorage/PasswordlessSQLStorage.java index 1235366e..d6687a71 100644 --- a/src/main/java/io/supertokens/pluginInterface/passwordless/sqlStorage/PasswordlessSQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/passwordless/sqlStorage/PasswordlessSQLStorage.java @@ -21,6 +21,7 @@ import io.supertokens.pluginInterface.exceptions.StorageQueryException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.pluginInterface.passwordless.PasswordlessCode; import io.supertokens.pluginInterface.passwordless.PasswordlessDevice; import io.supertokens.pluginInterface.passwordless.PasswordlessImportUser; @@ -31,7 +32,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Collection; +import java.util.List; public interface PasswordlessSQLStorage extends PasswordlessStorage, SQLStorage { PasswordlessDevice getDevice_Transaction(TenantIdentifier tenantIdentifier, TransactionConnection con, @@ -88,6 +89,6 @@ void deletePasswordlessUser_Transaction(TransactionConnection con, AppIdentifier boolean deleteUserIdMappingToo) throws StorageQueryException; - void importPasswordlessUsers_Transaction(TransactionConnection con, Collection users) - throws StorageQueryException; + void importPasswordlessUsers_Transaction(TransactionConnection con, List users) + throws StorageQueryException, TenantOrAppNotFoundException; } diff --git a/src/main/java/io/supertokens/pluginInterface/sqlStorage/SQLStorage.java b/src/main/java/io/supertokens/pluginInterface/sqlStorage/SQLStorage.java index a5fa1259..a66d7801 100644 --- a/src/main/java/io/supertokens/pluginInterface/sqlStorage/SQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/sqlStorage/SQLStorage.java @@ -24,6 +24,8 @@ import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import java.sql.SQLException; + public interface SQLStorage extends Storage { T startTransaction(TransactionLogic logic, TransactionIsolationLevel isolationLevel) throws StorageQueryException, StorageTransactionLogicException; @@ -40,7 +42,8 @@ KeyValueInfo getKeyValue_Transaction(TenantIdentifier tenantIdentifier, Transact interface TransactionLogic { T mainLogicAndCommit(TransactionConnection con) - throws StorageQueryException, StorageTransactionLogicException, TenantOrAppNotFoundException; + throws StorageQueryException, StorageTransactionLogicException, TenantOrAppNotFoundException, + SQLException; } public enum TransactionIsolationLevel { diff --git a/src/main/java/io/supertokens/pluginInterface/thirdparty/sqlStorage/ThirdPartySQLStorage.java b/src/main/java/io/supertokens/pluginInterface/thirdparty/sqlStorage/ThirdPartySQLStorage.java index 3e022a16..c0f17215 100644 --- a/src/main/java/io/supertokens/pluginInterface/thirdparty/sqlStorage/ThirdPartySQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/thirdparty/sqlStorage/ThirdPartySQLStorage.java @@ -17,13 +17,15 @@ package io.supertokens.pluginInterface.thirdparty.sqlStorage; import io.supertokens.pluginInterface.exceptions.StorageQueryException; +import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; import io.supertokens.pluginInterface.sqlStorage.SQLStorage; import io.supertokens.pluginInterface.sqlStorage.TransactionConnection; import io.supertokens.pluginInterface.thirdparty.ThirdPartyImportUser; import io.supertokens.pluginInterface.thirdparty.ThirdPartyStorage; -import java.util.Collection; +import java.util.List; public interface ThirdPartySQLStorage extends ThirdPartyStorage, SQLStorage { @@ -35,6 +37,6 @@ void deleteThirdPartyUser_Transaction(TransactionConnection con, AppIdentifier a boolean deleteUserIdMappingToo) throws StorageQueryException; - void importThirdPartyUsers_Transaction(TransactionConnection con, Collection usersToImport) - throws StorageQueryException; + void importThirdPartyUsers_Transaction(TransactionConnection con, List usersToImport) + throws StorageQueryException, StorageTransactionLogicException, TenantOrAppNotFoundException; } diff --git a/src/main/java/io/supertokens/pluginInterface/useridmapping/UserIdMappingStorage.java b/src/main/java/io/supertokens/pluginInterface/useridmapping/UserIdMappingStorage.java index eab19ae9..1b7b8c7a 100644 --- a/src/main/java/io/supertokens/pluginInterface/useridmapping/UserIdMappingStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/useridmapping/UserIdMappingStorage.java @@ -25,6 +25,7 @@ import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; public interface UserIdMappingStorage extends Storage { @@ -35,6 +36,10 @@ void createUserIdMapping(AppIdentifier appIdentifier, String superTokensUserId, @Nullable String externalUserIdInfo) throws StorageQueryException, UnknownSuperTokensUserIdException, UserIdMappingAlreadyExistsException; + // support method for bulk migration + void createBulkUserIdMapping(AppIdentifier appIdentifier, Map superTokensUserIdToExternalUserId) + throws StorageQueryException; + boolean deleteUserIdMapping(AppIdentifier appIdentifier, String userId, boolean isSuperTokensUserId) throws StorageQueryException; diff --git a/src/main/java/io/supertokens/pluginInterface/useridmapping/sqlStorage/UserIdMappingSQLStorage.java b/src/main/java/io/supertokens/pluginInterface/useridmapping/sqlStorage/UserIdMappingSQLStorage.java index 44bb8573..28e283b4 100644 --- a/src/main/java/io/supertokens/pluginInterface/useridmapping/sqlStorage/UserIdMappingSQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/useridmapping/sqlStorage/UserIdMappingSQLStorage.java @@ -23,6 +23,8 @@ import io.supertokens.pluginInterface.useridmapping.UserIdMapping; import io.supertokens.pluginInterface.useridmapping.UserIdMappingStorage; +import java.util.List; + public interface UserIdMappingSQLStorage extends UserIdMappingStorage, SQLStorage { UserIdMapping getUserIdMapping_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId, boolean isSuperTokensUserId) @@ -30,4 +32,8 @@ UserIdMapping getUserIdMapping_Transaction(TransactionConnection con, AppIdentif UserIdMapping[] getUserIdMapping_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId) throws StorageQueryException; + + List getMultipleUserIdMapping_Transaction(TransactionConnection connection, AppIdentifier appIdentifier, + List userIds, boolean isSupertokensIds) + throws StorageQueryException; } diff --git a/src/main/java/io/supertokens/pluginInterface/userroles/sqlStorage/UserRolesSQLStorage.java b/src/main/java/io/supertokens/pluginInterface/userroles/sqlStorage/UserRolesSQLStorage.java index b3e7931e..79641984 100644 --- a/src/main/java/io/supertokens/pluginInterface/userroles/sqlStorage/UserRolesSQLStorage.java +++ b/src/main/java/io/supertokens/pluginInterface/userroles/sqlStorage/UserRolesSQLStorage.java @@ -25,6 +25,7 @@ import io.supertokens.pluginInterface.userroles.UserRolesStorage; import io.supertokens.pluginInterface.userroles.exception.UnknownRoleException; +import java.util.List; import java.util.Map; public interface UserRolesSQLStorage extends UserRolesStorage, SQLStorage { @@ -56,6 +57,9 @@ int deleteAllPermissionsForRole_Transaction(AppIdentifier appIdentifier, Transac boolean doesRoleExist_Transaction(AppIdentifier appIdentifier, TransactionConnection con, String role) throws StorageQueryException; + List doesMultipleRoleExist_Transaction(AppIdentifier appIdentifier, TransactionConnection con, List roles) + throws StorageQueryException; + void deleteAllRolesForUser_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String userId) throws StorageQueryException;