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: miscellaneous fixes #796

Merged
merged 4 commits into from
Sep 11, 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
Binary file added jar/core-6.0.12.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ public static void updateUsersEmailOrPassword(AppIdentifierWithStorage appIdenti
}
boolean foundEmailPasswordLoginMethod = false;
for (LoginMethod lm : user.loginMethods) {
if (lm.recipeId == RECIPE_ID.EMAIL_PASSWORD) {
if (lm.recipeId == RECIPE_ID.EMAIL_PASSWORD && lm.getSupertokensUserId().equals(userId)) {
foundEmailPasswordLoginMethod = true;
break;
}
Expand Down
30 changes: 15 additions & 15 deletions src/main/java/io/supertokens/multitenancy/Multitenancy.java
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,10 @@ public static boolean addUserIdToTenant(Main main, TenantIdentifierWithStorage t
}

for (String email : emails) {
AuthRecipeUserInfo[] users = storage.listPrimaryUsersByEmail_Transaction(tenantIdentifierWithStorage.toAppIdentifier(), con, email);
for (AuthRecipeUserInfo user : users) {
if (user.tenantIds.contains(tenantId) && !user.getSupertokensUserId().equals(userId)) {
for (LoginMethod lm1 : user.loginMethods) {
AuthRecipeUserInfo[] usersWithSameEmail = storage.listPrimaryUsersByEmail_Transaction(tenantIdentifierWithStorage.toAppIdentifier(), con, email);
for (AuthRecipeUserInfo userWithSameEmail : usersWithSameEmail) {
if (userWithSameEmail.isPrimaryUser && userWithSameEmail.tenantIds.contains(tenantId) && !userWithSameEmail.getSupertokensUserId().equals(userId)) {
for (LoginMethod lm1 : userWithSameEmail.loginMethods) {
if (lm1.tenantIds.contains(tenantId)) {
for (LoginMethod lm2 : userToAssociate.loginMethods) {
if (lm1.recipeId.equals(lm2.recipeId) && email.equals(lm1.email) && lm1.email.equals(lm2.email)) {
Expand All @@ -436,16 +436,16 @@ public static boolean addUserIdToTenant(Main main, TenantIdentifierWithStorage t
}
}
}
throw new StorageTransactionLogicException(new AnotherPrimaryUserWithEmailAlreadyExistsException(user.getSupertokensUserId()));
throw new StorageTransactionLogicException(new AnotherPrimaryUserWithEmailAlreadyExistsException(userWithSameEmail.getSupertokensUserId()));
}
}
}

for (String phoneNumber : phoneNumbers) {
AuthRecipeUserInfo[] users = storage.listPrimaryUsersByPhoneNumber_Transaction(tenantIdentifierWithStorage.toAppIdentifier(), con, phoneNumber);
for (AuthRecipeUserInfo user : users) {
if (user.tenantIds.contains(tenantId) && !user.getSupertokensUserId().equals(userId)) {
for (LoginMethod lm1 : user.loginMethods) {
AuthRecipeUserInfo[] usersWithSamePhoneNumber = storage.listPrimaryUsersByPhoneNumber_Transaction(tenantIdentifierWithStorage.toAppIdentifier(), con, phoneNumber);
for (AuthRecipeUserInfo userWithSamePhoneNumber : usersWithSamePhoneNumber) {
if (userWithSamePhoneNumber.tenantIds.contains(tenantId) && !userWithSamePhoneNumber.getSupertokensUserId().equals(userId)) {
for (LoginMethod lm1 : userWithSamePhoneNumber.loginMethods) {
if (lm1.tenantIds.contains(tenantId)) {
for (LoginMethod lm2 : userToAssociate.loginMethods) {
if (lm1.recipeId.equals(lm2.recipeId) && phoneNumber.equals(lm1.phoneNumber) && lm1.phoneNumber.equals(lm2.phoneNumber)) {
Expand All @@ -454,16 +454,16 @@ public static boolean addUserIdToTenant(Main main, TenantIdentifierWithStorage t
}
}
}
throw new StorageTransactionLogicException(new AnotherPrimaryUserWithPhoneNumberAlreadyExistsException(user.getSupertokensUserId()));
throw new StorageTransactionLogicException(new AnotherPrimaryUserWithPhoneNumberAlreadyExistsException(userWithSamePhoneNumber.getSupertokensUserId()));
}
}
}

for (LoginMethod.ThirdParty tp : thirdParties) {
AuthRecipeUserInfo[] users = storage.listPrimaryUsersByThirdPartyInfo_Transaction(tenantIdentifierWithStorage.toAppIdentifier(), con, tp.id, tp.userId);
for (AuthRecipeUserInfo user : users) {
if (user.tenantIds.contains(tenantId) && !user.getSupertokensUserId().equals(userId)) {
for (LoginMethod lm1 : user.loginMethods) {
AuthRecipeUserInfo[] usersWithSameThirdPartyInfo = storage.listPrimaryUsersByThirdPartyInfo_Transaction(tenantIdentifierWithStorage.toAppIdentifier(), con, tp.id, tp.userId);
for (AuthRecipeUserInfo userWithSameThirdPartyInfo : usersWithSameThirdPartyInfo) {
if (userWithSameThirdPartyInfo.tenantIds.contains(tenantId) && !userWithSameThirdPartyInfo.getSupertokensUserId().equals(userId)) {
for (LoginMethod lm1 : userWithSameThirdPartyInfo.loginMethods) {
if (lm1.tenantIds.contains(tenantId)) {
for (LoginMethod lm2 : userToAssociate.loginMethods) {
if (lm1.recipeId.equals(lm2.recipeId) && tp.equals(lm1.thirdParty) && lm1.thirdParty.equals(lm2.thirdParty)) {
Expand All @@ -473,7 +473,7 @@ public static boolean addUserIdToTenant(Main main, TenantIdentifierWithStorage t
}
}

throw new StorageTransactionLogicException(new AnotherPrimaryUserWithThirdPartyInfoAlreadyExistsException(user.getSupertokensUserId()));
throw new StorageTransactionLogicException(new AnotherPrimaryUserWithThirdPartyInfoAlreadyExistsException(userWithSameThirdPartyInfo.getSupertokensUserId()));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/io/supertokens/passwordless/Passwordless.java
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public static ConsumeCodeResponse consumeCode(TenantIdentifierWithStorage tenant
consumedDevice.email);
for (AuthRecipeUserInfo currUser : users) {
for (LoginMethod currLM : currUser.loginMethods) {
if (currLM.recipeId == RECIPE_ID.PASSWORDLESS && currLM.email.equals(consumedDevice.email)) {
if (currLM.recipeId == RECIPE_ID.PASSWORDLESS && currLM.email.equals(consumedDevice.email) && currLM.tenantIds.contains(tenantIdentifierWithStorage.getTenantId())) {
user = currUser;
loginMethod = currLM;
break;
Expand All @@ -412,7 +412,7 @@ public static ConsumeCodeResponse consumeCode(TenantIdentifierWithStorage tenant
for (AuthRecipeUserInfo currUser : users) {
for (LoginMethod currLM : currUser.loginMethods) {
if (currLM.recipeId == RECIPE_ID.PASSWORDLESS &&
currLM.phoneNumber.equals(consumedDevice.phoneNumber)) {
currLM.phoneNumber.equals(consumedDevice.phoneNumber) && currLM.tenantIds.contains(tenantIdentifierWithStorage.getTenantId())) {
user = currUser;
loginMethod = currLM;
break;
Expand Down
132 changes: 132 additions & 0 deletions src/test/java/io/supertokens/test/accountlinking/MultitenantTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import io.supertokens.passwordless.exceptions.PhoneNumberChangeNotAllowedException;
import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo;
import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateEmailException;
import io.supertokens.pluginInterface.emailpassword.exceptions.UnknownUserIdException;
import io.supertokens.pluginInterface.exceptions.InvalidConfigException;
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
import io.supertokens.pluginInterface.multitenancy.*;
Expand Down Expand Up @@ -159,6 +160,82 @@ private void createTenants(Main main)
}
}

@Test
public void testUserAreNotAutomaticallySharedBetweenTenantsOfLinkedAccountsForPless() throws Exception {
String[] args = {"../"};
TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
FeatureFlagTestContent.getInstance(process.getProcess())
.setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[]{
EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY});
process.startProcess();
assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));

createTenants(process.getProcess());

t1 = new TenantIdentifier(null, "a1", null);
t2 = new TenantIdentifier(null, "a1", "t1");

TenantIdentifierWithStorage t1WithStorage = t1.withStorage(StorageLayer.getStorage(t1, process.getProcess()));
TenantIdentifierWithStorage t2WithStorage = t2.withStorage(StorageLayer.getStorage(t2, process.getProcess()));

AuthRecipeUserInfo user1 = EmailPassword.signUp(t1WithStorage, process.getProcess(), "[email protected]", "password");
Passwordless.CreateCodeResponse user2Code = Passwordless.createCode(t1WithStorage, process.getProcess(),
"[email protected]", null, null, null);
AuthRecipeUserInfo user2 = Passwordless.consumeCode(t1WithStorage, process.getProcess(), user2Code.deviceId, user2Code.deviceIdHash, user2Code.userInputCode, null).user;

AuthRecipe.createPrimaryUser(process.getProcess(), t1WithStorage.toAppIdentifierWithStorage(), user1.getSupertokensUserId());
AuthRecipe.linkAccounts(process.getProcess(), t1WithStorage.toAppIdentifierWithStorage(), user2.getSupertokensUserId(), user1.getSupertokensUserId());

Multitenancy.addUserIdToTenant(process.getProcess(), t2WithStorage, user1.getSupertokensUserId());

{ // user2 should not be shared in tenant2
Passwordless.CreateCodeResponse user3Code = Passwordless.createCode(t2WithStorage, process.getProcess(),
"[email protected]", null, null, null);
Passwordless.ConsumeCodeResponse res = Passwordless.consumeCode(t2WithStorage, process.getProcess(),
user3Code.deviceId, user3Code.deviceIdHash, user3Code.userInputCode, null);
assertTrue(res.createdNewUser);
}

process.kill();
assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
}

@Test
public void testUserAreNotAutomaticallySharedBetweenTenantsOfLinkedAccountsForTP() throws Exception {
String[] args = {"../"};
TestingProcessManager.TestingProcess process = TestingProcessManager.start(args, false);
FeatureFlagTestContent.getInstance(process.getProcess())
.setKeyValue(FeatureFlagTestContent.ENABLED_FEATURES, new EE_FEATURES[]{
EE_FEATURES.ACCOUNT_LINKING, EE_FEATURES.MULTI_TENANCY});
process.startProcess();
assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED));

createTenants(process.getProcess());

t1 = new TenantIdentifier(null, "a1", null);
t2 = new TenantIdentifier(null, "a1", "t1");

TenantIdentifierWithStorage t1WithStorage = t1.withStorage(StorageLayer.getStorage(t1, process.getProcess()));
TenantIdentifierWithStorage t2WithStorage = t2.withStorage(StorageLayer.getStorage(t2, process.getProcess()));

AuthRecipeUserInfo user1 = EmailPassword.signUp(t1WithStorage, process.getProcess(), "[email protected]", "password");
AuthRecipeUserInfo user2 = ThirdParty.signInUp(t1WithStorage, process.getProcess(), "google", "googleid1", "[email protected]").user;

AuthRecipe.createPrimaryUser(process.getProcess(), t1WithStorage.toAppIdentifierWithStorage(), user1.getSupertokensUserId());
AuthRecipe.linkAccounts(process.getProcess(), t1WithStorage.toAppIdentifierWithStorage(), user2.getSupertokensUserId(), user1.getSupertokensUserId());

Multitenancy.addUserIdToTenant(process.getProcess(), t2WithStorage, user1.getSupertokensUserId());

{ // user2 should not be shared in tenant2
ThirdParty.SignInUpResponse res = ThirdParty.signInUp(t2WithStorage, process.getProcess(), "google",
"googleid1", "[email protected]");
assertTrue(res.createdNewUser);
}

process.kill();
assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED));
}

@Test
public void testVariousCases() throws Exception {
t1 = new TenantIdentifier(null, "a1", null);
Expand All @@ -167,6 +244,19 @@ public void testVariousCases() throws Exception {
t4 = new TenantIdentifier(null, "a1", "t3");

TestCase[] testCases = new TestCase[]{
new TestCase(new TestCaseStep[]{
new CreateEmailPasswordUser(t1, "[email protected]"),
new CreatePlessUserWithEmail(t2, "[email protected]"),
new MakePrimaryUser(t1, 0),
new AssociateUserToTenant(t2, 0),
}),
new TestCase(new TestCaseStep[]{
new CreateEmailPasswordUser(t1, "[email protected]"),
new CreatePlessUserWithEmail(t2, "[email protected]"),
new AssociateUserToTenant(t2, 0),
new MakePrimaryUser(t1, 0),
}),

new TestCase(new TestCaseStep[]{
new CreateEmailPasswordUser(t1, "[email protected]"),
new CreateEmailPasswordUser(t2, "[email protected]"),
Expand Down Expand Up @@ -446,6 +536,32 @@ public void testVariousCases() throws Exception {
new CreateThirdPartyUser(t1, "google", "googleid1", "[email protected]").expect(new EmailChangeNotAllowedException()),
new CreateThirdPartyUser(t1, "google", "googleid3", "[email protected]").expect(new EmailChangeNotAllowedException()),
}),
new TestCase(new TestCaseStep[]{
new CreateEmailPasswordUser(t1, "[email protected]"),
new CreateEmailPasswordUser(t1, "[email protected]"),
new MakePrimaryUser(t1, 0),
new LinkAccounts(t1, 0, 1),
new UnlinkAccount(t1, 0),
new AssociateUserToTenant(t2, 0).expect(new UnknownUserIdException()),
}),

new TestCase(new TestCaseStep[]{
new CreatePlessUserWithEmail(t1, "[email protected]"),
new CreatePlessUserWithEmail(t1, "[email protected]"),
new MakePrimaryUser(t1, 0),
new LinkAccounts(t1, 0, 1),
new UnlinkAccount(t1, 0),
new AssociateUserToTenant(t2, 0).expect(new UnknownUserIdException()),
}),

new TestCase(new TestCaseStep[]{
new CreateThirdPartyUser(t1, "google", "googleid1", "[email protected]"),
new CreateThirdPartyUser(t1, "google", "googleid2", "[email protected]"),
new MakePrimaryUser(t1, 0),
new LinkAccounts(t1, 0, 1),
new UnlinkAccount(t1, 0),
new AssociateUserToTenant(t2, 0).expect(new UnknownUserIdException()),
}),
};

int i = 0;
Expand Down Expand Up @@ -698,4 +814,20 @@ public void execute(Main main) throws Exception {
Passwordless.updateUser(tenantIdentifierWithStorage.toAppIdentifierWithStorage(), TestCase.users.get(userIndex).getSupertokensUserId(), null, new Passwordless.FieldUpdate(phoneNumber));
}
}

private static class UnlinkAccount extends TestCaseStep {
TenantIdentifier tenantIdentifier;
int userIndex;

public UnlinkAccount(TenantIdentifier tenantIdentifier, int userIndex) {
this.tenantIdentifier = tenantIdentifier;
this.userIndex = userIndex;
}

@Override
public void execute(Main main) throws Exception {
TenantIdentifierWithStorage tenantIdentifierWithStorage = tenantIdentifier.withStorage(StorageLayer.getStorage(tenantIdentifier, main));
AuthRecipe.unlinkAccounts(main, tenantIdentifierWithStorage.toAppIdentifierWithStorage(), TestCase.users.get(userIndex).getSupertokensUserId());
}
}
}
Loading
Loading