|
16 | 16 |
|
17 | 17 | package io.supertokens.pluginInterface.authRecipe; |
18 | 18 |
|
| 19 | +import com.google.gson.JsonArray; |
| 20 | +import com.google.gson.JsonObject; |
| 21 | +import com.google.gson.JsonPrimitive; |
19 | 22 | import io.supertokens.pluginInterface.RECIPE_ID; |
20 | 23 |
|
21 | | -public abstract class AuthRecipeUserInfo { |
| 24 | +import java.util.*; |
22 | 25 |
|
23 | | - public String id; |
| 26 | +public class AuthRecipeUserInfo { |
| 27 | + |
| 28 | + private final String id; |
| 29 | + |
| 30 | + private String externalUserId = null; |
| 31 | + |
| 32 | + public boolean isPrimaryUser; |
| 33 | + |
| 34 | + public LoginMethod[] loginMethods; |
| 35 | + |
| 36 | + public Set<String> tenantIds; |
24 | 37 |
|
25 | 38 | public long timeJoined; |
26 | 39 |
|
27 | | - public final String[] tenantIds; |
| 40 | + private boolean didCallSetExternalUserId = false; |
| 41 | + |
| 42 | + public void setExternalUserId(String externalUserId) { |
| 43 | + didCallSetExternalUserId = true; |
| 44 | + this.externalUserId = externalUserId; |
| 45 | + for (LoginMethod loginMethod : this.loginMethods) { |
| 46 | + if (loginMethod.getSupertokensUserId().equals(this.id)) { |
| 47 | + loginMethod.setExternalUserId(externalUserId); |
| 48 | + } |
| 49 | + } |
| 50 | + } |
28 | 51 |
|
29 | | - public AuthRecipeUserInfo(String id, long timeJoined, String[] tenantIds) { |
| 52 | + public String getSupertokensOrExternalUserId() { |
| 53 | + assert (this.didCallSetExternalUserId); |
| 54 | + |
| 55 | + if (this.externalUserId != null) { |
| 56 | + return this.externalUserId; |
| 57 | + } |
| 58 | + return this.id; |
| 59 | + } |
| 60 | + |
| 61 | + public String getSupertokensUserId() { |
| 62 | + return this.id; |
| 63 | + } |
| 64 | + |
| 65 | + protected AuthRecipeUserInfo(String id, Boolean isPrimaryUser, LoginMethod loginMethods) { |
| 66 | + assert (isPrimaryUser != null); |
30 | 67 | this.id = id; |
31 | | - this.timeJoined = timeJoined; |
32 | | - this.tenantIds = tenantIds; |
| 68 | + this.isPrimaryUser = isPrimaryUser; |
| 69 | + this.loginMethods = new LoginMethod[]{loginMethods}; |
| 70 | + this.timeJoined = loginMethods.timeJoined; |
| 71 | + this.tenantIds = new HashSet<>(); |
| 72 | + this.tenantIds.addAll(loginMethods.tenantIds); |
| 73 | + } |
| 74 | + |
| 75 | + public static AuthRecipeUserInfo create(String id, Boolean isPrimaryUser, LoginMethod loginMethod) { |
| 76 | + assert (isPrimaryUser != null); |
| 77 | + return new AuthRecipeUserInfo(id, isPrimaryUser, loginMethod); |
| 78 | + } |
| 79 | + |
| 80 | + public void addLoginMethod(LoginMethod loginMethod) { |
| 81 | + for (LoginMethod method : this.loginMethods) { |
| 82 | + if (method.equals(loginMethod)) { |
| 83 | + return; |
| 84 | + } |
| 85 | + } |
| 86 | + LoginMethod[] newLoginMethods = new LoginMethod[this.loginMethods.length + 1]; |
| 87 | + System.arraycopy(this.loginMethods, 0, newLoginMethods, 0, this.loginMethods.length); |
| 88 | + newLoginMethods[this.loginMethods.length] = loginMethod; |
| 89 | + this.loginMethods = Arrays.stream(newLoginMethods).sorted((o1, o2) -> { |
| 90 | + if (o1.timeJoined < o2.timeJoined) { |
| 91 | + return -1; |
| 92 | + } else if (o1.timeJoined > o2.timeJoined) { |
| 93 | + return 1; |
| 94 | + } |
| 95 | + return 0; |
| 96 | + }).toArray(LoginMethod[]::new); |
| 97 | + if (timeJoined > loginMethod.timeJoined) { |
| 98 | + this.timeJoined = loginMethod.timeJoined; |
| 99 | + } |
| 100 | + |
| 101 | + this.tenantIds.addAll(loginMethod.tenantIds); |
33 | 102 | } |
34 | 103 |
|
35 | | - public abstract RECIPE_ID getRecipeId(); |
| 104 | + @Override |
| 105 | + public boolean equals(Object other) { |
| 106 | + if (!(other instanceof AuthRecipeUserInfo)) { |
| 107 | + return false; |
| 108 | + } |
| 109 | + AuthRecipeUserInfo otherUser = (AuthRecipeUserInfo) other; |
| 110 | + return this.id.equals(otherUser.id) && this.isPrimaryUser == otherUser.isPrimaryUser |
| 111 | + && this.timeJoined == otherUser.timeJoined && Arrays.equals(this.loginMethods, otherUser.loginMethods) |
| 112 | + && this.tenantIds.equals(otherUser.tenantIds); |
| 113 | + } |
| 114 | + |
| 115 | + @Override |
| 116 | + public int hashCode() { |
| 117 | + // combine hash codes of all fields |
| 118 | + // We multiply with 31 because it's a prime number. |
| 119 | + int hashCode = this.id.hashCode(); |
| 120 | + hashCode = 31 * hashCode + Boolean.hashCode(this.isPrimaryUser); |
| 121 | + hashCode = 31 * hashCode + Long.hashCode(this.timeJoined); |
| 122 | + hashCode = 31 * hashCode + Arrays.hashCode(this.loginMethods); |
| 123 | + hashCode = 31 * hashCode + this.tenantIds.hashCode(); |
| 124 | + return hashCode; |
| 125 | + } |
36 | 126 |
|
| 127 | + public JsonObject toJson() { |
| 128 | + if (!didCallSetExternalUserId) { |
| 129 | + throw new RuntimeException("Found a bug: Did you forget to call setExternalUserId?"); |
| 130 | + } |
| 131 | + JsonObject jsonObject = new JsonObject(); |
| 132 | + jsonObject.addProperty("id", getSupertokensOrExternalUserId()); |
| 133 | + jsonObject.addProperty("isPrimaryUser", this.isPrimaryUser); |
| 134 | + JsonArray tenantIds = new JsonArray(); |
| 135 | + for (String tenant : this.tenantIds) { |
| 136 | + tenantIds.add(new JsonPrimitive(tenant)); |
| 137 | + } |
| 138 | + jsonObject.add("tenantIds", tenantIds); |
| 139 | + jsonObject.addProperty("timeJoined", this.timeJoined); |
| 140 | + |
| 141 | + // now we add unique emails, phone numbers and third party across all login methods |
| 142 | + Set<String> emails = new HashSet<>(); |
| 143 | + Set<String> phoneNumbers = new HashSet<>(); |
| 144 | + Set<LoginMethod.ThirdParty> thirdParty = new HashSet<>(); |
| 145 | + for (LoginMethod loginMethod : this.loginMethods) { |
| 146 | + if (loginMethod.email != null) { |
| 147 | + emails.add(loginMethod.email); |
| 148 | + } |
| 149 | + if (loginMethod.phoneNumber != null) { |
| 150 | + phoneNumbers.add(loginMethod.phoneNumber); |
| 151 | + } |
| 152 | + if (loginMethod.thirdParty != null) { |
| 153 | + thirdParty.add(loginMethod.thirdParty); |
| 154 | + } |
| 155 | + } |
| 156 | + JsonArray emailsJson = new JsonArray(); |
| 157 | + for (String email : emails) { |
| 158 | + emailsJson.add(new JsonPrimitive(email)); |
| 159 | + } |
| 160 | + jsonObject.add("emails", emailsJson); |
| 161 | + JsonArray phoneNumbersJson = new JsonArray(); |
| 162 | + for (String phoneNumber : phoneNumbers) { |
| 163 | + phoneNumbersJson.add(new JsonPrimitive(phoneNumber)); |
| 164 | + } |
| 165 | + jsonObject.add("phoneNumbers", phoneNumbersJson); |
| 166 | + JsonArray thirdPartyJson = new JsonArray(); |
| 167 | + for (LoginMethod.ThirdParty tpInfo : thirdParty) { |
| 168 | + JsonObject j = new JsonObject(); |
| 169 | + j.addProperty("id", tpInfo.id); |
| 170 | + j.addProperty("userId", tpInfo.userId); |
| 171 | + thirdPartyJson.add(j); |
| 172 | + } |
| 173 | + jsonObject.add("thirdParty", thirdPartyJson); |
| 174 | + |
| 175 | + // now we add login methods.. |
| 176 | + JsonArray loginMethodsArr = new JsonArray(); |
| 177 | + for (LoginMethod lM : this.loginMethods) { |
| 178 | + JsonObject lMJsonObject = new JsonObject(); |
| 179 | + JsonArray lMTenantIds = new JsonArray(); |
| 180 | + for (String tenant : lM.tenantIds) { |
| 181 | + lMTenantIds.add(new JsonPrimitive(tenant)); |
| 182 | + } |
| 183 | + lMJsonObject.add("tenantIds", lMTenantIds); |
| 184 | + lMJsonObject.addProperty("recipeUserId", lM.getSupertokensOrExternalUserId()); |
| 185 | + lMJsonObject.addProperty("verified", lM.verified); |
| 186 | + lMJsonObject.addProperty("timeJoined", lM.timeJoined); |
| 187 | + lMJsonObject.addProperty("recipeId", lM.recipeId.toString()); |
| 188 | + if (lM.email != null) { |
| 189 | + lMJsonObject.addProperty("email", lM.email); |
| 190 | + } |
| 191 | + if (lM.phoneNumber != null) { |
| 192 | + lMJsonObject.addProperty("phoneNumber", lM.phoneNumber); |
| 193 | + } |
| 194 | + if (lM.thirdParty != null) { |
| 195 | + JsonObject thirdPartyJsonObject = new JsonObject(); |
| 196 | + thirdPartyJsonObject.addProperty("id", lM.thirdParty.id); |
| 197 | + thirdPartyJsonObject.addProperty("userId", lM.thirdParty.userId); |
| 198 | + lMJsonObject.add("thirdParty", thirdPartyJsonObject); |
| 199 | + } |
| 200 | + loginMethodsArr.add(lMJsonObject); |
| 201 | + } |
| 202 | + jsonObject.add("loginMethods", loginMethodsArr); |
| 203 | + return jsonObject; |
| 204 | + } |
| 205 | + |
| 206 | + public JsonObject toJsonWithoutAccountLinking() { |
| 207 | + if (!didCallSetExternalUserId) { |
| 208 | + throw new RuntimeException("Found a bug: Did you forget to call setExternalUserId?"); |
| 209 | + } |
| 210 | + // this is for older CDI versions. |
| 211 | + if (this.loginMethods.length != 1) { |
| 212 | + throw new IllegalStateException( |
| 213 | + "Please use a CDI version that is greater than the one in which account linking feature was " + |
| 214 | + "enabled."); |
| 215 | + } |
| 216 | + LoginMethod loginMethod = loginMethods[0]; |
| 217 | + JsonObject jsonObject = new JsonObject(); |
| 218 | + jsonObject.addProperty("id", loginMethod.getSupertokensOrExternalUserId()); |
| 219 | + jsonObject.addProperty("timeJoined", loginMethod.timeJoined); |
| 220 | + JsonArray tenantIds = new JsonArray(); |
| 221 | + for (String tenant : loginMethod.tenantIds) { |
| 222 | + tenantIds.add(new JsonPrimitive(tenant)); |
| 223 | + } |
| 224 | + jsonObject.add("tenantIds", tenantIds); |
| 225 | + if (loginMethod.recipeId == RECIPE_ID.EMAIL_PASSWORD) { |
| 226 | + jsonObject.addProperty("email", loginMethod.email); |
| 227 | + } else if (loginMethod.recipeId == RECIPE_ID.THIRD_PARTY) { |
| 228 | + jsonObject.addProperty("email", loginMethod.email); |
| 229 | + JsonObject thirdPartyJson = new JsonObject(); |
| 230 | + assert loginMethod.thirdParty != null; |
| 231 | + thirdPartyJson.addProperty("id", loginMethod.thirdParty.id); |
| 232 | + thirdPartyJson.addProperty("userId", loginMethod.thirdParty.userId); |
| 233 | + jsonObject.add("thirdParty", thirdPartyJson); |
| 234 | + } else if (loginMethod.recipeId == RECIPE_ID.PASSWORDLESS) { |
| 235 | + if (loginMethod.email != null) { |
| 236 | + jsonObject.addProperty("email", loginMethod.email); |
| 237 | + } |
| 238 | + if (loginMethod.phoneNumber != null) { |
| 239 | + jsonObject.addProperty("phoneNumber", loginMethod.phoneNumber); |
| 240 | + } |
| 241 | + } else { |
| 242 | + throw new UnsupportedOperationException("Please search for bugs"); |
| 243 | + } |
| 244 | + |
| 245 | + return jsonObject; |
| 246 | + } |
37 | 247 | } |
0 commit comments