Skip to content

Commit

Permalink
fix: more fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
sattvikc committed Aug 29, 2023
1 parent c11e096 commit 09c2247
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 12 deletions.
9 changes: 5 additions & 4 deletions src/main/java/io/supertokens/authRecipe/AuthRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -834,12 +834,13 @@ private static void deleteUserHelper(TransactionConnection con, AppIdentifierWit

if (primaryUserIdToDeleteNonAuthRecipe != null) {
deleteNonAuthRecipeUser(con, appIdentifierWithStorage, primaryUserIdToDeleteNonAuthRecipe);

// this is only done to also delete the user ID mapping in case it exists, since we do not delete in the
// previous call to deleteAuthRecipeUser above.
deleteAuthRecipeUser(con, appIdentifierWithStorage, userToDelete.getSupertokensUserId(),
true);
}

// this is only done to also delete the user ID mapping in case it exists, since we do not delete in the
// previous call to deleteAuthRecipeUser above.
deleteAuthRecipeUser(con, appIdentifierWithStorage, userToDelete.getSupertokensUserId(),
true);
} else {
for (LoginMethod lM : userToDelete.loginMethods) {
io.supertokens.pluginInterface.useridmapping.UserIdMapping mappingResult = lM.getSupertokensUserId().equals(
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/io/supertokens/multitenancy/Multitenancy.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import io.supertokens.featureflag.exceptions.FeatureNotEnabledException;
import io.supertokens.multitenancy.exception.*;
import io.supertokens.pluginInterface.STORAGE_TYPE;
import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo;
import io.supertokens.pluginInterface.authRecipe.LoginMethod;
import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateEmailException;
import io.supertokens.pluginInterface.emailpassword.exceptions.UnknownUserIdException;
import io.supertokens.pluginInterface.exceptions.InvalidConfigException;
Expand Down Expand Up @@ -389,15 +391,40 @@ public static boolean addUserIdToTenant(Main main, TenantIdentifierWithStorage t
.addUserIdToTenant(tenantIdentifierWithStorage, userId);
}

@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
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2023, 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.multitenancy.exception;

public class DisassociationNotAllowedException extends Exception {
public DisassociationNotAllowedException() {
super("Disassociation not allowed");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
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;
import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException;
import io.supertokens.useridmapping.UserIdType;
import io.supertokens.utils.SemVer;
import io.supertokens.webserver.InputParser;
import io.supertokens.webserver.WebserverAPI;
import jakarta.servlet.ServletException;
Expand Down Expand Up @@ -68,7 +70,8 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
}

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

JsonObject result = new JsonObject();
result.addProperty("status", "OK");
Expand All @@ -79,7 +82,10 @@ 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");
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 @@ -720,7 +720,7 @@ public void testThatTenantIdIsNotAllowedForOlderCDIVersion() throws Exception {
}

@Test
public void testGetUserByIdForUserThatBelongsToNoTenant() throws Exception {
public void testThatDisassociationFromAllTenantsIsDisallowed() throws Exception {
if (StorageLayer.getStorage(process.getProcess()).getType() != STORAGE_TYPE.SQL) {
return;
}
Expand All @@ -729,11 +729,16 @@ public void testGetUserByIdForUserThatBelongsToNoTenant() throws Exception {

{
JsonObject user = TestMultitenancyAPIHelper.epSignUp(t1, "[email protected]", "password", process.getProcess());
TestMultitenancyAPIHelper.disassociateUserFromTenant(t1, user.get("id").getAsString(), process.getProcess());
JsonObject userInfoFromId = TestMultitenancyAPIHelper.getEpUserById(t1, user.get("id").getAsString(),
process.getProcess());

assertEquals(0, userInfoFromId.get("tenantIds").getAsJsonArray().size());
{
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());
}
}
}
}

0 comments on commit 09c2247

Please sign in to comment.