diff --git a/src/main/java/io/supertokens/pluginInterface/multitenancy/TenantConfig.java b/src/main/java/io/supertokens/pluginInterface/multitenancy/TenantConfig.java index f68ee35d..2bde4237 100644 --- a/src/main/java/io/supertokens/pluginInterface/multitenancy/TenantConfig.java +++ b/src/main/java/io/supertokens/pluginInterface/multitenancy/TenantConfig.java @@ -17,9 +17,11 @@ package io.supertokens.pluginInterface.multitenancy; import com.google.gson.Gson; +import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.annotations.SerializedName; import io.supertokens.pluginInterface.Storage; +import io.supertokens.pluginInterface.utils.Utils; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -41,17 +43,35 @@ public class TenantConfig { @SerializedName("passwordless") public final PasswordlessConfig passwordlessConfig; + @Nonnull + @SerializedName("totp") + public final TotpConfig totpConfig; + + @Nullable + @SerializedName("firstFactors") + public final String[] firstFactors; + + @Nullable + @SerializedName("defaultRequiredFactorIds") + public final String[] defaultRequiredFactorIds; + @Nonnull public final JsonObject coreConfig; public TenantConfig(@Nonnull TenantIdentifier tenantIdentifier, @Nonnull EmailPasswordConfig emailPasswordConfig, @Nonnull ThirdPartyConfig thirdPartyConfig, - @Nonnull PasswordlessConfig passwordlessConfig, @Nullable JsonObject coreConfig) { + @Nonnull PasswordlessConfig passwordlessConfig, + @Nonnull TotpConfig totpConfig, + @Nullable String[] firstFactors, @Nullable String[] defaultRequiredFactorIds, + @Nullable JsonObject coreConfig) { this.tenantIdentifier = tenantIdentifier; this.coreConfig = coreConfig == null ? new JsonObject() : coreConfig; this.emailPasswordConfig = emailPasswordConfig; this.passwordlessConfig = passwordlessConfig; this.thirdPartyConfig = thirdPartyConfig; + this.totpConfig = totpConfig; + this.firstFactors = firstFactors; + this.defaultRequiredFactorIds = defaultRequiredFactorIds; } public TenantConfig(TenantConfig other) { @@ -62,6 +82,9 @@ public TenantConfig(TenantConfig other) { this.emailPasswordConfig = new EmailPasswordConfig(other.emailPasswordConfig.enabled); this.passwordlessConfig = new PasswordlessConfig(other.passwordlessConfig.enabled); this.thirdPartyConfig = new ThirdPartyConfig(other.thirdPartyConfig.enabled, other.thirdPartyConfig.providers.clone()); + this.totpConfig = new TotpConfig(other.totpConfig.enabled); + this.firstFactors = other.firstFactors == null ? null : other.firstFactors.clone(); + this.defaultRequiredFactorIds = other.defaultRequiredFactorIds == null ? null : other.defaultRequiredFactorIds.clone(); } public boolean deepEquals(TenantConfig other) { @@ -72,6 +95,9 @@ public boolean deepEquals(TenantConfig other) { this.emailPasswordConfig.equals(other.emailPasswordConfig) && this.passwordlessConfig.equals(other.passwordlessConfig) && this.thirdPartyConfig.equals(other.thirdPartyConfig) && + this.totpConfig.equals(other.totpConfig) && + Utils.unorderedArrayEquals(this.firstFactors, other.firstFactors) && + Utils.unorderedArrayEquals(this.defaultRequiredFactorIds, other.defaultRequiredFactorIds) && this.coreConfig.equals(other.coreConfig); } @@ -94,7 +120,6 @@ public JsonObject toJson(boolean shouldProtectDbConfig, Storage storage, String[ JsonObject tenantConfigObject = gson.toJsonTree(this).getAsJsonObject(); tenantConfigObject.add("thirdParty", this.thirdPartyConfig.toJson()); - tenantConfigObject.addProperty("tenantId", this.tenantIdentifier.getTenantId()); if (shouldProtectDbConfig) { diff --git a/src/main/java/io/supertokens/pluginInterface/multitenancy/ThirdPartyConfig.java b/src/main/java/io/supertokens/pluginInterface/multitenancy/ThirdPartyConfig.java index d77a3e75..9ee2352b 100644 --- a/src/main/java/io/supertokens/pluginInterface/multitenancy/ThirdPartyConfig.java +++ b/src/main/java/io/supertokens/pluginInterface/multitenancy/ThirdPartyConfig.java @@ -20,6 +20,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import io.supertokens.pluginInterface.utils.Utils; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -48,38 +49,6 @@ public JsonObject toJson() { return result; } - public static boolean unorderedArrayEquals(Object[] array1, Object[] array2) { - if (array1 == null && array2 == null) { - return true; - } else if (array1 == null || array2 == null) { - return false; - } - - List items1 = List.of(array1); - List items2 = new ArrayList<>(); - items2.addAll(Arrays.asList(array2)); - - if (items1.size() != items2.size()) return false; - - for (Object p1 : items1) { - boolean found = false; - for (Object p2 : items2) { - if (p1.equals(p2)) { - found = true; - break; - } - } - - if (!found) { - return false; - } else { - items2.remove(p1); - } - } - - return true; - } - public static class Provider { @Nonnull @@ -189,7 +158,7 @@ public boolean equals(Object other) { Provider otherProvider = (Provider) other; return Objects.equals(otherProvider.thirdPartyId, this.thirdPartyId) && Objects.equals(otherProvider.name, this.name) && - unorderedArrayEquals(otherProvider.clients, this.clients) && + Utils.unorderedArrayEquals(otherProvider.clients, this.clients) && Objects.equals(otherProvider.authorizationEndpoint, this.authorizationEndpoint) && Objects.equals(otherProvider.authorizationEndpointQueryParams, this.authorizationEndpointQueryParams) && @@ -245,7 +214,7 @@ public boolean equals(Object other) { return Objects.equals(otherProviderClient.clientType, this.clientType) && otherProviderClient.clientId.equals(this.clientId) && Objects.equals(otherProviderClient.clientSecret, this.clientSecret) && - unorderedArrayEquals(otherProviderClient.scope, this.scope) && + Utils.unorderedArrayEquals(otherProviderClient.scope, this.scope) && otherProviderClient.forcePKCE == this.forcePKCE && Objects.equals(otherProviderClient.additionalConfig, this.additionalConfig); } @@ -310,7 +279,7 @@ public boolean equals(Object other) { if (other instanceof ThirdPartyConfig) { ThirdPartyConfig otherThirdPartyConfig = (ThirdPartyConfig) other; return otherThirdPartyConfig.enabled == this.enabled && - unorderedArrayEquals(otherThirdPartyConfig.providers, this.providers); + Utils.unorderedArrayEquals(otherThirdPartyConfig.providers, this.providers); } return false; } diff --git a/src/main/java/io/supertokens/pluginInterface/multitenancy/TotpConfig.java b/src/main/java/io/supertokens/pluginInterface/multitenancy/TotpConfig.java new file mode 100644 index 00000000..47d42349 --- /dev/null +++ b/src/main/java/io/supertokens/pluginInterface/multitenancy/TotpConfig.java @@ -0,0 +1,34 @@ +/* + * 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.pluginInterface.multitenancy; + +public class TotpConfig { + public boolean enabled; + + public TotpConfig(boolean enabled) { + this.enabled = enabled; + } + + @Override + public boolean equals(Object other) { + if (other instanceof TotpConfig) { + TotpConfig otherTotpConfig = (TotpConfig) other; + return otherTotpConfig.enabled == this.enabled; + } + return false; + } +} diff --git a/src/main/java/io/supertokens/pluginInterface/utils/Utils.java b/src/main/java/io/supertokens/pluginInterface/utils/Utils.java new file mode 100644 index 00000000..0daa85d3 --- /dev/null +++ b/src/main/java/io/supertokens/pluginInterface/utils/Utils.java @@ -0,0 +1,71 @@ +/* + * 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.pluginInterface.utils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +public class Utils { + public static boolean unorderedStringArrayEquals(String[] arr1, String[] arr2) { + if (arr1 == null && arr2 == null) { + return true; + } + + if (arr1 == null || arr2 == null) { + return false; + } + + Set set1 = Set.of(arr1); + Set set2 = Set.of(arr2); + + return set1.equals(set2); + } + + public static boolean unorderedArrayEquals(Object[] array1, Object[] array2) { + if (array1 == null && array2 == null) { + return true; + } else if (array1 == null || array2 == null) { + return false; + } + + List items1 = List.of(array1); + List items2 = new ArrayList<>(); + items2.addAll(Arrays.asList(array2)); + + if (items1.size() != items2.size()) return false; + + for (Object p1 : items1) { + boolean found = false; + for (Object p2 : items2) { + if (p1.equals(p2)) { + found = true; + break; + } + } + + if (!found) { + return false; + } else { + items2.remove(p1); + } + } + + return true; + } +}