Skip to content

Commit

Permalink
fix: allow user disassociation from all tenants
Browse files Browse the repository at this point in the history
  • Loading branch information
sattvikc committed Sep 12, 2023
1 parent a2d8d61 commit bb938de
Show file tree
Hide file tree
Showing 5 changed files with 5 additions and 81 deletions.
25 changes: 0 additions & 25 deletions src/main/java/io/supertokens/multitenancy/Multitenancy.java
Original file line number Diff line number Diff line change
Expand Up @@ -513,40 +513,15 @@ public static boolean addUserIdToTenant(Main main, TenantIdentifierWithStorage t
}
}

@TestOnly
public static boolean removeUserIdFromTenant(Main main, TenantIdentifierWithStorage tenantIdentifierWithStorage,
String userId, String externalUserId)
throws FeatureNotEnabledException, TenantOrAppNotFoundException, StorageQueryException,
UnknownUserIdException {
try {
return removeUserIdFromTenant(main, tenantIdentifierWithStorage, userId, externalUserId, false);
} catch (DisassociationNotAllowedException e) {
throw new IllegalStateException("should never happen");
}
}

public static boolean removeUserIdFromTenant(Main main, TenantIdentifierWithStorage tenantIdentifierWithStorage,
String userId, String externalUserId, boolean disallowLastTenantDisassociation)
throws FeatureNotEnabledException, TenantOrAppNotFoundException, StorageQueryException,
UnknownUserIdException, DisassociationNotAllowedException {
if (Arrays.stream(FeatureFlag.getInstance(main, new AppIdentifier(null, null)).getEnabledFeatures())
.noneMatch(ee_features -> ee_features == EE_FEATURES.MULTI_TENANCY)) {
throw new FeatureNotEnabledException(EE_FEATURES.MULTI_TENANCY);
}

if (disallowLastTenantDisassociation) {
AuthRecipeUserInfo userInfo = AuthRecipe.getUserById(tenantIdentifierWithStorage.toAppIdentifierWithStorage(), userId);
if (userInfo != null) {
for (LoginMethod lM : userInfo.loginMethods) {
if (lM.getSupertokensUserId().equals(userId)) {
if (lM.tenantIds.size() == 1 && lM.tenantIds.contains(tenantIdentifierWithStorage.getTenantId())) {
throw new DisassociationNotAllowedException();
}
}
}
}
}

boolean finalDidExist = false;
boolean didExist = AuthRecipe.deleteNonAuthRecipeUser(tenantIdentifierWithStorage,
externalUserId == null ? userId : externalUserId);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import io.supertokens.Main;
import io.supertokens.featureflag.exceptions.FeatureNotEnabledException;
import io.supertokens.multitenancy.Multitenancy;
import io.supertokens.multitenancy.exception.DisassociationNotAllowedException;
import io.supertokens.pluginInterface.RECIPE_ID;
import io.supertokens.pluginInterface.emailpassword.exceptions.UnknownUserIdException;
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
Expand Down Expand Up @@ -70,8 +69,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
}

boolean wasAssociated = Multitenancy.removeUserIdFromTenant(main,
getTenantIdentifierWithStorageFromRequest(req), userId, externalUserId, getVersionFromRequest(req).greaterThanOrEqualTo(
SemVer.v4_0));
getTenantIdentifierWithStorageFromRequest(req), userId, externalUserId);

JsonObject result = new JsonObject();
result.addProperty("status", "OK");
Expand All @@ -82,11 +80,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
JsonObject result = new JsonObject();
result.addProperty("status", "UNKNOWN_USER_ID_ERROR");
super.sendJsonResponse(200, result, resp);
} catch (DisassociationNotAllowedException e) {
JsonObject result = new JsonObject();
result.addProperty("status", "DISASSOCIATION_NOT_ALLOWED_ERROR");
result.addProperty("reason", "The user belongs to only one tenant and cannot be disassociated from that");
super.sendJsonResponse(200, result, resp);

} catch (StorageQueryException | TenantOrAppNotFoundException | FeatureNotEnabledException e) {
throw new ServletException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,27 +718,4 @@ public void testThatTenantIdIsNotAllowedForOlderCDIVersion() throws Exception {
assertEquals(404, e.statusCode);
}
}

@Test
public void testThatDisassociationFromAllTenantsIsDisallowed() throws Exception {
if (StorageLayer.getStorage(process.getProcess()).getType() != STORAGE_TYPE.SQL) {
return;
}

createTenants(false);

{
JsonObject user = TestMultitenancyAPIHelper.epSignUp(t1, "[email protected]", "password", process.getProcess());
{
JsonObject requestBody = new JsonObject();
requestBody.addProperty("userId", user.get("id").getAsString());

JsonObject response = HttpRequestForTesting.sendJsonPOSTRequest(process.getProcess(), "",
HttpRequestForTesting.getMultitenantUrl(t1, "/recipe/multitenancy/tenant/user/remove"),
requestBody, 1000, 1000, null,
SemVer.v4_0.get(), "multitenancy");
assertEquals("DISASSOCIATION_NOT_ALLOWED_ERROR", response.get("status").getAsString());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.supertokens.test.httpRequest.HttpRequestForTesting;
import io.supertokens.test.httpRequest.HttpResponseException;
import io.supertokens.utils.SemVer;
import io.supertokens.webserver.WebserverAPI;

import java.io.IOException;
import java.util.HashMap;
Expand Down Expand Up @@ -207,7 +208,7 @@ public static JsonObject associateUserToTenant(TenantIdentifier tenantIdentifier
JsonObject response = HttpRequestForTesting.sendJsonPOSTRequest(main, "",
HttpRequestForTesting.getMultitenantUrl(tenantIdentifier, "/recipe/multitenancy/tenant/user"),
requestBody, 1000, 1000, null,
SemVer.v3_0.get(), "multitenancy");
WebserverAPI.getLatestCDIVersion().get(), "multitenancy");

return response;
}
Expand All @@ -220,7 +221,7 @@ public static JsonObject disassociateUserFromTenant(TenantIdentifier tenantIdent
JsonObject response = HttpRequestForTesting.sendJsonPOSTRequest(main, "",
HttpRequestForTesting.getMultitenantUrl(tenantIdentifier, "/recipe/multitenancy/tenant/user/remove"),
requestBody, 1000, 1000, null,
SemVer.v3_0.get(), "multitenancy");
WebserverAPI.getLatestCDIVersion().get(), "multitenancy");

assertEquals("OK", response.getAsJsonPrimitive("status").getAsString());
return response;
Expand Down

0 comments on commit bb938de

Please sign in to comment.