Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: multitenant user association #808

Merged
merged 1 commit into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 71 additions & 87 deletions src/main/java/io/supertokens/inmemorydb/Start.java
Original file line number Diff line number Diff line change
Expand Up @@ -2288,77 +2288,64 @@ public TenantConfig[] getAllTenants() throws StorageQueryException {
}

@Override
public boolean addUserIdToTenant_Transaction(TenantIdentifier tenantIdentifier, TransactionConnection conn, String userId)
public boolean addUserIdToTenant_Transaction(TenantIdentifier tenantIdentifier, TransactionConnection con, String userId)
throws StorageQueryException, TenantOrAppNotFoundException, DuplicateEmailException,
DuplicateThirdPartyUserException, DuplicatePhoneNumberException, UnknownUserIdException {
Connection sqlCon = (Connection) con.getConnection();
try {
return this.startTransaction(con -> {
Connection sqlCon = (Connection) con.getConnection();
try {
String recipeId = GeneralQueries.getRecipeIdForUser_Transaction(this, sqlCon, tenantIdentifier,
userId);

if (recipeId == null) {
throw new StorageTransactionLogicException(new UnknownUserIdException());
}

boolean added;
if (recipeId.equals("emailpassword")) {
added = EmailPasswordQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier,
userId);
} else if (recipeId.equals("thirdparty")) {
added = ThirdPartyQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier, userId);
} else if (recipeId.equals("passwordless")) {
added = PasswordlessQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier,
userId);
} else {
throw new IllegalStateException("Should never come here!");
}
String recipeId = GeneralQueries.getRecipeIdForUser_Transaction(this, sqlCon, tenantIdentifier,
userId);

sqlCon.commit();
return added;
} catch (SQLException throwables) {
throw new StorageTransactionLogicException(throwables);
}
});
} catch (StorageTransactionLogicException e) {
if (e.actualException instanceof SQLException) {
SQLiteConfig config = Config.getConfig(this);
String serverErrorMessage = e.actualException.getMessage();
if (recipeId == null) {
throw new UnknownUserIdException();
}

if (isForeignKeyConstraintError(
serverErrorMessage,
config.getTenantsTable(),
new String[]{"app_id", "tenant_id"},
new Object[]{tenantIdentifier.getAppId(), tenantIdentifier.getTenantId()})) {
throw new TenantOrAppNotFoundException(tenantIdentifier);
}
if (isUniqueConstraintError(serverErrorMessage, config.getEmailPasswordUserToTenantTable(),
new String[]{"app_id", "tenant_id", "email"})) {
throw new DuplicateEmailException();
}
if (isUniqueConstraintError(serverErrorMessage, config.getThirdPartyUserToTenantTable(),
new String[]{"app_id", "tenant_id", "third_party_id", "third_party_user_id"})) {
throw new DuplicateThirdPartyUserException();
}
if (isUniqueConstraintError(serverErrorMessage,
Config.getConfig(this).getPasswordlessUserToTenantTable(),
new String[]{"app_id", "tenant_id", "phone_number"})) {
throw new DuplicatePhoneNumberException();
}
if (isUniqueConstraintError(serverErrorMessage,
Config.getConfig(this).getPasswordlessUserToTenantTable(),
new String[]{"app_id", "tenant_id", "email"})) {
throw new DuplicateEmailException();
}
boolean added;
if (recipeId.equals("emailpassword")) {
added = EmailPasswordQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier,
userId);
} else if (recipeId.equals("thirdparty")) {
added = ThirdPartyQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier, userId);
} else if (recipeId.equals("passwordless")) {
added = PasswordlessQueries.addUserIdToTenant_Transaction(this, sqlCon, tenantIdentifier,
userId);
} else {
throw new IllegalStateException("Should never come here!");
}

throw new StorageQueryException(e.actualException);
} else if (e.actualException instanceof UnknownUserIdException) {
throw (UnknownUserIdException) e.actualException;
} else if (e.actualException instanceof StorageQueryException) {
throw (StorageQueryException) e.actualException;
sqlCon.commit();
return added;
} catch (SQLException throwables) {
SQLiteConfig config = Config.getConfig(this);
String serverErrorMessage = throwables.getMessage();

if (isForeignKeyConstraintError(
serverErrorMessage,
config.getTenantsTable(),
new String[]{"app_id", "tenant_id"},
new Object[]{tenantIdentifier.getAppId(), tenantIdentifier.getTenantId()})) {
throw new TenantOrAppNotFoundException(tenantIdentifier);
}
throw new StorageQueryException(e.actualException);
if (isUniqueConstraintError(serverErrorMessage, config.getEmailPasswordUserToTenantTable(),
new String[]{"app_id", "tenant_id", "email"})) {
throw new DuplicateEmailException();
}
if (isUniqueConstraintError(serverErrorMessage, config.getThirdPartyUserToTenantTable(),
new String[]{"app_id", "tenant_id", "third_party_id", "third_party_user_id"})) {
throw new DuplicateThirdPartyUserException();
}
if (isUniqueConstraintError(serverErrorMessage,
Config.getConfig(this).getPasswordlessUserToTenantTable(),
new String[]{"app_id", "tenant_id", "phone_number"})) {
throw new DuplicatePhoneNumberException();
}
if (isUniqueConstraintError(serverErrorMessage,
Config.getConfig(this).getPasswordlessUserToTenantTable(),
new String[]{"app_id", "tenant_id", "email"})) {
throw new DuplicateEmailException();
}

throw new StorageQueryException(throwables);
}
}

Expand Down Expand Up @@ -2804,28 +2791,26 @@ public AuthRecipeUserInfo getPrimaryUserById_Transaction(AppIdentifier appIdenti
public AuthRecipeUserInfo[] listPrimaryUsersByEmail_Transaction(AppIdentifier appIdentifier,
TransactionConnection con, String email)
throws StorageQueryException {
return null; // TODO
// try {
// Connection sqlCon = (Connection) con.getConnection();
// return GeneralQueries.listPrimaryUsersByEmail_Transaction(this, sqlCon, appIdentifier, email);
// } catch (SQLException e) {
// throw new StorageQueryException(e);
// }
try {
Connection sqlCon = (Connection) con.getConnection();
return GeneralQueries.listPrimaryUsersByEmail_Transaction(this, sqlCon, appIdentifier, email);
} catch (SQLException e) {
throw new StorageQueryException(e);
}
}

@Override
public AuthRecipeUserInfo[] listPrimaryUsersByPhoneNumber_Transaction(AppIdentifier appIdentifier,
TransactionConnection con,
String phoneNumber)
throws StorageQueryException {
return null; // TODO
// try {
// Connection sqlCon = (Connection) con.getConnection();
// return GeneralQueries.listPrimaryUsersByPhoneNumber_Transaction(this, sqlCon, tenantIdentifier,
// phoneNumber);
// } catch (SQLException e) {
// throw new StorageQueryException(e);
// }
try {
Connection sqlCon = (Connection) con.getConnection();
return GeneralQueries.listPrimaryUsersByPhoneNumber_Transaction(this, sqlCon, appIdentifier,
phoneNumber);
} catch (SQLException e) {
throw new StorageQueryException(e);
}
}

@Override
Expand All @@ -2842,14 +2827,13 @@ public AuthRecipeUserInfo[] listPrimaryUsersByThirdPartyInfo_Transaction(AppIden
String thirdPartyId,
String thirdPartyUserId)
throws StorageQueryException {
return null; // TODO
// try {
// Connection sqlCon = (Connection) con.getConnection();
// return GeneralQueries.getPrimaryUsersByThirdPartyInfo_Transaction(this, sqlCon, tenantIdentifier,
// thirdPartyId, thirdPartyUserId);
// } catch (SQLException e) {
// throw new StorageQueryException(e);
// }
try {
Connection sqlCon = (Connection) con.getConnection();
return GeneralQueries.getPrimaryUsersByThirdPartyInfo_Transaction(this, sqlCon, appIdentifier,
thirdPartyId, thirdPartyUserId);
} catch (SQLException e) {
throw new StorageQueryException(e);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,19 +397,18 @@ public static List<LoginMethod> getUsersInfoUsingIdList(Start start, Connection
return Collections.emptyList();
}

public static String lockEmailAndTenant_Transaction(Start start, Connection con, TenantIdentifier tenantIdentifier,
String email) throws SQLException, StorageQueryException {
public static String lockEmail_Transaction(Start start, Connection con, AppIdentifier appIdentifier,
String email) throws SQLException, StorageQueryException {
// normally the query below will use a for update, but sqlite doesn't support it.
((ConnectionWithLocks) con).lock(
tenantIdentifier.getAppId() + tenantIdentifier.getTenantId() + "~" + email +
Config.getConfig(start).getEmailPasswordUserToTenantTable());
appIdentifier.getAppId() + "~" + email +
Config.getConfig(start).getEmailPasswordUsersTable());

String QUERY = "SELECT user_id FROM " + getConfig(start).getEmailPasswordUserToTenantTable() +
" WHERE app_id = ? AND tenant_id = ? AND email = ?";
String QUERY = "SELECT user_id FROM " + getConfig(start).getEmailPasswordUsersTable() +
" WHERE app_id = ? AND email = ?";
return execute(con, QUERY, pst -> {
pst.setString(1, tenantIdentifier.getAppId());
pst.setString(2, tenantIdentifier.getTenantId());
pst.setString(3, email);
pst.setString(1, appIdentifier.getAppId());
pst.setString(2, email);
}, result -> {
if (result.next()) {
return result.getString("user_id");
Expand Down Expand Up @@ -439,6 +438,27 @@ public static String getPrimaryUserIdUsingEmail(Start start, Connection con, Ten
});
}

public static List<String> getPrimaryUserIdsUsingEmail(Start start, Connection con, AppIdentifier appIdentifier,
String email)
throws StorageQueryException, SQLException {
String QUERY = "SELECT DISTINCT all_users.primary_or_recipe_user_id AS user_id "
+ "FROM " + getConfig(start).getEmailPasswordUsersTable() + " AS ep" +
" JOIN " + getConfig(start).getUsersTable() + " AS all_users" +
" ON ep.app_id = all_users.app_id AND ep.user_id = all_users.user_id" +
" WHERE ep.app_id = ? AND ep.email = ?";

return execute(con, QUERY, pst -> {
pst.setString(1, appIdentifier.getAppId());
pst.setString(2, email);
}, result -> {
List<String> userIds = new ArrayList<>();
while (result.next()) {
userIds.add(result.getString("user_id"));
}
return userIds;
});
}

public static boolean addUserIdToTenant_Transaction(Start start, Connection sqlCon,
TenantIdentifier tenantIdentifier, String userId)
throws SQLException, StorageQueryException {
Expand Down
Loading
Loading