|
17 | 17 |
|
18 | 18 | package io.supertokens.storage.postgresql; |
19 | 19 |
|
20 | | -import ch.qos.logback.classic.Logger; |
| 20 | +import java.lang.reflect.Field; |
| 21 | +import java.sql.BatchUpdateException; |
| 22 | +import java.sql.Connection; |
| 23 | +import java.sql.SQLException; |
| 24 | +import java.sql.SQLTransactionRollbackException; |
| 25 | +import java.util.ArrayList; |
| 26 | +import java.util.HashMap; |
| 27 | +import java.util.List; |
| 28 | +import java.util.Map; |
| 29 | +import java.util.Set; |
| 30 | + |
| 31 | +import javax.annotation.Nonnull; |
| 32 | + |
| 33 | +import org.jetbrains.annotations.NotNull; |
| 34 | +import org.jetbrains.annotations.Nullable; |
| 35 | +import org.jetbrains.annotations.TestOnly; |
| 36 | +import org.postgresql.util.PSQLException; |
| 37 | +import org.postgresql.util.ServerErrorMessage; |
| 38 | +import org.slf4j.LoggerFactory; |
| 39 | + |
21 | 40 | import com.google.gson.JsonObject; |
22 | 41 | import com.google.gson.JsonPrimitive; |
23 | 42 | import com.zaxxer.hikari.pool.HikariPool; |
24 | | -import io.supertokens.pluginInterface.*; |
| 43 | + |
| 44 | +import ch.qos.logback.classic.Logger; |
| 45 | +import io.supertokens.pluginInterface.ActiveUsersSQLStorage; |
| 46 | +import io.supertokens.pluginInterface.ActiveUsersStorage; |
| 47 | +import io.supertokens.pluginInterface.ConfigFieldInfo; |
| 48 | +import io.supertokens.pluginInterface.KeyValueInfo; |
| 49 | +import io.supertokens.pluginInterface.LOG_LEVEL; |
| 50 | +import io.supertokens.pluginInterface.RECIPE_ID; |
| 51 | +import io.supertokens.pluginInterface.STORAGE_TYPE; |
| 52 | +import io.supertokens.pluginInterface.Storage; |
25 | 53 | import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo; |
26 | 54 | import io.supertokens.pluginInterface.authRecipe.LoginMethod; |
27 | 55 | import io.supertokens.pluginInterface.authRecipe.sqlStorage.AuthRecipeSQLStorage; |
|
73 | 101 | import io.supertokens.pluginInterface.passwordless.PasswordlessCode; |
74 | 102 | import io.supertokens.pluginInterface.passwordless.PasswordlessDevice; |
75 | 103 | import io.supertokens.pluginInterface.passwordless.PasswordlessImportUser; |
76 | | -import io.supertokens.pluginInterface.passwordless.exception.*; |
| 104 | +import io.supertokens.pluginInterface.passwordless.exception.DuplicateCodeIdException; |
| 105 | +import io.supertokens.pluginInterface.passwordless.exception.DuplicateDeviceIdHashException; |
| 106 | +import io.supertokens.pluginInterface.passwordless.exception.DuplicateLinkCodeHashException; |
| 107 | +import io.supertokens.pluginInterface.passwordless.exception.DuplicatePhoneNumberException; |
| 108 | +import io.supertokens.pluginInterface.passwordless.exception.UnknownDeviceIdHash; |
77 | 109 | import io.supertokens.pluginInterface.passwordless.sqlStorage.PasswordlessSQLStorage; |
| 110 | +import io.supertokens.pluginInterface.saml.SAMLClaimsInfo; |
| 111 | +import io.supertokens.pluginInterface.saml.SAMLClient; |
| 112 | +import io.supertokens.pluginInterface.saml.SAMLRelayStateInfo; |
| 113 | +import io.supertokens.pluginInterface.saml.SAMLStorage; |
78 | 114 | import io.supertokens.pluginInterface.session.SessionInfo; |
79 | 115 | import io.supertokens.pluginInterface.session.SessionStorage; |
80 | 116 | import io.supertokens.pluginInterface.session.sqlStorage.SessionSQLStorage; |
|
104 | 140 | import io.supertokens.pluginInterface.webauthn.AccountRecoveryTokenInfo; |
105 | 141 | import io.supertokens.pluginInterface.webauthn.WebAuthNOptions; |
106 | 142 | import io.supertokens.pluginInterface.webauthn.WebAuthNStoredCredential; |
107 | | -import io.supertokens.pluginInterface.webauthn.exceptions.*; |
| 143 | +import io.supertokens.pluginInterface.webauthn.exceptions.DuplicateOptionsIdException; |
| 144 | +import io.supertokens.pluginInterface.webauthn.exceptions.DuplicateRecoverAccountTokenException; |
| 145 | +import io.supertokens.pluginInterface.webauthn.exceptions.DuplicateUserEmailException; |
| 146 | +import io.supertokens.pluginInterface.webauthn.exceptions.WebauthNCredentialNotExistsException; |
| 147 | +import io.supertokens.pluginInterface.webauthn.exceptions.WebauthNOptionsNotExistsException; |
108 | 148 | import io.supertokens.pluginInterface.webauthn.slqStorage.WebAuthNSQLStorage; |
| 149 | +import static io.supertokens.storage.postgresql.QueryExecutorTemplate.execute; |
109 | 150 | import io.supertokens.storage.postgresql.annotations.EnvName; |
110 | 151 | import io.supertokens.storage.postgresql.config.Config; |
111 | 152 | import io.supertokens.storage.postgresql.config.PostgreSQLConfig; |
112 | 153 | import io.supertokens.storage.postgresql.output.Logging; |
113 | | -import io.supertokens.storage.postgresql.queries.*; |
114 | | -import org.jetbrains.annotations.NotNull; |
115 | | -import org.jetbrains.annotations.Nullable; |
116 | | -import org.jetbrains.annotations.TestOnly; |
117 | | -import org.postgresql.util.PSQLException; |
118 | | -import org.postgresql.util.ServerErrorMessage; |
119 | | -import org.slf4j.LoggerFactory; |
120 | | - |
121 | | -import javax.annotation.Nonnull; |
122 | | -import java.lang.reflect.Field; |
123 | | -import java.sql.BatchUpdateException; |
124 | | -import java.sql.Connection; |
125 | | -import java.sql.SQLException; |
126 | | -import java.sql.SQLTransactionRollbackException; |
127 | | -import java.util.*; |
128 | | - |
129 | | -import static io.supertokens.storage.postgresql.QueryExecutorTemplate.execute; |
| 154 | +import io.supertokens.storage.postgresql.queries.ActiveUsersQueries; |
| 155 | +import io.supertokens.storage.postgresql.queries.BulkImportQueries; |
| 156 | +import io.supertokens.storage.postgresql.queries.DashboardQueries; |
| 157 | +import io.supertokens.storage.postgresql.queries.EmailPasswordQueries; |
| 158 | +import io.supertokens.storage.postgresql.queries.EmailVerificationQueries; |
| 159 | +import io.supertokens.storage.postgresql.queries.GeneralQueries; |
| 160 | +import io.supertokens.storage.postgresql.queries.JWTSigningQueries; |
| 161 | +import io.supertokens.storage.postgresql.queries.MultitenancyQueries; |
| 162 | +import io.supertokens.storage.postgresql.queries.OAuthQueries; |
| 163 | +import io.supertokens.storage.postgresql.queries.PasswordlessQueries; |
| 164 | +import io.supertokens.storage.postgresql.queries.SAMLQueries; |
| 165 | +import io.supertokens.storage.postgresql.queries.SessionQueries; |
| 166 | +import io.supertokens.storage.postgresql.queries.TOTPQueries; |
| 167 | +import io.supertokens.storage.postgresql.queries.ThirdPartyQueries; |
| 168 | +import io.supertokens.storage.postgresql.queries.UserIdMappingQueries; |
| 169 | +import io.supertokens.storage.postgresql.queries.UserMetadataQueries; |
| 170 | +import io.supertokens.storage.postgresql.queries.UserRolesQueries; |
| 171 | +import io.supertokens.storage.postgresql.queries.WebAuthNQueries; |
130 | 172 |
|
131 | 173 | @WithinOtelSpan |
132 | 174 | public class Start |
133 | 175 | implements SessionSQLStorage, EmailPasswordSQLStorage, EmailVerificationSQLStorage, ThirdPartySQLStorage, |
134 | 176 | JWTRecipeSQLStorage, PasswordlessSQLStorage, UserMetadataSQLStorage, UserRolesSQLStorage, UserIdMappingStorage, |
135 | 177 | UserIdMappingSQLStorage, MultitenancyStorage, MultitenancySQLStorage, DashboardSQLStorage, TOTPSQLStorage, |
136 | 178 | ActiveUsersStorage, ActiveUsersSQLStorage, AuthRecipeSQLStorage, OAuthStorage, BulkImportSQLStorage, |
137 | | - WebAuthNSQLStorage { |
| 179 | + WebAuthNSQLStorage, SAMLStorage { |
138 | 180 |
|
139 | 181 | // these configs are protected from being modified / viewed by the dev using the SuperTokens |
140 | 182 | // SaaS. If the core is not running in SuperTokens SaaS, this array has no effect. |
@@ -1032,6 +1074,8 @@ public void addInfoToNonAuthRecipesBasedOnUserId(TenantIdentifier tenantIdentifi |
1032 | 1074 | //ignore |
1033 | 1075 | } else if (className.equals(OAuthStorage.class.getName())) { |
1034 | 1076 | /* Since OAuth recipe tables do not store userId we do not add any data to them */ |
| 1077 | + } else if (className.equals(SAMLStorage.class.getName())) { |
| 1078 | + //ignore |
1035 | 1079 | } else if (className.equals(ActiveUsersStorage.class.getName())) { |
1036 | 1080 | try { |
1037 | 1081 | ActiveUsersQueries.updateUserLastActive(this, tenantIdentifier.toAppIdentifier(), userId); |
@@ -4392,4 +4436,115 @@ public void deleteExpiredGeneratedOptions() throws StorageQueryException { |
4392 | 4436 | throw new StorageQueryException(e); |
4393 | 4437 | } |
4394 | 4438 | } |
| 4439 | + |
| 4440 | + @Override |
| 4441 | + public SAMLClient createOrUpdateSAMLClient(TenantIdentifier tenantIdentifier, SAMLClient samlClient) |
| 4442 | + throws StorageQueryException, io.supertokens.pluginInterface.saml.exception.DuplicateEntityIdException { |
| 4443 | + try { |
| 4444 | + return SAMLQueries.createOrUpdateSAMLClient(this, tenantIdentifier, samlClient.clientId, samlClient.clientSecret, |
| 4445 | + samlClient.ssoLoginURL, samlClient.redirectURIs.toString(), samlClient.defaultRedirectURI, |
| 4446 | + samlClient.idpEntityId, samlClient.idpSigningCertificate, |
| 4447 | + samlClient.allowIDPInitiatedLogin, samlClient.enableRequestSigning); |
| 4448 | + } catch (SQLException e) { |
| 4449 | + if (e instanceof PSQLException) { |
| 4450 | + PostgreSQLConfig config = Config.getConfig(this); |
| 4451 | + ServerErrorMessage serverMessage = ((PSQLException) e).getServerErrorMessage(); |
| 4452 | + |
| 4453 | + if (isUniqueConstraintError(serverMessage, config.getSAMLClientsTable(), "idp_entity_id")) { |
| 4454 | + throw new io.supertokens.pluginInterface.saml.exception.DuplicateEntityIdException(); |
| 4455 | + } |
| 4456 | + } |
| 4457 | + throw new StorageQueryException(e); |
| 4458 | + } |
| 4459 | + } |
| 4460 | + |
| 4461 | + @Override |
| 4462 | + public boolean removeSAMLClient(TenantIdentifier tenantIdentifier, String clientId) throws StorageQueryException { |
| 4463 | + try { |
| 4464 | + return SAMLQueries.removeSAMLClient(this, tenantIdentifier, clientId); |
| 4465 | + } catch (SQLException e) { |
| 4466 | + throw new StorageQueryException(e); |
| 4467 | + } |
| 4468 | + } |
| 4469 | + |
| 4470 | + @Override |
| 4471 | + public SAMLClient getSAMLClient(TenantIdentifier tenantIdentifier, String clientId) throws StorageQueryException { |
| 4472 | + try { |
| 4473 | + return SAMLQueries.getSAMLClient(this, tenantIdentifier, clientId); |
| 4474 | + } catch (SQLException e) { |
| 4475 | + throw new StorageQueryException(e); |
| 4476 | + } |
| 4477 | + } |
| 4478 | + |
| 4479 | + @Override |
| 4480 | + public SAMLClient getSAMLClientByIDPEntityId(TenantIdentifier tenantIdentifier, String idpEntityId) throws StorageQueryException { |
| 4481 | + try { |
| 4482 | + return SAMLQueries.getSAMLClientByIDPEntityId(this, tenantIdentifier, idpEntityId); |
| 4483 | + } catch (SQLException e) { |
| 4484 | + throw new StorageQueryException(e); |
| 4485 | + } |
| 4486 | + } |
| 4487 | + |
| 4488 | + @Override |
| 4489 | + public List<SAMLClient> getSAMLClients(TenantIdentifier tenantIdentifier) throws StorageQueryException { |
| 4490 | + try { |
| 4491 | + return SAMLQueries.getSAMLClients(this, tenantIdentifier); |
| 4492 | + } catch (SQLException e) { |
| 4493 | + throw new StorageQueryException(e); |
| 4494 | + } |
| 4495 | + } |
| 4496 | + |
| 4497 | + @Override |
| 4498 | + public void saveRelayStateInfo(TenantIdentifier tenantIdentifier, SAMLRelayStateInfo relayStateInfo, long relayStateValidity) throws StorageQueryException { |
| 4499 | + try { |
| 4500 | + SAMLQueries.saveRelayStateInfo(this, tenantIdentifier, relayStateInfo.relayState, relayStateInfo.clientId, relayStateInfo.state, relayStateInfo.redirectURI, relayStateValidity); |
| 4501 | + } catch (SQLException e) { |
| 4502 | + throw new StorageQueryException(e); |
| 4503 | + } |
| 4504 | + } |
| 4505 | + |
| 4506 | + @Override |
| 4507 | + public SAMLRelayStateInfo getRelayStateInfo(TenantIdentifier tenantIdentifier, String relayState) throws StorageQueryException { |
| 4508 | + try { |
| 4509 | + return SAMLQueries.getRelayStateInfo(this, tenantIdentifier, relayState); |
| 4510 | + } catch (SQLException e) { |
| 4511 | + throw new StorageQueryException(e); |
| 4512 | + } |
| 4513 | + } |
| 4514 | + |
| 4515 | + @Override |
| 4516 | + public void saveSAMLClaims(TenantIdentifier tenantIdentifier, String clientId, String code, JsonObject claims, long claimsValidity) throws StorageQueryException { |
| 4517 | + try { |
| 4518 | + SAMLQueries.saveSAMLClaims(this, tenantIdentifier, clientId, code, claims.toString(), claimsValidity); |
| 4519 | + } catch (SQLException e) { |
| 4520 | + throw new StorageQueryException(e); |
| 4521 | + } |
| 4522 | + } |
| 4523 | + |
| 4524 | + @Override |
| 4525 | + public SAMLClaimsInfo getSAMLClaimsAndRemoveCode(TenantIdentifier tenantIdentifier, String code) throws StorageQueryException { |
| 4526 | + try { |
| 4527 | + return SAMLQueries.getSAMLClaimsAndRemoveCode(this, tenantIdentifier, code); |
| 4528 | + } catch (SQLException e) { |
| 4529 | + throw new StorageQueryException(e); |
| 4530 | + } |
| 4531 | + } |
| 4532 | + |
| 4533 | + @Override |
| 4534 | + public void removeExpiredSAMLCodesAndRelayStates() throws StorageQueryException { |
| 4535 | + try { |
| 4536 | + SAMLQueries.removeExpiredSAMLCodesAndRelayStates(this); |
| 4537 | + } catch (SQLException e) { |
| 4538 | + throw new StorageQueryException(e); |
| 4539 | + } |
| 4540 | + } |
| 4541 | + |
| 4542 | + @Override |
| 4543 | + public int countSAMLClients(TenantIdentifier tenantIdentifier) throws StorageQueryException { |
| 4544 | + try { |
| 4545 | + return SAMLQueries.countSAMLClients(this, tenantIdentifier); |
| 4546 | + } catch (SQLException e) { |
| 4547 | + throw new StorageQueryException(e); |
| 4548 | + } |
| 4549 | + } |
4395 | 4550 | } |
0 commit comments