diff --git a/src/main/java/io/supertokens/storage/postgresql/Start.java b/src/main/java/io/supertokens/storage/postgresql/Start.java index d5a72796..d44c9da5 100644 --- a/src/main/java/io/supertokens/storage/postgresql/Start.java +++ b/src/main/java/io/supertokens/storage/postgresql/Start.java @@ -875,37 +875,58 @@ public String[] getProtectedConfigsFromSuperTokensSaaSUsers() { return PROTECTED_DB_CONFIG; } + private AuthRecipeUserInfo handleEmailPasswordSignUpExceptions(TenantIdentifier tenantIdentifier, + StorageTransactionLogicException exception) throws StorageQueryException, DuplicateUserIdException, + DuplicateEmailException, TenantOrAppNotFoundException { + Exception e = exception.actualException; + if (e instanceof PSQLException) { + PostgreSQLConfig config = Config.getConfig(this); + ServerErrorMessage serverMessage = ((PSQLException) e).getServerErrorMessage(); + + if (isUniqueConstraintError(serverMessage, config.getEmailPasswordUserToTenantTable(), "email")) { + throw new DuplicateEmailException(); + } else if (isPrimaryKeyError(serverMessage, config.getEmailPasswordUsersTable()) + || isPrimaryKeyError(serverMessage, config.getUsersTable()) + || isPrimaryKeyError(serverMessage, config.getEmailPasswordUserToTenantTable()) + || isPrimaryKeyError(serverMessage, config.getAppIdToUserIdTable())) { + throw new DuplicateUserIdException(); + } else if (isForeignKeyConstraintError(serverMessage, config.getEmailPasswordUsersTable(), "user_id")) { + // This should never happen because we add the user to app_id_to_user_id table first + throw new IllegalStateException("should never come here"); + } else if (isForeignKeyConstraintError(serverMessage, config.getAppIdToUserIdTable(), "app_id")) { + throw new TenantOrAppNotFoundException(tenantIdentifier.toAppIdentifier()); + } else if (isForeignKeyConstraintError(serverMessage, config.getUsersTable(), "tenant_id")) { + throw new TenantOrAppNotFoundException(tenantIdentifier); + } + } + + throw new StorageQueryException(e); + } + @Override public AuthRecipeUserInfo signUp(TenantIdentifier tenantIdentifier, String id, String email, String passwordHash, - long timeJoined) + long timeJoined) throws StorageQueryException, DuplicateUserIdException, DuplicateEmailException, TenantOrAppNotFoundException { try { return EmailPasswordQueries.signUp(this, tenantIdentifier, id, email, passwordHash, timeJoined); } catch (StorageTransactionLogicException eTemp) { - Exception e = eTemp.actualException; - if (e instanceof PSQLException) { - PostgreSQLConfig config = Config.getConfig(this); - ServerErrorMessage serverMessage = ((PSQLException) e).getServerErrorMessage(); - - if (isUniqueConstraintError(serverMessage, config.getEmailPasswordUserToTenantTable(), "email")) { - throw new DuplicateEmailException(); - } else if (isPrimaryKeyError(serverMessage, config.getEmailPasswordUsersTable()) - || isPrimaryKeyError(serverMessage, config.getUsersTable()) - || isPrimaryKeyError(serverMessage, config.getEmailPasswordUserToTenantTable()) - || isPrimaryKeyError(serverMessage, config.getAppIdToUserIdTable())) { - throw new DuplicateUserIdException(); - } else if (isForeignKeyConstraintError(serverMessage, config.getEmailPasswordUsersTable(), "user_id")) { - // This should never happen because we add the user to app_id_to_user_id table first - throw new IllegalStateException("should never come here"); - } else if (isForeignKeyConstraintError(serverMessage, config.getAppIdToUserIdTable(), "app_id")) { - throw new TenantOrAppNotFoundException(tenantIdentifier.toAppIdentifier()); - } else if (isForeignKeyConstraintError(serverMessage, config.getUsersTable(), "tenant_id")) { - throw new TenantOrAppNotFoundException(tenantIdentifier); - } - } + return handleEmailPasswordSignUpExceptions(tenantIdentifier, eTemp); + } + } - throw new StorageQueryException(e); + @Override + public AuthRecipeUserInfo bulkImport_signUp_Transaction(TransactionConnection con, + TenantIdentifier tenantIdentifier, String id, String email, String passwordHash, + long timeJoined) + throws StorageQueryException, DuplicateUserIdException, DuplicateEmailException, + TenantOrAppNotFoundException { + try { + Connection sqlCon = (Connection) con.getConnection(); + return EmailPasswordQueries.bulkImport_signUp_Transaction(this, sqlCon, tenantIdentifier, id, email, + passwordHash, timeJoined); + } catch (StorageTransactionLogicException eTemp) { + return handleEmailPasswordSignUpExceptions(tenantIdentifier, eTemp); } } @@ -1191,6 +1212,16 @@ public void updateIsEmailVerifiedToExternalUserId(AppIdentifier appIdentifier, S EmailVerificationQueries.updateIsEmailVerifiedToExternalUserId(this, appIdentifier, supertokensUserId, externalUserId); } + @Override + public void bulkImport_updateIsEmailVerifiedToExternalUserId_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String supertokensUserId, String externalUserId) throws StorageQueryException { + Connection sqlCon = (Connection) con.getConnection(); + try { + EmailVerificationQueries.bulkImport_updateIsEmailVerifiedToExternalUserId_Transaction(this, sqlCon, appIdentifier, supertokensUserId, externalUserId); + } catch (SQLException e) { + throw new StorageQueryException(e); + } + } + @Override public void deleteExpiredPasswordResetTokens() throws StorageQueryException { try { @@ -1213,46 +1244,65 @@ public void updateUserEmail_Transaction(AppIdentifier appIdentifier, Transaction } } - @Override - public AuthRecipeUserInfo signUp( - TenantIdentifier tenantIdentifier, String id, String email, - LoginMethod.ThirdParty thirdParty, long timeJoined) - throws StorageQueryException, io.supertokens.pluginInterface.thirdparty.exception.DuplicateUserIdException, - DuplicateThirdPartyUserException, TenantOrAppNotFoundException { - try { - return ThirdPartyQueries.signUp(this, tenantIdentifier, id, email, thirdParty, timeJoined); - } catch (StorageTransactionLogicException eTemp) { - Exception e = eTemp.actualException; - if (e instanceof PSQLException) { - PostgreSQLConfig config = Config.getConfig(this); - ServerErrorMessage serverMessage = ((PSQLException) e).getServerErrorMessage(); - if (isUniqueConstraintError(serverMessage, config.getThirdPartyUserToTenantTable(), - "third_party_user_id")) { - throw new DuplicateThirdPartyUserException(); + private AuthRecipeUserInfo handleThirdPartySignUpExceptions(TenantIdentifier tenantIdentifier, + StorageTransactionLogicException exception) + throws DuplicateThirdPartyUserException, TenantOrAppNotFoundException, StorageQueryException, + io.supertokens.pluginInterface.thirdparty.exception.DuplicateUserIdException { + Exception e = exception.actualException; + if (e instanceof PSQLException) { + PostgreSQLConfig config = Config.getConfig(this); + ServerErrorMessage serverMessage = ((PSQLException) e).getServerErrorMessage(); - } else if (isPrimaryKeyError(serverMessage, config.getThirdPartyUsersTable()) - || isPrimaryKeyError(serverMessage, config.getUsersTable()) - || isPrimaryKeyError(serverMessage, config.getThirdPartyUserToTenantTable()) - || isPrimaryKeyError(serverMessage, config.getAppIdToUserIdTable())) { - throw new io.supertokens.pluginInterface.thirdparty.exception.DuplicateUserIdException(); + if (isUniqueConstraintError(serverMessage, config.getThirdPartyUserToTenantTable(), + "third_party_user_id")) { + throw new DuplicateThirdPartyUserException(); - } else if (isForeignKeyConstraintError(serverMessage, config.getThirdPartyUsersTable(), "user_id")) { - // This should never happen because we add the user to app_id_to_user_id table first - throw new IllegalStateException("should never come here"); + } else if (isPrimaryKeyError(serverMessage, config.getThirdPartyUsersTable()) + || isPrimaryKeyError(serverMessage, config.getUsersTable()) + || isPrimaryKeyError(serverMessage, config.getThirdPartyUserToTenantTable()) + || isPrimaryKeyError(serverMessage, config.getAppIdToUserIdTable())) { + throw new io.supertokens.pluginInterface.thirdparty.exception.DuplicateUserIdException(); - } else if (isForeignKeyConstraintError(serverMessage, config.getAppIdToUserIdTable(), "app_id")) { - throw new TenantOrAppNotFoundException(tenantIdentifier.toAppIdentifier()); + } else if (isForeignKeyConstraintError(serverMessage, config.getThirdPartyUsersTable(), "user_id")) { + // This should never happen because we add the user to app_id_to_user_id table first + throw new IllegalStateException("should never come here"); - } else if (isForeignKeyConstraintError(serverMessage, config.getUsersTable(), "tenant_id")) { - throw new TenantOrAppNotFoundException(tenantIdentifier); + } else if (isForeignKeyConstraintError(serverMessage, config.getAppIdToUserIdTable(), "app_id")) { + throw new TenantOrAppNotFoundException(tenantIdentifier.toAppIdentifier()); - } + } else if (isForeignKeyConstraintError(serverMessage, config.getUsersTable(), "tenant_id")) { + throw new TenantOrAppNotFoundException(tenantIdentifier); + } + } + throw new StorageQueryException(exception.actualException); + } - } + @Override + public AuthRecipeUserInfo signUp( + TenantIdentifier tenantIdentifier, String id, String email, + LoginMethod.ThirdParty thirdParty, long timeJoined) + throws StorageQueryException, io.supertokens.pluginInterface.thirdparty.exception.DuplicateUserIdException, + DuplicateThirdPartyUserException, TenantOrAppNotFoundException { + try { + return ThirdPartyQueries.signUp(this, tenantIdentifier, id, email, thirdParty, timeJoined); + } catch (StorageTransactionLogicException e) { + return handleThirdPartySignUpExceptions(tenantIdentifier, e); + } + } - throw new StorageQueryException(eTemp.actualException); + @Override + public AuthRecipeUserInfo bulkImport_signUp_Transaction( + TransactionConnection con, TenantIdentifier tenantIdentifier, String id, String email, + LoginMethod.ThirdParty thirdParty, long timeJoined) + throws StorageQueryException, io.supertokens.pluginInterface.thirdparty.exception.DuplicateUserIdException, + DuplicateThirdPartyUserException, TenantOrAppNotFoundException { + try { + Connection sqlCon = (Connection) con.getConnection(); + return ThirdPartyQueries.bulkInmport_signUp_Transaction(this, sqlCon, tenantIdentifier, id, email, thirdParty, timeJoined); + } catch (StorageTransactionLogicException e) { + return handleThirdPartySignUpExceptions(tenantIdentifier, e); } } @@ -1707,15 +1757,57 @@ public void createCode(TenantIdentifier tenantIdentifier, PasswordlessCode code) } } + private AuthRecipeUserInfo handleCreateUserExceptions(TenantIdentifier tenantIdentifier, + StorageTransactionLogicException exception) throws StorageQueryException, TenantOrAppNotFoundException, + DuplicateUserIdException, DuplicateEmailException, DuplicatePhoneNumberException { + Exception e = exception.actualException; + + if (e instanceof PSQLException) { + PostgreSQLConfig config = Config.getConfig(this); + ServerErrorMessage serverMessage = ((PSQLException) e).getServerErrorMessage(); + + if (isPrimaryKeyError(serverMessage, config.getPasswordlessUsersTable()) + || isPrimaryKeyError(serverMessage, config.getUsersTable()) + || isPrimaryKeyError(serverMessage, config.getPasswordlessUserToTenantTable()) + || isPrimaryKeyError(serverMessage, config.getAppIdToUserIdTable())) { + throw new DuplicateUserIdException(); + } + + if (isUniqueConstraintError(((PSQLException) e).getServerErrorMessage(), + Config.getConfig(this).getPasswordlessUserToTenantTable(), "email")) { + throw new DuplicateEmailException(); + } + + if (isUniqueConstraintError(((PSQLException) e).getServerErrorMessage(), + Config.getConfig(this).getPasswordlessUserToTenantTable(), "phone_number")) { + throw new DuplicatePhoneNumberException(); + } + + if (isForeignKeyConstraintError(serverMessage, config.getPasswordlessUsersTable(), "user_id")) { + // This should never happen because we add the user to app_id_to_user_id table first + throw new IllegalStateException("should never come here"); + } + + if (isForeignKeyConstraintError(serverMessage, config.getAppIdToUserIdTable(), "app_id")) { + throw new TenantOrAppNotFoundException(tenantIdentifier.toAppIdentifier()); + } + + if (isForeignKeyConstraintError(serverMessage, config.getUsersTable(), "tenant_id")) { + throw new TenantOrAppNotFoundException(tenantIdentifier); + } + } + throw new StorageQueryException(exception.actualException); + } + + @Override public AuthRecipeUserInfo createUser(TenantIdentifier tenantIdentifier, String id, @javax.annotation.Nullable String email, @javax.annotation.Nullable String phoneNumber, long timeJoined) - throws StorageQueryException, - DuplicateEmailException, DuplicatePhoneNumberException, DuplicateUserIdException, - TenantOrAppNotFoundException { + throws StorageQueryException, DuplicateEmailException, DuplicatePhoneNumberException, + DuplicateUserIdException, TenantOrAppNotFoundException { if (email == null && phoneNumber == null) { throw new IllegalArgumentException("Both email and phoneNumber cannot be null"); } @@ -1723,45 +1815,28 @@ public AuthRecipeUserInfo createUser(TenantIdentifier tenantIdentifier, try { return PasswordlessQueries.createUser(this, tenantIdentifier, id, email, phoneNumber, timeJoined); } catch (StorageTransactionLogicException e) { + return handleCreateUserExceptions(tenantIdentifier, e); + } + } - Exception actualException = e.actualException; - - if (actualException instanceof PSQLException) { - PostgreSQLConfig config = Config.getConfig(this); - ServerErrorMessage serverMessage = ((PSQLException) actualException).getServerErrorMessage(); - - if (isPrimaryKeyError(serverMessage, config.getPasswordlessUsersTable()) - || isPrimaryKeyError(serverMessage, config.getUsersTable()) - || isPrimaryKeyError(serverMessage, config.getPasswordlessUserToTenantTable()) - || isPrimaryKeyError(serverMessage, config.getAppIdToUserIdTable())) { - throw new DuplicateUserIdException(); - } - - if (isUniqueConstraintError(((PSQLException) actualException).getServerErrorMessage(), - Config.getConfig(this).getPasswordlessUserToTenantTable(), "email")) { - throw new DuplicateEmailException(); - } - - if (isUniqueConstraintError(((PSQLException) actualException).getServerErrorMessage(), - Config.getConfig(this).getPasswordlessUserToTenantTable(), "phone_number")) { - throw new DuplicatePhoneNumberException(); - } - - if (isForeignKeyConstraintError(serverMessage, config.getPasswordlessUsersTable(), "user_id")) { - // This should never happen because we add the user to app_id_to_user_id table first - throw new IllegalStateException("should never come here"); - } - - if (isForeignKeyConstraintError(serverMessage, config.getAppIdToUserIdTable(), "app_id")) { - throw new TenantOrAppNotFoundException(tenantIdentifier.toAppIdentifier()); - } - - if (isForeignKeyConstraintError(serverMessage, config.getUsersTable(), "tenant_id")) { - throw new TenantOrAppNotFoundException(tenantIdentifier); - } + @Override + public AuthRecipeUserInfo bulkImport_createUser_Transaction(TransactionConnection con, + TenantIdentifier tenantIdentifier, + String id, + @javax.annotation.Nullable String email, + @javax.annotation.Nullable + String phoneNumber, long timeJoined) + throws StorageQueryException, DuplicateEmailException, DuplicatePhoneNumberException, + DuplicateUserIdException, TenantOrAppNotFoundException { + if (email == null && phoneNumber == null) { + throw new IllegalArgumentException("Both email and phoneNumber cannot be null"); + } - } - throw new StorageQueryException(e.actualException); + try { + Connection sqlCon = (Connection) con.getConnection(); + return PasswordlessQueries.bulkImport_createUser_Transaction(this, sqlCon, tenantIdentifier, id, email, phoneNumber, timeJoined); + } catch (StorageTransactionLogicException e) { + return handleCreateUserExceptions(tenantIdentifier, e); } } @@ -1910,6 +1985,26 @@ public int deleteUserMetadata(AppIdentifier appIdentifier, String userId) throws } } + private void handleAddRoleToUserException(TenantIdentifier tenantIdentifier, SQLException e) + throws StorageQueryException, UnknownRoleException, DuplicateUserRoleMappingException, + TenantOrAppNotFoundException { + if (e instanceof PSQLException) { + PostgreSQLConfig config = Config.getConfig(this); + ServerErrorMessage serverErrorMessage = ((PSQLException) e).getServerErrorMessage(); + if (isForeignKeyConstraintError(serverErrorMessage, config.getUserRolesTable(), "role")) { + throw new UnknownRoleException(); + } + if (isPrimaryKeyError(serverErrorMessage, config.getUserRolesTable())) { + throw new DuplicateUserRoleMappingException(); + } + if (isForeignKeyConstraintError(serverErrorMessage, config.getUserRolesTable(), + "tenant_id")) { + throw new TenantOrAppNotFoundException(tenantIdentifier); + } + } + throw new StorageQueryException(e); + } + @Override public void addRoleToUser(TenantIdentifier tenantIdentifier, String userId, String role) throws StorageQueryException, UnknownRoleException, DuplicateUserRoleMappingException, @@ -1917,23 +2012,20 @@ public void addRoleToUser(TenantIdentifier tenantIdentifier, String userId, Stri try { UserRolesQueries.addRoleToUser(this, tenantIdentifier, userId, role); } catch (SQLException e) { - if (e instanceof PSQLException) { - PostgreSQLConfig config = Config.getConfig(this); - ServerErrorMessage serverErrorMessage = ((PSQLException) e).getServerErrorMessage(); - if (isForeignKeyConstraintError(serverErrorMessage, config.getUserRolesTable(), "role")) { - throw new UnknownRoleException(); - } - if (isPrimaryKeyError(serverErrorMessage, config.getUserRolesTable())) { - throw new DuplicateUserRoleMappingException(); - } - if (isForeignKeyConstraintError(serverErrorMessage, config.getUserRolesTable(), - "tenant_id")) { - throw new TenantOrAppNotFoundException(tenantIdentifier); - } - } - throw new StorageQueryException(e); + handleAddRoleToUserException(tenantIdentifier, e); } + } + @Override + public void bulkImport_addRoleToUser_Transaction(TransactionConnection con, TenantIdentifier tenantIdentifier, String userId, String role) + throws StorageQueryException, UnknownRoleException, DuplicateUserRoleMappingException, + TenantOrAppNotFoundException { + try { + Connection sqlCon = (Connection) con.getConnection(); + UserRolesQueries.bulkImport_addRoleToUser_Transaction(this, sqlCon, tenantIdentifier, userId, role); + } catch (SQLException e) { + handleAddRoleToUserException(tenantIdentifier, e); + } } @Override @@ -2130,6 +2222,32 @@ public boolean doesRoleExist_Transaction(AppIdentifier appIdentifier, Transactio } } + private void handleCreateUserIdMappingExceptions(SQLException e) throws StorageQueryException, UnknownSuperTokensUserIdException, UserIdMappingAlreadyExistsException { + if (e instanceof PSQLException) { + PostgreSQLConfig config = Config.getConfig(this); + ServerErrorMessage serverErrorMessage = ((PSQLException) e).getServerErrorMessage(); + if (isForeignKeyConstraintError(serverErrorMessage, config.getUserIdMappingTable(), + "supertokens_user_id")) { + throw new UnknownSuperTokensUserIdException(); + } + + if (isPrimaryKeyError(serverErrorMessage, config.getUserIdMappingTable())) { + throw new UserIdMappingAlreadyExistsException(true, true); + } + + if (isUniqueConstraintError(serverErrorMessage, config.getUserIdMappingTable(), + "supertokens_user_id")) { + throw new UserIdMappingAlreadyExistsException(true, false); + } + + if (isUniqueConstraintError(serverErrorMessage, config.getUserIdMappingTable(), + "external_user_id")) { + throw new UserIdMappingAlreadyExistsException(false, true); + } + } + throw new StorageQueryException(e); + } + @Override public void createUserIdMapping(AppIdentifier appIdentifier, String superTokensUserId, String externalUserId, @org.jetbrains.annotations.Nullable String externalUserIdInfo) @@ -2138,31 +2256,21 @@ public void createUserIdMapping(AppIdentifier appIdentifier, String superTokensU UserIdMappingQueries.createUserIdMapping(this, appIdentifier, superTokensUserId, externalUserId, externalUserIdInfo); } catch (SQLException e) { - if (e instanceof PSQLException) { - PostgreSQLConfig config = Config.getConfig(this); - ServerErrorMessage serverErrorMessage = ((PSQLException) e).getServerErrorMessage(); - if (isForeignKeyConstraintError(serverErrorMessage, config.getUserIdMappingTable(), - "supertokens_user_id")) { - throw new UnknownSuperTokensUserIdException(); - } - - if (isPrimaryKeyError(serverErrorMessage, config.getUserIdMappingTable())) { - throw new UserIdMappingAlreadyExistsException(true, true); - } - - if (isUniqueConstraintError(serverErrorMessage, config.getUserIdMappingTable(), - "supertokens_user_id")) { - throw new UserIdMappingAlreadyExistsException(true, false); - } - - if (isUniqueConstraintError(serverErrorMessage, config.getUserIdMappingTable(), - "external_user_id")) { - throw new UserIdMappingAlreadyExistsException(false, true); - } - } - throw new StorageQueryException(e); + handleCreateUserIdMappingExceptions(e); } + } + @Override + public void bulkImport_createUserIdMapping_Transaction(TransactionConnection con, AppIdentifier appIdentifier, String superTokensUserId, String externalUserId, + @org.jetbrains.annotations.Nullable String externalUserIdInfo) + throws StorageQueryException, UnknownSuperTokensUserIdException, UserIdMappingAlreadyExistsException { + try { + Connection sqlCon = (Connection) con.getConnection(); + UserIdMappingQueries.bulkImport_createUserIdMapping_Transaction(this, sqlCon, appIdentifier, superTokensUserId, externalUserId, + externalUserIdInfo); + } catch (SQLException e) { + handleCreateUserIdMappingExceptions(e); + } } @Override @@ -2354,7 +2462,6 @@ public boolean addUserIdToTenant_Transaction(TenantIdentifier tenantIdentifier, throw new IllegalStateException("Should never come here!"); } - sqlCon.commit(); return added; } catch (SQLException throwables) { PostgreSQLConfig config = Config.getConfig(this); @@ -3074,11 +3181,11 @@ public List getBulkImportUsers(AppIdentifier appIdentifier, @Non } @Override - public void updateBulkImportUserStatus_Transaction(AppIdentifier appIdentifier, TransactionConnection con, @Nonnull String[] bulkImportUserIds, @Nonnull BULK_IMPORT_USER_STATUS status) + public void updateBulkImportUserStatus_Transaction(AppIdentifier appIdentifier, TransactionConnection con, @Nonnull String[] bulkImportUserIds, @Nonnull BULK_IMPORT_USER_STATUS status, @Nullable String errorMessage) throws StorageQueryException { Connection sqlCon = (Connection) con.getConnection(); try { - BulkImportQueries.updateBulkImportUserStatus_Transaction(this, sqlCon, appIdentifier, bulkImportUserIds, status); + BulkImportQueries.updateBulkImportUserStatus_Transaction(this, sqlCon, appIdentifier, bulkImportUserIds, status, errorMessage); } catch (SQLException e) { throw new StorageQueryException(e); } @@ -3092,4 +3199,23 @@ public List deleteBulkImportUsers(AppIdentifier appIdentifier, @Nonnull throw new StorageQueryException(e); } } + + @Override + public List getBulkImportUsersForProcessing(AppIdentifier appIdentifier, @Nonnull Integer limit) throws StorageQueryException { + try { + return BulkImportQueries.getBulkImportUsersForProcessing(this, appIdentifier, limit); + } catch (StorageTransactionLogicException e) { + throw new StorageQueryException(e.actualException); + } + } + + @Override + public void deleteBulkImportUser_Transaction(AppIdentifier appIdentifier, TransactionConnection con, @Nonnull String bulkImportUserId) throws StorageQueryException { + Connection sqlCon = (Connection) con.getConnection(); + try { + BulkImportQueries.deleteBulkImportUser_Transaction(this, sqlCon, appIdentifier, bulkImportUserId); + } catch (SQLException e) { + throw new StorageQueryException(e); + } + } } diff --git a/src/main/java/io/supertokens/storage/postgresql/queries/BulkImportQueries.java b/src/main/java/io/supertokens/storage/postgresql/queries/BulkImportQueries.java index 2f3b5139..e162ad4e 100644 --- a/src/main/java/io/supertokens/storage/postgresql/queries/BulkImportQueries.java +++ b/src/main/java/io/supertokens/storage/postgresql/queries/BulkImportQueries.java @@ -32,6 +32,7 @@ import io.supertokens.pluginInterface.bulkimport.BulkImportStorage.BULK_IMPORT_USER_STATUS; import io.supertokens.pluginInterface.bulkimport.BulkImportUser; import io.supertokens.pluginInterface.exceptions.StorageQueryException; +import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException; import io.supertokens.pluginInterface.multitenancy.AppIdentifier; import io.supertokens.storage.postgresql.Start; import io.supertokens.storage.postgresql.config.Config; @@ -47,8 +48,8 @@ static String getQueryToCreateBulkImportUsersTable(Start start) { + "raw_data TEXT NOT NULL," + "status VARCHAR(128) DEFAULT 'NEW'," + "error_msg TEXT," - + "created_at BIGINT DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)," - + "updated_at BIGINT DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)," + + "created_at BIGINT DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000," + + "updated_at BIGINT DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000," + "CONSTRAINT " + Utils.getConstraintName(schema, tableName, null, "pkey") + " PRIMARY KEY(app_id, id)," + "CONSTRAINT " + Utils.getConstraintName(schema, tableName, "app_id", "fkey") + " " @@ -92,18 +93,19 @@ public static void insertBulkImportUsers(Start start, AppIdentifier appIdentifie }); } - public static void updateBulkImportUserStatus_Transaction(Start start, Connection con, AppIdentifier appIdentifier, @Nonnull String[] bulkImportUserIds, @Nonnull BULK_IMPORT_USER_STATUS status) + public static void updateBulkImportUserStatus_Transaction(Start start, Connection con, AppIdentifier appIdentifier, @Nonnull String[] bulkImportUserIds, @Nonnull BULK_IMPORT_USER_STATUS status, @Nullable String errorMessage) throws SQLException, StorageQueryException { if (bulkImportUserIds.length == 0) { return; } - String baseQuery = "UPDATE " + Config.getConfig(start).getBulkImportUsersTable() + " SET status = ?, updated_at = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) WHERE app_id = ?"; + String baseQuery = "UPDATE " + Config.getConfig(start).getBulkImportUsersTable() + " SET status = ?, error_msg = ?, updated_at = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) WHERE app_id = ?"; StringBuilder queryBuilder = new StringBuilder(baseQuery); List parameters = new ArrayList<>(); parameters.add(status.toString()); + parameters.add(errorMessage); parameters.add(appIdentifier.getAppId()); queryBuilder.append(" AND id IN ("); @@ -125,6 +127,39 @@ public static void updateBulkImportUserStatus_Transaction(Start start, Connectio }); } + public static List getBulkImportUsersForProcessing(Start start, AppIdentifier appIdentifier, @Nonnull Integer limit) + throws StorageQueryException, StorageTransactionLogicException { + + return start.startTransaction(con -> { + Connection sqlCon = (Connection) con.getConnection(); + try { + String selectQuery = "SELECT * FROM " + Config.getConfig(start).getBulkImportUsersTable() + + " WHERE status = 'NEW' AND app_id = ? " + + " OR (status = 'PROCESSING' AND updated_at < EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000 - 60 * 1000) " + + " LIMIT ? FOR UPDATE SKIP LOCKED"; + + List bulkImportUsers = new ArrayList<>(); + + execute(sqlCon, selectQuery, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setInt(2, limit); + }, result -> { + while (result.next()) { + bulkImportUsers.add(BulkImportUserRowMapper.getInstance().mapOrThrow(result)); + } + return null; + }); + + String[] bulkImportUserIds = bulkImportUsers.stream().map(user -> user.id).toArray(String[]::new); + + updateBulkImportUserStatus_Transaction(start, sqlCon, appIdentifier, bulkImportUserIds, BULK_IMPORT_USER_STATUS.PROCESSING, null); + return bulkImportUsers; + } catch (SQLException throwables) { + throw new StorageTransactionLogicException(throwables); + } + }); + } + public static List getBulkImportUsers(Start start, AppIdentifier appIdentifier, @Nonnull Integer limit, @Nullable BULK_IMPORT_USER_STATUS status, @Nullable String bulkImportUserId, @Nullable Long createdAt) throws SQLException, StorageQueryException { @@ -205,6 +240,16 @@ public static List deleteBulkImportUsers(Start start, AppIdentifier appI return deletedIds; }); } + + public static void deleteBulkImportUser_Transaction(Start start, Connection con, AppIdentifier appIdentifier, @Nonnull String bulkImportUserId) throws SQLException, StorageQueryException { + String query = "DELETE FROM " + Config.getConfig(start).getBulkImportUsersTable() + " WHERE app_id = ? AND id = ?"; + + update(con, query, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setString(2, bulkImportUserId); + }); + } + private static class BulkImportUserRowMapper implements RowMapper { private static final BulkImportUserRowMapper INSTANCE = new BulkImportUserRowMapper(); @@ -219,7 +264,7 @@ private static BulkImportUserRowMapper getInstance() { public BulkImportUser map(ResultSet result) throws Exception { return BulkImportUser.fromRawDataFromDbStorage(result.getString("id"), result.getString("raw_data"), BULK_IMPORT_USER_STATUS.valueOf(result.getString("status")), - result.getLong("created_at"), result.getLong("updated_at")); + result.getString("error_msg"), result.getLong("created_at"), result.getLong("updated_at")); } } } diff --git a/src/main/java/io/supertokens/storage/postgresql/queries/EmailPasswordQueries.java b/src/main/java/io/supertokens/storage/postgresql/queries/EmailPasswordQueries.java index 55bb51c4..485b7185 100644 --- a/src/main/java/io/supertokens/storage/postgresql/queries/EmailPasswordQueries.java +++ b/src/main/java/io/supertokens/storage/postgresql/queries/EmailPasswordQueries.java @@ -20,13 +20,11 @@ import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; import io.supertokens.pluginInterface.authRecipe.LoginMethod; import io.supertokens.pluginInterface.emailpassword.PasswordResetTokenInfo; -import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateEmailException; 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.storage.postgresql.ConnectionPool; import io.supertokens.storage.postgresql.Start; import io.supertokens.storage.postgresql.config.Config; import io.supertokens.storage.postgresql.utils.Utils; @@ -266,74 +264,85 @@ public static void addPasswordResetToken(Start start, AppIdentifier appIdentifie } } - public static AuthRecipeUserInfo signUp(Start start, TenantIdentifier tenantIdentifier, String userId, String email, - String passwordHash, long timeJoined) - throws StorageQueryException, StorageTransactionLogicException { - return start.startTransaction(con -> { - Connection sqlCon = (Connection) con.getConnection(); - try { - { // app_id_to_user_id - String QUERY = "INSERT INTO " + getConfig(start).getAppIdToUserIdTable() - + "(app_id, user_id, primary_or_recipe_user_id, recipe_id)" + " VALUES(?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, userId); - pst.setString(3, userId); - pst.setString(4, EMAIL_PASSWORD.toString()); - }); - } + private static AuthRecipeUserInfo signUpQuery(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String userId, String email, + String passwordHash, long timeJoined) throws StorageQueryException, StorageTransactionLogicException { + try { + { // app_id_to_user_id + String QUERY = "INSERT INTO " + getConfig(start).getAppIdToUserIdTable() + + "(app_id, user_id, primary_or_recipe_user_id, recipe_id)" + " VALUES(?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, userId); + pst.setString(3, userId); + pst.setString(4, EMAIL_PASSWORD.toString()); + }); + } - { // all_auth_recipe_users - String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + - " VALUES(?, ?, ?, ?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, tenantIdentifier.getTenantId()); - pst.setString(3, userId); - pst.setString(4, userId); - pst.setString(5, EMAIL_PASSWORD.toString()); - pst.setLong(6, timeJoined); - pst.setLong(7, timeJoined); - }); - } + { // all_auth_recipe_users + String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + " VALUES(?, ?, ?, ?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, userId); + pst.setString(4, userId); + pst.setString(5, EMAIL_PASSWORD.toString()); + pst.setLong(6, timeJoined); + pst.setLong(7, timeJoined); + }); + } - { // emailpassword_users - String QUERY = "INSERT INTO " + getConfig(start).getEmailPasswordUsersTable() - + "(app_id, user_id, email, password_hash, time_joined)" + " VALUES(?, ?, ?, ?, ?)"; - - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, userId); - pst.setString(3, email); - pst.setString(4, passwordHash); - pst.setLong(5, timeJoined); - }); - } + { // emailpassword_users + String QUERY = "INSERT INTO " + getConfig(start).getEmailPasswordUsersTable() + + "(app_id, user_id, email, password_hash, time_joined)" + " VALUES(?, ?, ?, ?, ?)"; - { // emailpassword_user_to_tenant - String QUERY = "INSERT INTO " + getConfig(start).getEmailPasswordUserToTenantTable() - + "(app_id, tenant_id, user_id, email)" + " VALUES(?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, userId); + pst.setString(3, email); + pst.setString(4, passwordHash); + pst.setLong(5, timeJoined); + }); + } - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, tenantIdentifier.getTenantId()); - pst.setString(3, userId); - pst.setString(4, email); - }); - } + { // emailpassword_user_to_tenant + String QUERY = "INSERT INTO " + getConfig(start).getEmailPasswordUserToTenantTable() + + "(app_id, tenant_id, user_id, email)" + " VALUES(?, ?, ?, ?)"; - UserInfoPartial userInfo = new UserInfoPartial(userId, email, passwordHash, timeJoined); - fillUserInfoWithTenantIds_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); - fillUserInfoWithVerified_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); - sqlCon.commit(); - return AuthRecipeUserInfo.create(userId, false, userInfo.toLoginMethod()); - } catch (SQLException throwables) { - throw new StorageTransactionLogicException(throwables); + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, userId); + pst.setString(4, email); + }); } + + UserInfoPartial userInfo = new UserInfoPartial(userId, email, passwordHash, timeJoined); + fillUserInfoWithTenantIds_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); + fillUserInfoWithVerified_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); + + return AuthRecipeUserInfo.create(userId, false, userInfo.toLoginMethod()); + } catch (SQLException throwables) { + throw new StorageTransactionLogicException(throwables); + } + } + + public static AuthRecipeUserInfo signUp(Start start, TenantIdentifier tenantIdentifier, String userId, String email, + String passwordHash, long timeJoined) + throws StorageQueryException, StorageTransactionLogicException { + return start.startTransaction(con -> { + Connection sqlCon = (Connection) con.getConnection(); + return signUpQuery(start, sqlCon, tenantIdentifier, userId, email, passwordHash, timeJoined); }); } + public static AuthRecipeUserInfo bulkImport_signUp_Transaction(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String userId, String email, + String passwordHash, long timeJoined) + throws StorageQueryException, StorageTransactionLogicException { + return signUpQuery(start, sqlCon, tenantIdentifier, userId, email, passwordHash, timeJoined); + } + public static void deleteUser_Transaction(Connection sqlCon, Start start, AppIdentifier appIdentifier, String userId, boolean deleteUserIdMappingToo) throws StorageQueryException, SQLException { diff --git a/src/main/java/io/supertokens/storage/postgresql/queries/EmailVerificationQueries.java b/src/main/java/io/supertokens/storage/postgresql/queries/EmailVerificationQueries.java index ff9fc950..7aa0c1b2 100644 --- a/src/main/java/io/supertokens/storage/postgresql/queries/EmailVerificationQueries.java +++ b/src/main/java/io/supertokens/storage/postgresql/queries/EmailVerificationQueries.java @@ -476,30 +476,35 @@ public static boolean isUserIdBeingUsedForEmailVerification(Start start, AppIden } } + public static void updateIsEmailVerifiedToExternalUserIdQuery(Start start, Connection sqlCon, AppIdentifier appIdentifier, String supertokensUserId, String externalUserId) + throws StorageQueryException, SQLException { + { + String QUERY = "UPDATE " + getConfig(start).getEmailVerificationTable() + + " SET user_id = ? WHERE app_id = ? AND user_id = ?"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, externalUserId); + pst.setString(2, appIdentifier.getAppId()); + pst.setString(3, supertokensUserId); + }); + } + { + String QUERY = "UPDATE " + getConfig(start).getEmailVerificationTokensTable() + + " SET user_id = ? WHERE app_id = ? AND user_id = ?"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, externalUserId); + pst.setString(2, appIdentifier.getAppId()); + pst.setString(3, supertokensUserId); + }); + } + } + public static void updateIsEmailVerifiedToExternalUserId(Start start, AppIdentifier appIdentifier, String supertokensUserId, String externalUserId) throws StorageQueryException { try { start.startTransaction((TransactionConnection con) -> { Connection sqlCon = (Connection) con.getConnection(); try { - { - String QUERY = "UPDATE " + getConfig(start).getEmailVerificationTable() - + " SET user_id = ? WHERE app_id = ? AND user_id = ?"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, externalUserId); - pst.setString(2, appIdentifier.getAppId()); - pst.setString(3, supertokensUserId); - }); - } - { - String QUERY = "UPDATE " + getConfig(start).getEmailVerificationTokensTable() - + " SET user_id = ? WHERE app_id = ? AND user_id = ?"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, externalUserId); - pst.setString(2, appIdentifier.getAppId()); - pst.setString(3, supertokensUserId); - }); - } + updateIsEmailVerifiedToExternalUserIdQuery(start, sqlCon, appIdentifier, supertokensUserId, externalUserId); } catch (SQLException e) { throw new StorageTransactionLogicException(e); } @@ -511,6 +516,11 @@ public static void updateIsEmailVerifiedToExternalUserId(Start start, AppIdentif } } + public static void bulkImport_updateIsEmailVerifiedToExternalUserId_Transaction(Start start, Connection sqlCon, AppIdentifier appIdentifier, String supertokensUserId, String externalUserId) + throws SQLException, StorageQueryException { + updateIsEmailVerifiedToExternalUserIdQuery(start, sqlCon, appIdentifier, supertokensUserId, externalUserId); + } + private static class EmailVerificationTokenInfoRowMapper implements RowMapper { private static final EmailVerificationTokenInfoRowMapper INSTANCE = new EmailVerificationTokenInfoRowMapper(); diff --git a/src/main/java/io/supertokens/storage/postgresql/queries/PasswordlessQueries.java b/src/main/java/io/supertokens/storage/postgresql/queries/PasswordlessQueries.java index 8f8df3d6..88104181 100644 --- a/src/main/java/io/supertokens/storage/postgresql/queries/PasswordlessQueries.java +++ b/src/main/java/io/supertokens/storage/postgresql/queries/PasswordlessQueries.java @@ -388,74 +388,89 @@ public static void deleteCode_Transaction(Start start, Connection con, TenantIde }); } - public static AuthRecipeUserInfo createUser(Start start, TenantIdentifier tenantIdentifier, String id, @Nullable String email, - @Nullable String phoneNumber, long timeJoined) + public static AuthRecipeUserInfo createUserQuery(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, + String id, @Nullable String email, + @Nullable String phoneNumber, long timeJoined) throws StorageTransactionLogicException, StorageQueryException { - return start.startTransaction(con -> { - Connection sqlCon = (Connection) con.getConnection(); - try { - { // app_id_to_user_id - String QUERY = "INSERT INTO " + getConfig(start).getAppIdToUserIdTable() - + "(app_id, user_id, primary_or_recipe_user_id, recipe_id)" + " VALUES(?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, id); - pst.setString(3, id); - pst.setString(4, PASSWORDLESS.toString()); - }); - } + try { + { // app_id_to_user_id + String QUERY = "INSERT INTO " + getConfig(start).getAppIdToUserIdTable() + + "(app_id, user_id, primary_or_recipe_user_id, recipe_id)" + " VALUES(?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, id); + pst.setString(3, id); + pst.setString(4, PASSWORDLESS.toString()); + }); + } - { // all_auth_recipe_users - String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + - " VALUES(?, ?, ?, ?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, tenantIdentifier.getTenantId()); - pst.setString(3, id); - pst.setString(4, id); - pst.setString(5, PASSWORDLESS.toString()); - pst.setLong(6, timeJoined); - pst.setLong(7, timeJoined); - }); - } + { // all_auth_recipe_users + String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + " VALUES(?, ?, ?, ?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, id); + pst.setString(4, id); + pst.setString(5, PASSWORDLESS.toString()); + pst.setLong(6, timeJoined); + pst.setLong(7, timeJoined); + }); + } - { // passwordless_users - String QUERY = "INSERT INTO " + getConfig(start).getPasswordlessUsersTable() - + "(app_id, user_id, email, phone_number, time_joined)" + " VALUES(?, ?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, id); - pst.setString(3, email); - pst.setString(4, phoneNumber); - pst.setLong(5, timeJoined); - }); - } + { // passwordless_users + String QUERY = "INSERT INTO " + getConfig(start).getPasswordlessUsersTable() + + "(app_id, user_id, email, phone_number, time_joined)" + " VALUES(?, ?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, id); + pst.setString(3, email); + pst.setString(4, phoneNumber); + pst.setLong(5, timeJoined); + }); + } - { // passwordless_user_to_tenant - String QUERY = "INSERT INTO " + getConfig(start).getPasswordlessUserToTenantTable() - + "(app_id, tenant_id, user_id, email, phone_number)" + " VALUES(?, ?, ?, ?, ?)"; - - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, tenantIdentifier.getTenantId()); - pst.setString(3, id); - pst.setString(4, email); - pst.setString(5, phoneNumber); - }); - } - UserInfoPartial userInfo = new UserInfoPartial(id, email, phoneNumber, timeJoined); - fillUserInfoWithTenantIds_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); - fillUserInfoWithVerified_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); - sqlCon.commit(); - return AuthRecipeUserInfo.create(id, false, - userInfo.toLoginMethod()); - } catch (SQLException throwables) { - throw new StorageTransactionLogicException(throwables); + { // passwordless_user_to_tenant + String QUERY = "INSERT INTO " + getConfig(start).getPasswordlessUserToTenantTable() + + "(app_id, tenant_id, user_id, email, phone_number)" + " VALUES(?, ?, ?, ?, ?)"; + + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, id); + pst.setString(4, email); + pst.setString(5, phoneNumber); + }); } + UserInfoPartial userInfo = new UserInfoPartial(id, email, phoneNumber, timeJoined); + fillUserInfoWithTenantIds_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); + fillUserInfoWithVerified_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); + + return AuthRecipeUserInfo.create(id, false, + userInfo.toLoginMethod()); + } catch (SQLException throwables) { + throw new StorageTransactionLogicException(throwables); + } + } + + public static AuthRecipeUserInfo createUser(Start start, TenantIdentifier tenantIdentifier, String id, + @Nullable String email, + @Nullable String phoneNumber, long timeJoined) + throws StorageTransactionLogicException, StorageQueryException { + return start.startTransaction(con -> { + Connection sqlCon = (Connection) con.getConnection(); + return createUserQuery(start, sqlCon, tenantIdentifier, id, email, phoneNumber, timeJoined); }); } + public static AuthRecipeUserInfo bulkImport_createUser_Transaction(Start start, Connection sqlCon, + TenantIdentifier tenantIdentifier, String id, @Nullable String email, @Nullable String phoneNumber, + long timeJoined) + throws StorageTransactionLogicException, StorageQueryException { + return createUserQuery(start, sqlCon, tenantIdentifier, id, email, phoneNumber, timeJoined); + } + private static UserInfoWithTenantId[] getUserInfosWithTenant_Transaction(Start start, Connection con, AppIdentifier appIdentifier, String userId) throws StorageQueryException, SQLException { diff --git a/src/main/java/io/supertokens/storage/postgresql/queries/ThirdPartyQueries.java b/src/main/java/io/supertokens/storage/postgresql/queries/ThirdPartyQueries.java index 2a37c9dc..b98f7fac 100644 --- a/src/main/java/io/supertokens/storage/postgresql/queries/ThirdPartyQueries.java +++ b/src/main/java/io/supertokens/storage/postgresql/queries/ThirdPartyQueries.java @@ -98,77 +98,89 @@ static String getQueryToCreateThirdPartyUserToTenantTable(Start start) { // @formatter:on } - public static AuthRecipeUserInfo signUp(Start start, TenantIdentifier tenantIdentifier, String id, String email, + public static AuthRecipeUserInfo signUpQuery(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String id, String email, LoginMethod.ThirdParty thirdParty, long timeJoined) throws StorageQueryException, StorageTransactionLogicException { - return start.startTransaction(con -> { - Connection sqlCon = (Connection) con.getConnection(); - try { - { // app_id_to_user_id - String QUERY = "INSERT INTO " + getConfig(start).getAppIdToUserIdTable() - + "(app_id, user_id, primary_or_recipe_user_id, recipe_id)" + " VALUES(?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, id); - pst.setString(3, id); - pst.setString(4, THIRD_PARTY.toString()); - }); - } + try { + { // app_id_to_user_id + String QUERY = "INSERT INTO " + getConfig(start).getAppIdToUserIdTable() + + "(app_id, user_id, primary_or_recipe_user_id, recipe_id)" + " VALUES(?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, id); + pst.setString(3, id); + pst.setString(4, THIRD_PARTY.toString()); + }); + } - { // all_auth_recipe_users - String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() - + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + - " VALUES(?, ?, ?, ?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, tenantIdentifier.getTenantId()); - pst.setString(3, id); - pst.setString(4, id); - pst.setString(5, THIRD_PARTY.toString()); - pst.setLong(6, timeJoined); - pst.setLong(7, timeJoined); - }); - } + { // all_auth_recipe_users + String QUERY = "INSERT INTO " + getConfig(start).getUsersTable() + + "(app_id, tenant_id, user_id, primary_or_recipe_user_id, recipe_id, time_joined, primary_or_recipe_user_time_joined)" + + " VALUES(?, ?, ?, ?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, id); + pst.setString(4, id); + pst.setString(5, THIRD_PARTY.toString()); + pst.setLong(6, timeJoined); + pst.setLong(7, timeJoined); + }); + } - { // thirdparty_users - String QUERY = "INSERT INTO " + getConfig(start).getThirdPartyUsersTable() - + "(app_id, third_party_id, third_party_user_id, user_id, email, time_joined)" - + " VALUES(?, ?, ?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, thirdParty.id); - pst.setString(3, thirdParty.userId); - pst.setString(4, id); - pst.setString(5, email); - pst.setLong(6, timeJoined); - }); - } + { // thirdparty_users + String QUERY = "INSERT INTO " + getConfig(start).getThirdPartyUsersTable() + + "(app_id, third_party_id, third_party_user_id, user_id, email, time_joined)" + + " VALUES(?, ?, ?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, thirdParty.id); + pst.setString(3, thirdParty.userId); + pst.setString(4, id); + pst.setString(5, email); + pst.setLong(6, timeJoined); + }); + } - { // thirdparty_user_to_tenant - String QUERY = "INSERT INTO " + getConfig(start).getThirdPartyUserToTenantTable() - + "(app_id, tenant_id, user_id, third_party_id, third_party_user_id)" - + " VALUES(?, ?, ?, ?, ?)"; - update(sqlCon, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, tenantIdentifier.getTenantId()); - pst.setString(3, id); - pst.setString(4, thirdParty.id); - pst.setString(5, thirdParty.userId); - }); - } + { // thirdparty_user_to_tenant + String QUERY = "INSERT INTO " + getConfig(start).getThirdPartyUserToTenantTable() + + "(app_id, tenant_id, user_id, third_party_id, third_party_user_id)" + + " VALUES(?, ?, ?, ?, ?)"; + update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, id); + pst.setString(4, thirdParty.id); + pst.setString(5, thirdParty.userId); + }); + } - UserInfoPartial userInfo = new UserInfoPartial(id, email, thirdParty, timeJoined); - fillUserInfoWithTenantIds_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); - fillUserInfoWithVerified_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); - sqlCon.commit(); - return AuthRecipeUserInfo.create(id, false, userInfo.toLoginMethod()); + UserInfoPartial userInfo = new UserInfoPartial(id, email, thirdParty, timeJoined); + fillUserInfoWithTenantIds_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); + fillUserInfoWithVerified_transaction(start, sqlCon, tenantIdentifier.toAppIdentifier(), userInfo); - } catch (SQLException throwables) { - throw new StorageTransactionLogicException(throwables); - } + return AuthRecipeUserInfo.create(id, false, userInfo.toLoginMethod()); + + } catch (SQLException throwables) { + throw new StorageTransactionLogicException(throwables); + } + } + + public static AuthRecipeUserInfo signUp(Start start, TenantIdentifier tenantIdentifier, String id, String email, + LoginMethod.ThirdParty thirdParty, long timeJoined) + throws StorageQueryException, StorageTransactionLogicException { + return start.startTransaction(con -> { + Connection sqlCon = (Connection) con.getConnection(); + return signUpQuery(start, sqlCon, tenantIdentifier, id, email, thirdParty, timeJoined); }); } + public static AuthRecipeUserInfo bulkInmport_signUp_Transaction(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String id, String email, + LoginMethod.ThirdParty thirdParty, long timeJoined) + throws StorageQueryException, StorageTransactionLogicException { + return signUpQuery(start, sqlCon, tenantIdentifier, id, email, thirdParty, timeJoined); + } + public static void deleteUser_Transaction(Connection sqlCon, Start start, AppIdentifier appIdentifier, String userId, boolean deleteUserIdMappingToo) throws StorageQueryException, SQLException { diff --git a/src/main/java/io/supertokens/storage/postgresql/queries/UserIdMappingQueries.java b/src/main/java/io/supertokens/storage/postgresql/queries/UserIdMappingQueries.java index 24f4fab7..7d5c84fc 100644 --- a/src/main/java/io/supertokens/storage/postgresql/queries/UserIdMappingQueries.java +++ b/src/main/java/io/supertokens/storage/postgresql/queries/UserIdMappingQueries.java @@ -65,17 +65,39 @@ public static String getQueryToCreateSupertokensUserIdIndexForUserIdMappingTable + getConfig(start).getUserIdMappingTable() + "(app_id, supertokens_user_id);"; } - public static void createUserIdMapping(Start start, AppIdentifier appIdentifier, String superTokensUserId, String externalUserId, - String externalUserIdInfo) throws SQLException, StorageQueryException { + public static void createUserIdMappingQuery(Start start, Connection sqlCon, AppIdentifier appIdentifier, + String superTokensUserId, String externalUserId, + String externalUserIdInfo) throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + Config.getConfig(start).getUserIdMappingTable() + " (app_id, supertokens_user_id, external_user_id, external_user_id_info)" + " VALUES(?, ?, ?, ?)"; - update(start, QUERY, pst -> { - pst.setString(1, appIdentifier.getAppId()); - pst.setString(2, superTokensUserId); - pst.setString(3, externalUserId); - pst.setString(4, externalUserIdInfo); - }); + if (sqlCon == null) { + update(start, QUERY, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setString(2, superTokensUserId); + pst.setString(3, externalUserId); + pst.setString(4, externalUserIdInfo); + }); + } else { + update(sqlCon, QUERY, pst -> { + pst.setString(1, appIdentifier.getAppId()); + pst.setString(2, superTokensUserId); + pst.setString(3, externalUserId); + pst.setString(4, externalUserIdInfo); + }); + } + } + + public static void createUserIdMapping(Start start, AppIdentifier appIdentifier, String superTokensUserId, + String externalUserId, + String externalUserIdInfo) throws SQLException, StorageQueryException { + createUserIdMappingQuery(start, null, appIdentifier, superTokensUserId, externalUserId, externalUserIdInfo); + } + + public static void bulkImport_createUserIdMapping_Transaction(Start start, Connection sqlCon, + AppIdentifier appIdentifier, String superTokensUserId, + String externalUserId, String externalUserIdInfo) throws SQLException, StorageQueryException { + createUserIdMappingQuery(start, sqlCon, appIdentifier, superTokensUserId, externalUserId, externalUserIdInfo); } public static UserIdMapping getuseraIdMappingWithSuperTokensUserId(Start start, AppIdentifier appIdentifier, String userId) diff --git a/src/main/java/io/supertokens/storage/postgresql/queries/UserRolesQueries.java b/src/main/java/io/supertokens/storage/postgresql/queries/UserRolesQueries.java index 549cac86..6151f3c9 100644 --- a/src/main/java/io/supertokens/storage/postgresql/queries/UserRolesQueries.java +++ b/src/main/java/io/supertokens/storage/postgresql/queries/UserRolesQueries.java @@ -190,16 +190,36 @@ public static String[] getRoles(Start start, AppIdentifier appIdentifier) }); } - public static int addRoleToUser(Start start, TenantIdentifier tenantIdentifier, String userId, String role) + public static int addRoleToUserQuery(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String userId, String role) throws SQLException, StorageQueryException { String QUERY = "INSERT INTO " + getConfig(start).getUserRolesTable() + "(app_id, tenant_id, user_id, role) VALUES(?, ?, ?, ?);"; - return update(start, QUERY, pst -> { - pst.setString(1, tenantIdentifier.getAppId()); - pst.setString(2, tenantIdentifier.getTenantId()); - pst.setString(3, userId); - pst.setString(4, role); - }); + + if (sqlCon == null) { + return update(start, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, userId); + pst.setString(4, role); + }); + } else { + return update(sqlCon, QUERY, pst -> { + pst.setString(1, tenantIdentifier.getAppId()); + pst.setString(2, tenantIdentifier.getTenantId()); + pst.setString(3, userId); + pst.setString(4, role); + }); + } + } + + public static int addRoleToUser(Start start, TenantIdentifier tenantIdentifier, String userId, String role) + throws SQLException, StorageQueryException { + return addRoleToUserQuery(start, null, tenantIdentifier, userId, role); + } + + public static int bulkImport_addRoleToUser_Transaction(Start start, Connection sqlCon, TenantIdentifier tenantIdentifier, String userId, String role) + throws SQLException, StorageQueryException { + return addRoleToUserQuery(start, sqlCon, tenantIdentifier, userId, role); } public static String[] getRolesForUser(Start start, TenantIdentifier tenantIdentifier, String userId)