From 6aad59c0d12b848814bc444c6bd0650c7d5a7db0 Mon Sep 17 00:00:00 2001 From: Sattvik Chakravarthy Date: Mon, 1 May 2023 12:25:06 +0530 Subject: [PATCH 1/3] fix: license tests --- .../test/TestingProcessManager.java | 8 + .../supertokens/test/multitenant/LogTest.java | 6 +- .../multitenant/api/TestLicenseBehaviour.java | 258 ++++++++++++++++++ .../api/TestMultitenancyAPIHelper.java | 32 +++ 4 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java diff --git a/src/test/java/io/supertokens/test/TestingProcessManager.java b/src/test/java/io/supertokens/test/TestingProcessManager.java index ebb7ce5e4..f1f49a8e3 100644 --- a/src/test/java/io/supertokens/test/TestingProcessManager.java +++ b/src/test/java/io/supertokens/test/TestingProcessManager.java @@ -143,6 +143,14 @@ public void kill() throws InterruptedException { killed = true; } + public void killWithoutDeletingData() throws InterruptedException { + if (killed) { + return; + } + main.killForTestingAndWaitForShutdown(); + killed = true; + } + public EventAndException checkOrWaitForEvent(PROCESS_STATE state) throws InterruptedException { return checkOrWaitForEvent(state, 15000); } diff --git a/src/test/java/io/supertokens/test/multitenant/LogTest.java b/src/test/java/io/supertokens/test/multitenant/LogTest.java index 6e568f643..4f7ce38c4 100644 --- a/src/test/java/io/supertokens/test/multitenant/LogTest.java +++ b/src/test/java/io/supertokens/test/multitenant/LogTest.java @@ -107,7 +107,9 @@ public void testLogThatEachLineIsUniqueOnStartup() throws Exception { new PasswordlessConfig(true), new JsonObject()), false); - process.kill(); + assertEquals(7, Multitenancy.getAllTenants(process.getProcess()).length); + + process.killWithoutDeletingData(); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); ByteArrayOutputStream stdOutput = new ByteArrayOutputStream(); @@ -139,6 +141,8 @@ public void testLogThatEachLineIsUniqueOnStartup() throws Exception { assertEquals(uniqueLines.size(), lines.length); + assertEquals(7, Multitenancy.getAllTenants(process.getProcess()).length); + process.kill(); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); } diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java b/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java new file mode 100644 index 000000000..1abc48f24 --- /dev/null +++ b/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java @@ -0,0 +1,258 @@ +/* + * 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.test.multitenant.api; + +import com.google.gson.JsonObject; +import io.supertokens.ProcessState; +import io.supertokens.featureflag.exceptions.FeatureNotEnabledException; +import io.supertokens.multitenancy.exception.BadPermissionException; +import io.supertokens.multitenancy.exception.CannotModifyBaseConfigException; +import io.supertokens.pluginInterface.exceptions.InvalidConfigException; +import io.supertokens.pluginInterface.exceptions.StorageQueryException; +import io.supertokens.pluginInterface.multitenancy.TenantIdentifier; +import io.supertokens.pluginInterface.multitenancy.ThirdPartyConfig; +import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException; +import io.supertokens.storageLayer.StorageLayer; +import io.supertokens.test.TestingProcessManager; +import io.supertokens.test.Utils; +import io.supertokens.test.httpRequest.HttpResponseException; +import io.supertokens.thirdparty.InvalidProviderConfigException; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class TestLicenseBehaviour { + TestingProcessManager.TestingProcess process; + + @AfterClass + public static void afterTesting() { + Utils.afterTesting(); + } + + @After + public void afterEach() throws InterruptedException { + process.kill(); + assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); + } + + @Before + public void beforeEach() throws InterruptedException, InvalidProviderConfigException, + StorageQueryException, FeatureNotEnabledException, TenantOrAppNotFoundException, IOException, + InvalidConfigException, CannotModifyBaseConfigException, BadPermissionException { + Utils.reset(); + + String[] args = {"../"}; + + this.process = TestingProcessManager.start(args); + assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); + } + + private final String OPAQUE_KEY_WITH_MULTITENANCY_FEATURE = "ijaleljUd2kU9XXWLiqFYv5br8nutTxbyBqWypQdv2N-" + + "BocoNriPrnYQd0NXPm8rVkeEocN9ayq0B7c3Pv-BTBIhAZSclXMlgyfXtlwAOJk=9BfESEleW6LyTov47dXu"; + + @Test + public void testAllowLicenseRemovalForCoreWithMultitenancy() throws Exception { + TestMultitenancyAPIHelper.addLicense(OPAQUE_KEY_WITH_MULTITENANCY_FEATURE, process.getProcess()); + + JsonObject coreConfig = new JsonObject(); + StorageLayer.getStorage(new TenantIdentifier(null, null, null), process.getProcess()) + .modifyConfigToAddANewUserPoolForTesting(coreConfig, 1); + + TestMultitenancyAPIHelper.createApp( + process.getProcess(), + new TenantIdentifier(null, null, null), + "a1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.removeLicense(process.getProcess()); + + // Sign up and get user info + JsonObject userInfo = TestMultitenancyAPIHelper.epSignUp(new TenantIdentifier(null, "a1", "t1"), "user@example.com", "password", process.getProcess()); + JsonObject userInfo2 = TestMultitenancyAPIHelper.getEpUserById(new TenantIdentifier(null, "a1", "t1"), userInfo.get("id").getAsString(), process.getProcess()); + assertEquals(userInfo, userInfo2); + } + + @Test + public void testThatCreationOfNewTenantIsNotAllowedAfterLicenseRemoval() throws Exception { + TestMultitenancyAPIHelper.addLicense(OPAQUE_KEY_WITH_MULTITENANCY_FEATURE, process.getProcess()); + + JsonObject coreConfig = new JsonObject(); + StorageLayer.getStorage(new TenantIdentifier(null, null, null), process.getProcess()) + .modifyConfigToAddANewUserPoolForTesting(coreConfig, 1); + + TestMultitenancyAPIHelper.createApp( + process.getProcess(), + new TenantIdentifier(null, null, null), + "a1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.removeLicense(process.getProcess()); + + try { + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t2", true, true, true, + coreConfig); + fail(); + } catch (HttpResponseException e) { + assertEquals("Http error. Status Code: 402. Message: Cannot use feature: multi_tenancy, because the license key is missing, or doesn't have this feature enabled.", e.getMessage()); + } + } + + @Test + public void testThatCoreCanRestartWithAllTheTenantsWithoutLicenseKey() throws Exception { + TestMultitenancyAPIHelper.addLicense(OPAQUE_KEY_WITH_MULTITENANCY_FEATURE, process.getProcess()); + + JsonObject coreConfig = new JsonObject(); + StorageLayer.getStorage(new TenantIdentifier(null, null, null), process.getProcess()) + .modifyConfigToAddANewUserPoolForTesting(coreConfig, 1); + + TestMultitenancyAPIHelper.createApp( + process.getProcess(), + new TenantIdentifier(null, null, null), + "a1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t1", true, true, true, + coreConfig); + + JsonObject tenants = TestMultitenancyAPIHelper.listConnectionUriDomains(new TenantIdentifier(null, null, null), + process.getProcess()); + + TestMultitenancyAPIHelper.removeLicense(process.getProcess()); + + // Restart the core + process.killWithoutDeletingData(); + assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); + + String[] args = {"../"}; + this.process = TestingProcessManager.start(args); + process.startProcess(); + assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STARTED)); + + JsonObject tenants2 = TestMultitenancyAPIHelper.listConnectionUriDomains(new TenantIdentifier(null, null, null), + process.getProcess()); + + // Ensure all tenants are loaded back correctly + assertEquals(tenants, tenants2); + + try { + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t2", true, true, true, + coreConfig); + fail(); + } catch (HttpResponseException e) { + assertEquals("Http error. Status Code: 402. Message: Cannot use feature: multi_tenancy, because the license key is missing, or doesn't have this feature enabled.", e.getMessage()); + } + } + + @Test + public void testThatAddingThirdPartyConfigIsNotAllowedAfterLicenseRemoval() throws Exception { + TestMultitenancyAPIHelper.addLicense(OPAQUE_KEY_WITH_MULTITENANCY_FEATURE, process.getProcess()); + + JsonObject coreConfig = new JsonObject(); + StorageLayer.getStorage(new TenantIdentifier(null, null, null), process.getProcess()) + .modifyConfigToAddANewUserPoolForTesting(coreConfig, 1); + + TestMultitenancyAPIHelper.createApp( + process.getProcess(), + new TenantIdentifier(null, null, null), + "a1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.removeLicense(process.getProcess()); + + try { + TestMultitenancyAPIHelper.addOrUpdateThirdPartyProviderConfig( + new TenantIdentifier(null, "a1", "t1"), + new ThirdPartyConfig.Provider( + "google", "Google", null, null, null, null, null, null, null, null, null, null, null, null + ), + process.getProcess()); + fail(); + } catch (HttpResponseException e) { + assertEquals("Http error. Status Code: 402. Message: Cannot use feature: multi_tenancy, because the license key is missing, or doesn't have this feature enabled.", e.getMessage()); + } + } + + @Test + public void testThatAssociationOfUserWithAnotherTenantIsNotAllowedAfterLicenseRemoval() throws Exception { + TestMultitenancyAPIHelper.addLicense(OPAQUE_KEY_WITH_MULTITENANCY_FEATURE, process.getProcess()); + + JsonObject coreConfig = new JsonObject(); + StorageLayer.getStorage(new TenantIdentifier(null, null, null), process.getProcess()) + .modifyConfigToAddANewUserPoolForTesting(coreConfig, 1); + + TestMultitenancyAPIHelper.createApp( + process.getProcess(), + new TenantIdentifier(null, null, null), + "a1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t2", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.removeLicense(process.getProcess()); + + JsonObject userInfo = TestMultitenancyAPIHelper.epSignUp(new TenantIdentifier(null, "a1", "t1"), "user@example.com", "password", process.getProcess()); + + try { + TestMultitenancyAPIHelper.associateUserToTenant(new TenantIdentifier(null, "a1", "t2"), userInfo.get("id").getAsString(), process.getProcess()); + fail(); + } catch (HttpResponseException e) { + assertEquals("Http error. Status Code: 402. Message: Cannot use feature: multi_tenancy, because the license key is missing, or doesn't have this feature enabled.", e.getMessage()); + } + } +} diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java b/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java index 59680f410..2da5707a5 100644 --- a/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java +++ b/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java @@ -26,6 +26,7 @@ import io.supertokens.test.httpRequest.HttpResponseException; import java.io.IOException; +import java.util.HashMap; import static org.junit.Assert.assertEquals; @@ -259,4 +260,35 @@ public static JsonObject tpSignInUp(TenantIdentifier tenantIdentifier, String th return response.get("user").getAsJsonObject(); } + + public static void addLicense(String licenseKey, Main main) throws HttpResponseException, IOException { + JsonObject licenseKeyRequest = new JsonObject(); + licenseKeyRequest.addProperty("licenseKey", licenseKey); + + JsonObject response = HttpRequestForTesting.sendJsonPUTRequest(main, "", + "http://localhost:3567/ee/license", licenseKeyRequest, + 1000, 1000, null, + Utils.getCdiVersionStringLatestForTests(), null); + assertEquals("OK", response.get("status").getAsString()); + } + + public static void removeLicense(Main main) throws HttpResponseException, IOException { + JsonObject response = HttpRequestForTesting.sendJsonDELETERequest(main, "", + "http://localhost:3567/ee/license", null, + 1000, 1000, null, + Utils.getCdiVersionStringLatestForTests(), null); + assertEquals("OK", response.get("status").getAsString()); + } + + public static JsonObject getEpUserById(TenantIdentifier tenantIdentifier, String userId, Main main) + throws HttpResponseException, IOException { + HashMap map = new HashMap<>(); + map.put("userId", userId); + JsonObject userResponse = HttpRequestForTesting.sendGETRequest(main, "", + HttpRequestForTesting.getMultitenantUrl(tenantIdentifier, "/recipe/user"), + map, 1000, 1000, null, Utils.getCdiVersionStringLatestForTests(), + "emailpassword"); + assertEquals("OK", userResponse.getAsJsonPrimitive("status").getAsString()); + return userResponse.getAsJsonObject("user"); + } } From 1627c0e13f05972b2ecdbc984e2740e005d5a685 Mon Sep 17 00:00:00 2001 From: Sattvik Chakravarthy Date: Mon, 1 May 2023 16:55:01 +0530 Subject: [PATCH 2/3] fix: added test --- .../multitenant/api/TestLicenseBehaviour.java | 32 +++++++++++++++++++ .../api/TestMultitenancyAPIHelper.java | 4 ++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java b/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java index 1abc48f24..54c925d95 100644 --- a/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java +++ b/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java @@ -255,4 +255,36 @@ public void testThatAssociationOfUserWithAnotherTenantIsNotAllowedAfterLicenseRe assertEquals("Http error. Status Code: 402. Message: Cannot use feature: multi_tenancy, because the license key is missing, or doesn't have this feature enabled.", e.getMessage()); } } + + @Test + public void testUpdationOfBaseTenantIsAllowedWithoutLicense() throws Exception { + TestMultitenancyAPIHelper.addLicense(OPAQUE_KEY_WITH_MULTITENANCY_FEATURE, process.getProcess()); + + JsonObject coreConfig = new JsonObject(); + StorageLayer.getStorage(new TenantIdentifier(null, null, null), process.getProcess()) + .modifyConfigToAddANewUserPoolForTesting(coreConfig, 1); + + TestMultitenancyAPIHelper.createApp( + process.getProcess(), + new TenantIdentifier(null, null, null), + "a1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.createTenant( + process.getProcess(), + new TenantIdentifier(null, "a1", null), + "t1", true, true, true, + coreConfig); + + TestMultitenancyAPIHelper.removeLicense(process.getProcess()); + + JsonObject config = new JsonObject(); + TestMultitenancyAPIHelper.createConnectionUriDomain(process.main, new TenantIdentifier(null, null, null), null, true, true, true, new JsonObject() ); + TestMultitenancyAPIHelper.addOrUpdateThirdPartyProviderConfig( + new TenantIdentifier(null, null, null), + new ThirdPartyConfig.Provider( + "google", "Google", null, null, null, null, null, null, null, null, null, null, null, null + ), + process.getProcess()); + } } diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java b/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java index 2da5707a5..7056e583f 100644 --- a/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java +++ b/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java @@ -35,7 +35,9 @@ public static void createConnectionUriDomain(Main main, TenantIdentifier sourceT boolean thirdPartyEnabled, boolean passwordlessEnabled, JsonObject coreConfig) throws HttpResponseException, IOException { JsonObject requestBody = new JsonObject(); - requestBody.addProperty("connectionUriDomain", connectionUriDomain); + if (connectionUriDomain != null) { + requestBody.addProperty("connectionUriDomain", connectionUriDomain); + } requestBody.addProperty("emailPasswordEnabled", emailPasswordEnabled); requestBody.addProperty("thirdPartyEnabled", thirdPartyEnabled); requestBody.addProperty("passwordlessEnabled", passwordlessEnabled); From 09533808fb08f177732f80e2430b97d518b13429 Mon Sep 17 00:00:00 2001 From: Sattvik Chakravarthy Date: Mon, 1 May 2023 17:37:10 +0530 Subject: [PATCH 3/3] fix: pr comment --- .../java/io/supertokens/test/TestingProcessManager.java | 6 +++++- src/test/java/io/supertokens/test/multitenant/LogTest.java | 3 +-- .../test/multitenant/api/TestLicenseBehaviour.java | 4 ++-- .../test/multitenant/api/TestMultitenancyAPIHelper.java | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/test/java/io/supertokens/test/TestingProcessManager.java b/src/test/java/io/supertokens/test/TestingProcessManager.java index f1f49a8e3..9f9c0c639 100644 --- a/src/test/java/io/supertokens/test/TestingProcessManager.java +++ b/src/test/java/io/supertokens/test/TestingProcessManager.java @@ -122,13 +122,17 @@ String[] getArgs() { } public void kill() throws InterruptedException { + kill(true); + } + + public void kill(boolean removeAllInfo) throws InterruptedException { if (killed) { return; } // we check if there are multiple user pool IDs loaded, and if there are, // we clear all the info before killing cause otherwise those extra dbs will retain info // across tests - if (StorageLayer.hasMultipleUserPools(this.main)) { + if (removeAllInfo && StorageLayer.hasMultipleUserPools(this.main)) { try { main.deleteAllInformationForTesting(); } catch (Exception e) { diff --git a/src/test/java/io/supertokens/test/multitenant/LogTest.java b/src/test/java/io/supertokens/test/multitenant/LogTest.java index 4f7ce38c4..2874ce649 100644 --- a/src/test/java/io/supertokens/test/multitenant/LogTest.java +++ b/src/test/java/io/supertokens/test/multitenant/LogTest.java @@ -25,7 +25,6 @@ import io.supertokens.featureflag.FeatureFlagTestContent; import io.supertokens.multitenancy.Multitenancy; import io.supertokens.pluginInterface.multitenancy.*; -import io.supertokens.storageLayer.StorageLayer; import io.supertokens.test.TestingProcessManager; import io.supertokens.test.Utils; import org.junit.AfterClass; @@ -109,7 +108,7 @@ public void testLogThatEachLineIsUniqueOnStartup() throws Exception { assertEquals(7, Multitenancy.getAllTenants(process.getProcess()).length); - process.killWithoutDeletingData(); + process.kill(false); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); ByteArrayOutputStream stdOutput = new ByteArrayOutputStream(); diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java b/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java index 54c925d95..35daf0023 100644 --- a/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java +++ b/src/test/java/io/supertokens/test/multitenant/api/TestLicenseBehaviour.java @@ -130,7 +130,7 @@ public void testThatCreationOfNewTenantIsNotAllowedAfterLicenseRemoval() throws assertEquals("Http error. Status Code: 402. Message: Cannot use feature: multi_tenancy, because the license key is missing, or doesn't have this feature enabled.", e.getMessage()); } } - + @Test public void testThatCoreCanRestartWithAllTheTenantsWithoutLicenseKey() throws Exception { TestMultitenancyAPIHelper.addLicense(OPAQUE_KEY_WITH_MULTITENANCY_FEATURE, process.getProcess()); @@ -157,7 +157,7 @@ public void testThatCoreCanRestartWithAllTheTenantsWithoutLicenseKey() throws Ex TestMultitenancyAPIHelper.removeLicense(process.getProcess()); // Restart the core - process.killWithoutDeletingData(); + process.kill(false); assertNotNull(process.checkOrWaitForEvent(ProcessState.PROCESS_STATE.STOPPED)); String[] args = {"../"}; diff --git a/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java b/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java index 7056e583f..eff19f3d2 100644 --- a/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java +++ b/src/test/java/io/supertokens/test/multitenant/api/TestMultitenancyAPIHelper.java @@ -269,7 +269,7 @@ public static void addLicense(String licenseKey, Main main) throws HttpResponseE JsonObject response = HttpRequestForTesting.sendJsonPUTRequest(main, "", "http://localhost:3567/ee/license", licenseKeyRequest, - 1000, 1000, null, + 2000, 2000, null, Utils.getCdiVersionStringLatestForTests(), null); assertEquals("OK", response.get("status").getAsString()); }