Skip to content

Commit 7f5d4b1

Browse files
authored
feat: Userid mapping updates (#50)
* feat * fixes * updates CHANGELOG.md * adds missing TestOnly * fixes * fixes
1 parent 535a5ba commit 7f5d4b1

File tree

6 files changed

+139
-3
lines changed

6 files changed

+139
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
99

10+
## [1.19.0] - 2022-08-10
11+
12+
- Adds compatibility with plugin interface 2.17
13+
1014
## [1.18.0] - 2022-07-25
1115

1216
- Adds support for UserIdMapping recipe

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ plugins {
22
id 'java-library'
33
}
44

5-
version = "1.18.0"
5+
version = "1.19.0"
66

77
repositories {
88
mavenCentral()

pluginInterfaceSupported.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"_comment": "contains a list of plugin interfaces branch names that this core supports",
33
"versions": [
4-
"2.16"
4+
"2.17"
55
]
66
}

src/main/java/io/supertokens/storage/postgresql/Start.java

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateUserIdException;
3232
import io.supertokens.pluginInterface.emailpassword.exceptions.UnknownUserIdException;
3333
import io.supertokens.pluginInterface.emailpassword.sqlStorage.EmailPasswordSQLStorage;
34+
import io.supertokens.pluginInterface.emailverification.EmailVerificationStorage;
3435
import io.supertokens.pluginInterface.emailverification.EmailVerificationTokenInfo;
3536
import io.supertokens.pluginInterface.emailverification.exception.DuplicateEmailVerificationTokenException;
3637
import io.supertokens.pluginInterface.emailverification.sqlStorage.EmailVerificationSQLStorage;
3738
import io.supertokens.pluginInterface.exceptions.QuitProgramFromPluginException;
3839
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
3940
import io.supertokens.pluginInterface.exceptions.StorageTransactionLogicException;
41+
import io.supertokens.pluginInterface.jwt.JWTRecipeStorage;
4042
import io.supertokens.pluginInterface.jwt.JWTSigningKeyInfo;
4143
import io.supertokens.pluginInterface.jwt.exceptions.DuplicateKeyIdException;
4244
import io.supertokens.pluginInterface.jwt.sqlstorage.JWTRecipeSQLStorage;
@@ -45,6 +47,7 @@
4547
import io.supertokens.pluginInterface.passwordless.exception.*;
4648
import io.supertokens.pluginInterface.passwordless.sqlStorage.PasswordlessSQLStorage;
4749
import io.supertokens.pluginInterface.session.SessionInfo;
50+
import io.supertokens.pluginInterface.session.SessionStorage;
4851
import io.supertokens.pluginInterface.session.sqlStorage.SessionSQLStorage;
4952
import io.supertokens.pluginInterface.sqlStorage.TransactionConnection;
5053
import io.supertokens.pluginInterface.thirdparty.exception.DuplicateThirdPartyUserException;
@@ -53,7 +56,9 @@
5356
import io.supertokens.pluginInterface.useridmapping.UserIdMappingStorage;
5457
import io.supertokens.pluginInterface.useridmapping.exception.UnknownSuperTokensUserIdException;
5558
import io.supertokens.pluginInterface.useridmapping.exception.UserIdMappingAlreadyExistsException;
59+
import io.supertokens.pluginInterface.usermetadata.UserMetadataStorage;
5660
import io.supertokens.pluginInterface.usermetadata.sqlStorage.UserMetadataSQLStorage;
61+
import io.supertokens.pluginInterface.userroles.UserRolesStorage;
5762
import io.supertokens.pluginInterface.userroles.exception.DuplicateUserRoleMappingException;
5863
import io.supertokens.pluginInterface.userroles.exception.UnknownRoleException;
5964
import io.supertokens.pluginInterface.userroles.sqlStorage.UserRolesSQLStorage;
@@ -72,6 +77,8 @@
7277
import java.sql.Connection;
7378
import java.sql.SQLException;
7479
import java.sql.SQLTransactionRollbackException;
80+
import java.util.ArrayList;
81+
import java.util.HashMap;
7582
import java.util.List;
7683

7784
public class Start
@@ -540,6 +547,84 @@ public boolean canBeUsed(String configFilePath) {
540547
return Config.canBeUsed(configFilePath);
541548
}
542549

550+
@Override
551+
public boolean isUserIdBeingUsedInNonAuthRecipe(String className, String userId) throws StorageQueryException {
552+
// check if the input userId is being used in nonAuthRecipes.
553+
if (className.equals(SessionStorage.class.getName())) {
554+
String[] sessionHandlesForUser = getAllNonExpiredSessionHandlesForUser(userId);
555+
return sessionHandlesForUser.length > 0;
556+
} else if (className.equals(UserRolesStorage.class.getName())) {
557+
String[] roles = getRolesForUser(userId);
558+
return roles.length > 0;
559+
} else if (className.equals(UserMetadataStorage.class.getName())) {
560+
JsonObject userMetadata = getUserMetadata(userId);
561+
return userMetadata != null;
562+
} else if (className.equals(EmailVerificationStorage.class.getName())) {
563+
try {
564+
return EmailVerificationQueries.isUserIdBeingUsedForEmailVerification(this, userId);
565+
} catch (SQLException e) {
566+
throw new StorageQueryException(e);
567+
}
568+
} else if (className.equals(JWTRecipeStorage.class.getName())) {
569+
return false;
570+
} else {
571+
throw new IllegalStateException("ClassName: " + className + " is not part of NonAuthRecipeStorage");
572+
}
573+
}
574+
575+
@TestOnly
576+
@Override
577+
public void addInfoToNonAuthRecipesBasedOnUserId(String className, String userId) throws StorageQueryException {
578+
// add entries to nonAuthRecipe tables with input userId
579+
if (className.equals(SessionStorage.class.getName())) {
580+
try {
581+
createNewSession("sessionHandle", userId, "refreshTokenHash", new JsonObject(),
582+
System.currentTimeMillis() + 1000000, new JsonObject(), System.currentTimeMillis());
583+
} catch (Exception e) {
584+
throw new StorageQueryException(e);
585+
}
586+
} else if (className.equals(UserRolesStorage.class.getName())) {
587+
try {
588+
String role = "testRole";
589+
this.startTransaction(con -> {
590+
createNewRoleOrDoNothingIfExists_Transaction(con, role);
591+
return null;
592+
});
593+
try {
594+
addRoleToUser(userId, role);
595+
} catch (Exception e) {
596+
throw new StorageTransactionLogicException(e);
597+
}
598+
} catch (StorageTransactionLogicException e) {
599+
throw new StorageQueryException(e.actualException);
600+
}
601+
} else if (className.equals(EmailVerificationStorage.class.getName())) {
602+
try {
603+
EmailVerificationTokenInfo info = new EmailVerificationTokenInfo(userId, "someToken", 10000,
604+
605+
addEmailVerificationToken(info);
606+
607+
} catch (DuplicateEmailVerificationTokenException e) {
608+
throw new StorageQueryException(e);
609+
}
610+
} else if (className.equals(UserMetadataStorage.class.getName())) {
611+
JsonObject data = new JsonObject();
612+
data.addProperty("test", "testData");
613+
try {
614+
this.startTransaction(con -> {
615+
setUserMetadata_Transaction(con, userId, data);
616+
return null;
617+
});
618+
} catch (StorageTransactionLogicException e) {
619+
throw new StorageQueryException(e);
620+
}
621+
} else if (className.equals(JWTRecipeStorage.class.getName())) {
622+
/* Since JWT recipe tables do not store userId we do not add any data to them */
623+
} else {
624+
throw new IllegalStateException("ClassName: " + className + " is not part of NonAuthRecipeStorage");
625+
}
626+
}
627+
543628
@Override
544629
public void signUp(UserInfo userInfo)
545630
throws StorageQueryException, DuplicateUserIdException, DuplicateEmailException {
@@ -1717,4 +1802,14 @@ public boolean updateOrDeleteExternalUserIdInfo(String userId, boolean isSuperTo
17171802
throw new StorageQueryException(e);
17181803
}
17191804
}
1805+
1806+
@Override
1807+
public HashMap<String, String> getUserIdMappingForSuperTokensIds(ArrayList<String> userIds)
1808+
throws StorageQueryException {
1809+
try {
1810+
return UserIdMappingQueries.getUserIdMappingWithUserIds(this, userIds);
1811+
} catch (SQLException e) {
1812+
throw new StorageQueryException(e);
1813+
}
1814+
}
17201815
}

src/main/java/io/supertokens/storage/postgresql/queries/EmailVerificationQueries.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static String getQueryToCreateEmailVerificationTokensTable(Start start) {
5353
String emailVerificationTokensTable = Config.getConfig(start).getEmailVerificationTokensTable();
5454
// @formatter:off
5555
return "CREATE TABLE IF NOT EXISTS " + emailVerificationTokensTable + " ("
56-
+ "user_id VARCHAR(128) NOT NULL,"
56+
+ "user_id VARCHAR(128) NOT NULL,"
5757
+ "email VARCHAR(256) NOT NULL,"
5858
+ "token VARCHAR(128) NOT NULL CONSTRAINT " + Utils.getConstraintName(schema, emailVerificationTokensTable, "token", "key") + " UNIQUE,"
5959
+ "token_expiry BIGINT NOT NULL,"
@@ -232,6 +232,15 @@ public static void revokeAllTokens(Start start, String userId, String email)
232232
});
233233
}
234234

235+
public static boolean isUserIdBeingUsedForEmailVerification(Start start, String userId)
236+
throws SQLException, StorageQueryException {
237+
String QUERY = "SELECT * FROM " + getConfig(start).getEmailVerificationTokensTable() + " WHERE user_id = ?";
238+
239+
return execute(start, QUERY, pst -> {
240+
pst.setString(1, userId);
241+
}, ResultSet::next);
242+
}
243+
235244
private static class EmailVerificationTokenInfoRowMapper
236245
implements RowMapper<EmailVerificationTokenInfo, ResultSet> {
237246
private static final EmailVerificationTokenInfoRowMapper INSTANCE = new EmailVerificationTokenInfoRowMapper();

src/main/java/io/supertokens/storage/postgresql/queries/UserIdMappingQueries.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.sql.ResultSet;
2828
import java.sql.SQLException;
2929
import java.util.ArrayList;
30+
import java.util.HashMap;
3031

3132
import static io.supertokens.storage.postgresql.QueryExecutorTemplate.execute;
3233
import static io.supertokens.storage.postgresql.QueryExecutorTemplate.update;
@@ -107,6 +108,33 @@ public static UserIdMapping[] getUserIdMappingWithEitherSuperTokensUserIdOrExter
107108

108109
}
109110

111+
public static HashMap<String, String> getUserIdMappingWithUserIds(Start start, ArrayList<String> userIds)
112+
throws SQLException, StorageQueryException {
113+
StringBuilder QUERY = new StringBuilder(
114+
"SELECT * FROM " + Config.getConfig(start).getUserIdMappingTable() + " WHERE supertokens_user_id IN (");
115+
for (int i = 0; i < userIds.size(); i++) {
116+
QUERY.append("?");
117+
if (i != userIds.size() - 1) {
118+
// not the last element
119+
QUERY.append(",");
120+
}
121+
}
122+
QUERY.append(")");
123+
return execute(start, QUERY.toString(), pst -> {
124+
for (int i = 0; i < userIds.size(); i++) {
125+
// i+1 cause this starts with 1 and not 0
126+
pst.setString(i + 1, userIds.get(i));
127+
}
128+
}, result -> {
129+
HashMap<String, String> userIdMappings = new HashMap<>();
130+
while (result.next()) {
131+
UserIdMapping temp = UserIdMappingRowMapper.getInstance().mapOrThrow(result);
132+
userIdMappings.put(temp.superTokensUserId, temp.externalUserId);
133+
}
134+
return userIdMappings;
135+
});
136+
}
137+
110138
public static boolean deleteUserIdMappingWithSuperTokensUserId(Start start, String userId)
111139
throws SQLException, StorageQueryException {
112140
String QUERY = "DELETE FROM " + Config.getConfig(start).getUserIdMappingTable()

0 commit comments

Comments
 (0)