From ff86bdc35f750ba8de84988937502a41315ef5c8 Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Tue, 15 Jul 2014 12:11:12 -0400 Subject: [PATCH] userprovider split --- .../audit/email/EmailAuditListener.java | 2 +- .../AbstractModelAuthenticationProvider.java | 15 +- .../ExternalModelAuthenticationProvider.java | 5 +- .../model/ModelAuthenticationProvider.java | 5 + .../ModelAuthenticationProviderFactory.java | 2 +- .../ExportImportProviderImpl.java | 4 +- .../keycloak/exportimport/ModelExporter.java | 11 +- .../keycloak/exportimport/ModelImporter.java | 11 +- .../exportimport/ExportImportTestBase.java | 6 +- .../freemarker/FreeMarkerAccountProvider.java | 2 +- .../freemarker/model/AccountSocialBean.java | 7 +- .../org/keycloak/models/KeycloakSession.java | 1 + .../org/keycloak/models/ModelProvider.java | 11 - .../java/org/keycloak/models/RealmModel.java | 28 -- .../org/keycloak/models/UserProvider.java | 5 +- .../java/org/keycloak/models/UserSpi.java | 27 ++ .../models/utils/KeycloakModelUtils.java | 7 +- .../services/org.keycloak.provider.Spi | 3 +- .../models/cache/ApplicationAdapter.java | 2 +- .../models/cache/CacheUserProvider.java | 15 + .../cache/CacheUserProviderFactory.java | 11 + .../models/cache/CacheUserProviderSpi.java | 27 ++ .../keycloak/models/cache/ClientAdapter.java | 5 +- .../cache/DefaultCacheModelProvider.java | 98 +----- .../cache/DefaultCacheUserProvider.java | 241 +++++++++++++ .../models/cache/NoCacheModelProvider.java | 45 --- .../models/cache/OAuthClientAdapter.java | 2 +- .../keycloak/models/cache/RealmAdapter.java | 86 +---- .../{KeycloakCache.java => RealmCache.java} | 14 +- .../keycloak/models/cache/RoleAdapter.java | 4 +- .../keycloak/models/cache/SimpleCache.java | 246 ------------- .../SimpleCacheModelProviderFactory.java | 2 +- .../cache/SimpleCacheUserProviderFactory.java | 33 ++ .../models/cache/SimpleRealmCache.java | 130 +++++++ .../models/cache/SimpleUserCache.java | 148 ++++++++ .../keycloak/models/cache/UserAdapter.java | 24 +- .../org/keycloak/models/cache/UserCache.java | 26 ++ .../cache/entities/CachedApplication.java | 10 +- .../models/cache/entities/CachedClient.java | 6 +- .../cache/entities/CachedOAuthClient.java | 5 +- .../models/cache/entities/CachedRealm.java | 5 +- .../models/cache/entities/CachedUser.java | 14 - ...loak.models.cache.CacheUserProviderFactory | 1 + .../services/org.keycloak.provider.Spi | 3 +- .../models/jpa/ApplicationAdapter.java | 7 +- .../keycloak/models/jpa/JpaModelProvider.java | 146 +------- .../keycloak/models/jpa/JpaUserProvider.java | 37 +- .../models/jpa/JpaUserProviderFactory.java | 38 +++ .../org/keycloak/models/jpa/RealmAdapter.java | 147 +------- .../org.keycloak.models.UserProviderFactory | 1 + .../keycloak/adapters/ApplicationAdapter.java | 1 + .../keycloak/adapters/MongoModelProvider.java | 177 +--------- .../keycloak/adapters/MongoUserProvider.java | 322 ++++++++++++++++++ .../adapters/MongoUserProviderFactory.java | 40 +++ .../mongo/keycloak/adapters/RealmAdapter.java | 134 +------- .../org.keycloak.models.UserProviderFactory | 1 + .../sessions/jpa/UserSessionAdapter.java | 2 +- .../sessions/mem/UserSessionAdapter.java | 2 +- .../mongo/MongoUserSessionProvider.java | 10 +- .../sessions/mongo/UserSessionAdapter.java | 7 +- .../org/keycloak/model/test/AdapterTest.java | 66 ++-- .../test/AuthProvidersExternalModelTest.java | 12 +- .../model/test/AuthProvidersLDAPTest.java | 9 +- .../model/test/AuthenticationManagerTest.java | 2 +- .../model/test/CompositeRolesModelTest.java | 2 +- .../org/keycloak/model/test/ImportTest.java | 29 +- .../model/test/MultipleRealmsTest.java | 18 +- .../keycloak/model/test/UserModelTest.java | 23 +- .../ups/security/UpsSecurityApplication.java | 4 +- .../services/DefaultKeycloakSession.java | 18 + .../services/managers/AccessCodeEntry.java | 7 +- .../services/managers/ApplianceBootstrap.java | 2 +- .../managers/AuthenticationManager.java | 6 +- .../services/managers/RealmManager.java | 8 +- .../managers/ResourceAdminManager.java | 9 +- .../services/managers/TokenManager.java | 14 +- .../services/managers/UserManager.java | 2 +- .../services/resources/AccountService.java | 6 +- .../resources/RequiredActionsService.java | 16 +- .../services/resources/SocialResource.java | 10 +- .../services/resources/TokenService.java | 14 +- .../resources/admin/ApplicationResource.java | 4 +- .../resources/admin/RealmAdminResource.java | 2 +- .../resources/admin/UsersResource.java | 52 +-- .../services/resources/flows/OAuthFlows.java | 2 +- .../keycloak/testutils/KeycloakServer.java | 2 +- .../resources/META-INF/keycloak-server.json | 4 + .../testsuite/account/AccountTest.java | 6 +- .../testsuite/account/ProfileTest.java | 4 +- .../RequiredActionEmailVerificationTest.java | 2 +- .../RequiredActionMultipleActionsTest.java | 2 +- .../RequiredActionResetPasswordTest.java | 2 +- .../RequiredActionUpdateProfileTest.java | 2 +- .../testsuite/adapter/AdapterTest.java | 2 +- .../adapter/RelativeUriAdapterTest.java | 2 +- .../testsuite/admin/AdminAPITest.java | 2 +- .../composites/CompositeRoleTest.java | 10 +- .../forms/AuthProvidersIntegrationTest.java | 9 +- .../keycloak/testsuite/forms/LoginTest.java | 2 +- .../testsuite/forms/LoginTotpTest.java | 2 +- .../testsuite/forms/ResetPasswordTest.java | 2 +- .../model/UserSessionProviderTest.java | 36 +- .../testsuite/rule/AbstractKeycloakRule.java | 6 +- .../performance/CreateUsersWorker.java | 4 +- .../performance/ReadUsersWorker.java | 6 +- .../org/keycloak/test/tools/PerfTools.java | 4 +- .../test/tools/jobs/CreateUsersJob.java | 4 +- .../test/tools/jobs/DeleteUsersJob.java | 6 +- .../test/tools/jobs/UpdateUsersJob.java | 6 +- .../keycloak/test/tools/jobs/UsersJob.java | 4 +- 110 files changed, 1467 insertions(+), 1428 deletions(-) mode change 100644 => 100755 audit/email/src/main/java/org/keycloak/audit/email/EmailAuditListener.java mode change 100644 => 100755 authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProvider.java mode change 100644 => 100755 authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProvider.java mode change 100644 => 100755 authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java mode change 100644 => 100755 export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java mode change 100644 => 100755 export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java create mode 100755 model/api/src/main/java/org/keycloak/models/UserSpi.java mode change 100644 => 100755 model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java mode change 100644 => 100755 model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java rename model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/{KeycloakCache.java => RealmCache.java} (74%) delete mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheUserProviderFactory.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleRealmCache.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleUserCache.java create mode 100755 model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java create mode 100755 model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory create mode 100755 model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java create mode 100755 model/jpa/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory create mode 100755 model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java create mode 100755 model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java create mode 100755 model/mongo/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory mode change 100644 => 100755 model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java mode change 100644 => 100755 model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java mode change 100644 => 100755 services/src/main/java/org/keycloak/services/managers/UserManager.java mode change 100644 => 100755 testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java mode change 100644 => 100755 testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java mode change 100644 => 100755 testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java mode change 100644 => 100755 testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java mode change 100644 => 100755 testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java mode change 100644 => 100755 testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java diff --git a/audit/email/src/main/java/org/keycloak/audit/email/EmailAuditListener.java b/audit/email/src/main/java/org/keycloak/audit/email/EmailAuditListener.java old mode 100644 new mode 100755 index a4aadfd259..dd70b05266 --- a/audit/email/src/main/java/org/keycloak/audit/email/EmailAuditListener.java +++ b/audit/email/src/main/java/org/keycloak/audit/email/EmailAuditListener.java @@ -37,7 +37,7 @@ public class EmailAuditListener implements AuditListener { if (includedEvents.contains(event.getEvent())) { if (event.getRealmId() != null && event.getUserId() != null) { RealmModel realm = model.getRealm(event.getRealmId()); - UserModel user = realm.getUserById(event.getUserId()); + UserModel user = session.users().getUserById(event.getUserId(), realm); if (user != null && user.getEmail() != null && user.isEmailVerified()) { try { emailProvider.setRealm(realm).setUser(user).sendEvent(event); diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java index d3433a98e7..1ac023f386 100755 --- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java +++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/AbstractModelAuthenticationProvider.java @@ -3,6 +3,7 @@ package org.keycloak.authentication.model; import java.util.Map; import org.jboss.logging.Logger; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; @@ -22,17 +23,23 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat private static final Logger logger = Logger.getLogger(AbstractModelAuthenticationProvider.class); + protected KeycloakSession keycloakSession; + + protected AbstractModelAuthenticationProvider(KeycloakSession keycloakSession) { + this.keycloakSession = keycloakSession; + } + @Override public AuthUser getUser(RealmModel currentRealm, Map config, String username) throws AuthenticationProviderException { RealmModel realm = getRealm(currentRealm, config); - UserModel user = KeycloakModelUtils.findUserByNameOrEmail(realm, username); + UserModel user = KeycloakModelUtils.findUserByNameOrEmail(keycloakSession, realm, username); return user == null ? null : createAuthenticatedUserInstance(user); } @Override public String registerUser(RealmModel currentRealm, Map config, UserModel user) throws AuthenticationProviderException { RealmModel realm = getRealm(currentRealm, config); - UserModel newUser = realm.addUser(user.getUsername()); + UserModel newUser = keycloakSession.users().addUser(realm, user.getUsername()); newUser.setFirstName(user.getFirstName()); newUser.setLastName(user.getLastName()); newUser.setEmail(user.getEmail()); @@ -43,7 +50,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat @Override public AuthProviderStatus validatePassword(RealmModel currentRealm, Map config, String username, String password) throws AuthenticationProviderException { RealmModel realm = getRealm(currentRealm, config); - UserModel user = KeycloakModelUtils.findUserByNameOrEmail(realm, username); + UserModel user = KeycloakModelUtils.findUserByNameOrEmail(keycloakSession, realm, username); boolean result = realm.validatePassword(user, password); return result ? AuthProviderStatus.SUCCESS : AuthProviderStatus.INVALID_CREDENTIALS; @@ -59,7 +66,7 @@ public abstract class AbstractModelAuthenticationProvider implements Authenticat throw new AuthenticationProviderException(error); } - UserModel user = realm.getUser(username); + UserModel user = keycloakSession.users().getUserByUsername(username, realm); if (user == null) { logger.warnf("User '%s' doesn't exists. Skip password update", username); return false; diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProvider.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProvider.java old mode 100644 new mode 100755 index 17c06ef957..1abf05f7c9 --- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProvider.java +++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProvider.java @@ -17,10 +17,9 @@ import java.util.Map; */ public class ExternalModelAuthenticationProvider extends AbstractModelAuthenticationProvider { - private ModelProvider model; public ExternalModelAuthenticationProvider(KeycloakSession session) { - this.model = session.model(); + super(session); } @Override @@ -40,7 +39,7 @@ public class ExternalModelAuthenticationProvider extends AbstractModelAuthentica throw new AuthenticationProviderException("Option '" + AuthProviderConstants.EXTERNAL_REALM_ID + "' not specified in configuration"); } - RealmModel realm = model.getRealm(realmId); + RealmModel realm = keycloakSession.model().getRealm(realmId); if (realm == null) { throw new AuthenticationProviderException("Realm with id '" + realmId + "' doesn't exists"); } diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProvider.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProvider.java old mode 100644 new mode 100755 index e46514df5b..210d56d8f9 --- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProvider.java +++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProvider.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.authentication.AuthProviderConstants; @@ -14,6 +15,10 @@ import org.keycloak.authentication.AuthProviderConstants; */ public class ModelAuthenticationProvider extends AbstractModelAuthenticationProvider { + public ModelAuthenticationProvider(KeycloakSession keycloakSession) { + super(keycloakSession); + } + @Override public String getName() { return AuthProviderConstants.PROVIDER_NAME_MODEL; diff --git a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java old mode 100644 new mode 100755 index ac8c393a44..bf699e39cf --- a/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java +++ b/authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java @@ -13,7 +13,7 @@ public class ModelAuthenticationProviderFactory implements AuthenticationProvide @Override public AuthenticationProvider create(KeycloakSession session) { - return new ModelAuthenticationProvider(); + return new ModelAuthenticationProvider(session); } @Override diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java old mode 100644 new mode 100755 index 03c9dda2ab..32d5d9f839 --- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java +++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ExportImportProviderImpl.java @@ -41,11 +41,11 @@ public class ExportImportProviderImpl implements ExportImportProvider { if (export) { ExportWriter exportWriter = getProvider().getExportWriter(); - new ModelExporter().exportModel(session.model(), exportWriter); + new ModelExporter().exportModel(session.users(), session.model(), exportWriter); logger.infof("Export finished successfully"); } else { ImportReader importReader = getProvider().getImportReader(); - new ModelImporter().importModel(session.model(), importReader); + new ModelImporter().importModel(session.users(), session.model(), importReader); logger.infof("Import finished successfully"); } diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java index 2b47bcec6c..463ee5e9d1 100755 --- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java +++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelExporter.java @@ -21,6 +21,7 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserModel; +import org.keycloak.models.UserProvider; import org.keycloak.models.UsernameLoginFailureModel; import org.keycloak.models.entities.ApplicationEntity; import org.keycloak.models.entities.AuthenticationLinkEntity; @@ -44,7 +45,7 @@ public class ModelExporter { private ExportWriter exportWriter; private ExportImportPropertiesManager propertiesManager; - public void exportModel(ModelProvider model, ExportWriter exportWriter) { + public void exportModel(UserProvider userProvider, ModelProvider model, ExportWriter exportWriter) { // Initialize needed objects this.exportWriter = exportWriter; this.propertiesManager = new ExportImportPropertiesManager(); @@ -54,7 +55,7 @@ public class ModelExporter { exportApplications(model, "applications.json"); exportOAuthClients(model, "oauthClients.json"); exportRoles(model, "roles.json"); - exportUsers(model, "users.json"); + exportUsers(userProvider, model, "users.json"); // exportUserFailures(model, "userFailures.json"); this.exportWriter.closeExportWriter(); @@ -199,12 +200,12 @@ public class ModelExporter { } } - protected void exportUsers(ModelProvider model, String fileName) { + protected void exportUsers(UserProvider userProvider, ModelProvider model, String fileName) { List realms = model.getRealms(); List result = new LinkedList(); for (RealmModel realm : realms) { - List userModels = realm.getUsers(); + List userModels = userProvider.getUsers(realm); for (UserModel userModel : userModels) { UserEntity userEntity = new UserEntity(); userEntity.setId(userModel.getId()); @@ -225,7 +226,7 @@ public class ModelExporter { } // social links - Set socialLinks = realm.getSocialLinks(userModel); + Set socialLinks = userProvider.getSocialLinks(userModel, realm); if (socialLinks != null && !socialLinks.isEmpty()) { List socialLinkEntities = new ArrayList(); for (SocialLinkModel socialLink : socialLinks) { diff --git a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java index 35371b44f0..ce52fa4f1e 100755 --- a/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java +++ b/export-import/export-import-impl/src/main/java/org/keycloak/exportimport/ModelImporter.java @@ -24,6 +24,7 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserModel; +import org.keycloak.models.UserProvider; import org.keycloak.models.UsernameLoginFailureModel; import org.keycloak.models.entities.ApplicationEntity; import org.keycloak.models.entities.AuthenticationLinkEntity; @@ -48,7 +49,7 @@ public class ModelImporter { private ImportReader importReader; private ExportImportPropertiesManager propertiesManager; - public void importModel(ModelProvider model, ImportReader importReader) { + public void importModel(UserProvider userModel, ModelProvider model, ImportReader importReader) { // Initialize needed objects this.importReader = importReader; this.propertiesManager = new ExportImportPropertiesManager(); @@ -62,7 +63,7 @@ public class ModelImporter { importApplicationsStep2(model, "applications.json"); importOAuthClients(model, "oauthClients.json"); - importUsers(model, "users.json"); + importUsers(userModel, model, "users.json"); // importUserFailures(model, "userFailures.json"); this.importReader.closeImportReader(); @@ -237,11 +238,11 @@ public class ModelImporter { return null; } - public void importUsers(ModelProvider model, String fileName) { + public void importUsers(UserProvider userModel, ModelProvider model, String fileName) { List users = this.importReader.readEntities(fileName, UserEntity.class); for (UserEntity userEntity : users) { RealmModel realm = model.getRealm(userEntity.getRealmId()); - UserModel user = realm.addUser(userEntity.getId(), userEntity.getUsername(), false); + UserModel user = userModel.addUser(realm, userEntity.getId(), userEntity.getUsername(), false); // We need to remove defaultRoles here as realm.addUser is automatically adding them. We may add them later during roles mapping processing for (RoleModel role : user.getRoleMappings()) { @@ -266,7 +267,7 @@ public class ModelImporter { SocialLinkModel socialLink = new SocialLinkModel(); this.propertiesManager.setBasicPropertiesToModel(socialLink, socialLinkEntity); - realm.addSocialLink(user, socialLink); + userModel.addSocialLink(realm, user, socialLink); } } diff --git a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java old mode 100644 new mode 100755 index 1f0c55e357..bdfdae1b80 --- a/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java +++ b/export-import/export-import-impl/src/test/java/org/keycloak/exportimport/ExportImportTestBase.java @@ -56,7 +56,7 @@ public abstract class ExportImportTestBase { beginTransaction(); realm = session.model().getRealm("demo"); - String wburkeId = realm.getUser("wburke").getId(); + String wburkeId = session.users().getUserByUsername("wburke", realm).getId(); String appId = realm.getApplicationByName("Application").getId(); // Commit transaction and close JPA now @@ -75,9 +75,9 @@ public abstract class ExportImportTestBase { RealmModel importedRealm = session.model().getRealm("demo"); System.out.println("Exported realm: " + realm + ", Imported realm: " + importedRealm); - Assert.assertEquals(wburkeId, importedRealm.getUser("wburke").getId()); + Assert.assertEquals(wburkeId, session.users().getUserByUsername("wburke", importedRealm).getId()); Assert.assertEquals(appId, importedRealm.getApplicationByName("Application").getId()); - ImportTest.assertDataImportedInRealm(importedRealm); + ImportTest.assertDataImportedInRealm(session, importedRealm); // Commit and close Mongo commitTransaction(); diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java index e7d9636f0a..ee84cc6161 100755 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java @@ -124,7 +124,7 @@ public class FreeMarkerAccountProvider implements AccountProvider { attributes.put("totp", new TotpBean(user, baseUri)); break; case SOCIAL: - attributes.put("social", new AccountSocialBean(realm, user, uriInfo.getBaseUri())); + attributes.put("social", new AccountSocialBean(session, realm, user, uriInfo.getBaseUri())); break; case LOG: attributes.put("log", new LogBean(events)); diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountSocialBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountSocialBean.java index 074174f062..ad2786cf78 100755 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountSocialBean.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccountSocialBean.java @@ -8,6 +8,7 @@ import java.util.Set; import javax.ws.rs.core.UriBuilder; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserModel; @@ -22,13 +23,15 @@ public class AccountSocialBean { private final List socialLinks; private final boolean removeLinkPossible; + private final KeycloakSession session; - public AccountSocialBean(RealmModel realm, UserModel user, URI baseUri) { + public AccountSocialBean(KeycloakSession session, RealmModel realm, UserModel user, URI baseUri) { + this.session = session; URI accountSocialUpdateUri = Urls.accountSocialUpdate(baseUri, realm.getName()); this.socialLinks = new LinkedList(); Map socialConfig = realm.getSocialConfig(); - Set userSocialLinks = realm.getSocialLinks(user); + Set userSocialLinks = session.users().getSocialLinks(user, realm); int availableLinks = 0; if (socialConfig != null && !socialConfig.isEmpty()) { diff --git a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java index 4a4f429378..628c1a6d86 100755 --- a/model/api/src/main/java/org/keycloak/models/KeycloakSession.java +++ b/model/api/src/main/java/org/keycloak/models/KeycloakSession.java @@ -42,4 +42,5 @@ public interface KeycloakSession { void close(); + UserProvider users(); } diff --git a/model/api/src/main/java/org/keycloak/models/ModelProvider.java b/model/api/src/main/java/org/keycloak/models/ModelProvider.java index 863530e0d0..2c1ad56174 100755 --- a/model/api/src/main/java/org/keycloak/models/ModelProvider.java +++ b/model/api/src/main/java/org/keycloak/models/ModelProvider.java @@ -18,17 +18,6 @@ public interface ModelProvider extends Provider { RealmModel getRealm(String id); RealmModel getRealmByName(String name); - UserModel getUserById(String id, RealmModel realm); - UserModel getUserByUsername(String username, RealmModel realm); - UserModel getUserByEmail(String email, RealmModel realm); - UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm); - List getUsers(RealmModel realm); - List searchForUser(String search, RealmModel realm); - List searchForUserByAttributes(Map attributes, RealmModel realm); - - Set getSocialLinks(UserModel user, RealmModel realm); - SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm); - RoleModel getRoleById(String id, RealmModel realm); ApplicationModel getApplicationById(String id, RealmModel realm); OAuthClientModel getOAuthClientById(String id, RealmModel realm); diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java index 2092f72bd4..d515c988b6 100755 --- a/model/api/src/main/java/org/keycloak/models/RealmModel.java +++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java @@ -110,18 +110,6 @@ public interface RealmModel extends RoleContainerModel { boolean validateTOTP(UserModel user, String password, String token); - UserModel getUser(String name); - - UserModel getUserByEmail(String email); - - UserModel getUserById(String name); - - UserModel addUser(String id, String username, boolean addDefaultRoles); - - UserModel addUser(String username); - - boolean removeUser(String name); - RoleModel getRoleById(String id); List getDefaultRoles(); @@ -147,16 +135,6 @@ public interface RealmModel extends RoleContainerModel { void updateRequiredCredentials(Set creds); - UserModel getUserBySocialLink(SocialLinkModel socialLink); - - Set getSocialLinks(UserModel user); - - SocialLinkModel getSocialLink(UserModel user, String socialProvider); - - void addSocialLink(UserModel user, SocialLinkModel socialLink); - - boolean removeSocialLink(UserModel user, String socialProvider); - boolean isSocial(); void setSocial(boolean social); @@ -165,12 +143,6 @@ public interface RealmModel extends RoleContainerModel { void setUpdateProfileOnInitialSocialLogin(boolean updateProfileOnInitialSocialLogin); - List getUsers(); - - List searchForUser(String search); - - List searchForUserByAttributes(Map attributes); - OAuthClientModel addOAuthClient(String name); OAuthClientModel addOAuthClient(String id, String name); diff --git a/model/api/src/main/java/org/keycloak/models/UserProvider.java b/model/api/src/main/java/org/keycloak/models/UserProvider.java index f4e2bbd75b..b5a9a26f7f 100755 --- a/model/api/src/main/java/org/keycloak/models/UserProvider.java +++ b/model/api/src/main/java/org/keycloak/models/UserProvider.java @@ -13,12 +13,13 @@ import java.util.Set; public interface UserProvider extends Provider { // Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession - KeycloakTransaction getTransaction(); - UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles); UserModel addUser(RealmModel realm, String username); boolean removeUser(RealmModel realm, String name); + public void addSocialLink(RealmModel realm, UserModel user, SocialLinkModel socialLink); + public boolean removeSocialLink(RealmModel realm, UserModel user, String socialProvider); + UserModel getUserById(String id, RealmModel realm); UserModel getUserByUsername(String username, RealmModel realm); UserModel getUserByEmail(String email, RealmModel realm); diff --git a/model/api/src/main/java/org/keycloak/models/UserSpi.java b/model/api/src/main/java/org/keycloak/models/UserSpi.java new file mode 100755 index 0000000000..e68299c650 --- /dev/null +++ b/model/api/src/main/java/org/keycloak/models/UserSpi.java @@ -0,0 +1,27 @@ +package org.keycloak.models; + +import org.keycloak.provider.Provider; +import org.keycloak.provider.ProviderFactory; +import org.keycloak.provider.Spi; + +/** + * @author Stian Thorgersen + */ +public class UserSpi implements Spi { + + @Override + public String getName() { + return "user"; + } + + @Override + public Class getProviderClass() { + return UserProvider.class; + } + + @Override + public Class getProviderFactoryClass() { + return UserProviderFactory.class; + } + +} diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java old mode 100644 new mode 100755 index 939eebaddc..5ad0a68697 --- a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java +++ b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java @@ -10,6 +10,7 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; import org.bouncycastle.openssl.PEMWriter; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; @@ -92,10 +93,10 @@ public final class KeycloakModelUtils { * @param username username or email of user * @return found user */ - public static UserModel findUserByNameOrEmail(RealmModel realm, String username) { - UserModel user = realm.getUser(username); + public static UserModel findUserByNameOrEmail(KeycloakSession session, RealmModel realm, String username) { + UserModel user = session.users().getUserByUsername(username, realm); if (user == null && username.contains("@")) { - user = realm.getUserByEmail(username); + user = session.users().getUserByEmail(username, realm); } return user; } diff --git a/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi old mode 100644 new mode 100755 index 6ad707ca9a..2e55a8a770 --- a/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -1,2 +1,3 @@ org.keycloak.models.ModelSpi -org.keycloak.models.UserSessionSpi \ No newline at end of file +org.keycloak.models.UserSessionSpi +org.keycloak.models.UserSpi \ No newline at end of file diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java index 31e938e9ed..3e45b11f94 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ApplicationAdapter.java @@ -19,7 +19,7 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode protected ApplicationModel updated; protected CachedApplication cached; - public ApplicationAdapter(RealmModel cachedRealm, CachedApplication cached, CacheModelProvider cacheSession, KeycloakCache cache) { + public ApplicationAdapter(RealmModel cachedRealm, CachedApplication cached, CacheModelProvider cacheSession, RealmCache cache) { super(cachedRealm, cached, cache, cacheSession); this.cached = cached; } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java new file mode 100755 index 0000000000..b8bc5263da --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java @@ -0,0 +1,15 @@ +package org.keycloak.models.cache; + +import org.keycloak.models.ModelProvider; +import org.keycloak.models.RealmModel; +import org.keycloak.models.UserProvider; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public interface CacheUserProvider extends UserProvider { + UserProvider getDelegate(); + + void registerUserInvalidation(RealmModel realm, String id); +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java new file mode 100755 index 0000000000..4341ad581b --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java @@ -0,0 +1,11 @@ +package org.keycloak.models.cache; + +import org.keycloak.provider.ProviderFactory; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public interface CacheUserProviderFactory extends ProviderFactory { + +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java new file mode 100755 index 0000000000..6c0fae5950 --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java @@ -0,0 +1,27 @@ +package org.keycloak.models.cache; + +import org.keycloak.provider.Provider; +import org.keycloak.provider.ProviderFactory; +import org.keycloak.provider.Spi; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class CacheUserProviderSpi implements Spi { + + @Override + public String getName() { + return "userCache"; + } + + @Override + public Class getProviderClass() { + return CacheUserProvider.class; + } + + @Override + public Class getProviderFactoryClass() { + return CacheUserProviderFactory.class; + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java index 34a785c7c2..c07e3cb48e 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java @@ -4,7 +4,6 @@ import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; -import org.keycloak.models.UserSessionModel; import org.keycloak.models.cache.entities.CachedClient; import java.util.HashSet; @@ -19,9 +18,9 @@ public abstract class ClientAdapter implements ClientModel { protected CacheModelProvider cacheSession; protected ClientModel updatedClient; protected RealmModel cachedRealm; - protected KeycloakCache cache; + protected RealmCache cache; - public ClientAdapter(RealmModel cachedRealm, CachedClient cached, KeycloakCache cache, CacheModelProvider cacheSession) { + public ClientAdapter(RealmModel cachedRealm, CachedClient cached, RealmCache cache, CacheModelProvider cacheSession) { this.cachedRealm = cachedRealm; this.cache = cache; this.cacheSession = cacheSession; diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheModelProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheModelProvider.java index d1167440bc..0d25e3393d 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheModelProvider.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheModelProvider.java @@ -1,7 +1,6 @@ package org.keycloak.models.cache; import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakTransaction; import org.keycloak.models.ModelProvider; @@ -10,8 +9,6 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserModel; -import org.keycloak.models.UserSessionModel; -import org.keycloak.models.UsernameLoginFailureModel; import org.keycloak.models.cache.entities.CachedApplication; import org.keycloak.models.cache.entities.CachedApplicationRole; import org.keycloak.models.cache.entities.CachedOAuthClient; @@ -31,7 +28,7 @@ import java.util.Set; * @version $Revision: 1 $ */ public class DefaultCacheModelProvider implements CacheModelProvider { - protected KeycloakCache cache; + protected RealmCache cache; protected KeycloakSession session; protected ModelProvider delegate; protected boolean transactionActive; @@ -50,7 +47,7 @@ public class DefaultCacheModelProvider implements CacheModelProvider { protected boolean clearAll; - public DefaultCacheModelProvider(KeycloakCache cache, KeycloakSession session) { + public DefaultCacheModelProvider(RealmCache cache, KeycloakSession session) { this.cache = cache; this.session = session; @@ -103,10 +100,6 @@ public class DefaultCacheModelProvider implements CacheModelProvider { for (String id : clientInvalidations) { cache.invalidateCachedOAuthClientById(id); } - for (String id : userInvalidations) { - cache.invalidateCachedUserById(id); - } - } private KeycloakTransaction getTransaction() { @@ -200,63 +193,6 @@ public class DefaultCacheModelProvider implements CacheModelProvider { return adapter; } - @Override - public UserModel getUserById(String id, RealmModel realm) { - CachedUser cached = cache.getCachedUser(id); - if (cached == null) { - UserModel model = getDelegate().getUserById(id, realm); - if (model == null) return null; - if (userInvalidations.contains(id)) return model; - cached = new CachedUser(realm, model); - cache.addCachedUser(cached); - } else if (userInvalidations.contains(id)) { - return getDelegate().getUserById(id, realm); - } else if (managedUsers.containsKey(id)) { - return managedUsers.get(id); - } - UserAdapter adapter = new UserAdapter(cached, cache, this, realm); - managedUsers.put(id, adapter); - return adapter; - } - - @Override - public UserModel getUserByUsername(String username, RealmModel realm) { - CachedUser cached = cache.getCachedUserByUsername(username, realm); - if (cached == null) { - UserModel model = getDelegate().getUserByUsername(username, realm); - if (model == null) return null; - if (userInvalidations.contains(model.getId())) return model; - cached = new CachedUser(realm, model); - cache.addCachedUser(cached); - } else if (userInvalidations.contains(cached.getId())) { - return getDelegate().getUserById(cached.getId(), realm); - } else if (managedUsers.containsKey(cached.getId())) { - return managedUsers.get(cached.getId()); - } - UserAdapter adapter = new UserAdapter(cached, cache, this, realm); - managedUsers.put(cached.getId(), adapter); - return adapter; - } - - @Override - public UserModel getUserByEmail(String email, RealmModel realm) { - CachedUser cached = cache.getCachedUserByEmail(email, realm); - if (cached == null) { - UserModel model = getDelegate().getUserByEmail(email, realm); - if (model == null) return null; - if (userInvalidations.contains(model.getId())) return model; - cached = new CachedUser(realm, model); - cache.addCachedUser(cached); - } else if (userInvalidations.contains(cached.getId())) { - return getDelegate().getUserByEmail(email, realm); - } else if (managedUsers.containsKey(cached.getId())) { - return managedUsers.get(cached.getId()); - } - UserAdapter adapter = new UserAdapter(cached, cache, this, realm); - managedUsers.put(cached.getId(), adapter); - return adapter; - } - @Override public List getRealms() { // we don't cache this for now @@ -277,36 +213,6 @@ public class DefaultCacheModelProvider implements CacheModelProvider { if (delegate != null) delegate.close(); } - @Override - public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) { - return getDelegate().getUserBySocialLink(socialLink, realm); - } - - @Override - public List getUsers(RealmModel realm) { - return getDelegate().getUsers(realm); - } - - @Override - public List searchForUser(String search, RealmModel realm) { - return getDelegate().searchForUser(search, realm); - } - - @Override - public List searchForUserByAttributes(Map attributes, RealmModel realm) { - return getDelegate().searchForUserByAttributes(attributes, realm); - } - - @Override - public Set getSocialLinks(UserModel user, RealmModel realm) { - return getDelegate().getSocialLinks(user, realm); - } - - @Override - public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) { - return getDelegate().getSocialLink(user, socialProvider, realm); - } - @Override public RoleModel getRoleById(String id, RealmModel realm) { CachedRole cached = cache.getRole(id); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java new file mode 100755 index 0000000000..415ad8d471 --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java @@ -0,0 +1,241 @@ +package org.keycloak.models.cache; + +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakTransaction; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserModel; +import org.keycloak.models.UserProvider; +import org.keycloak.models.cache.entities.CachedUser; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class DefaultCacheUserProvider implements CacheUserProvider { + protected UserCache cache; + protected KeycloakSession session; + protected UserProvider delegate; + protected boolean transactionActive; + protected boolean setRollbackOnly; + + protected Map userInvalidations = new HashMap(); + protected Set realmInvalidations = new HashSet(); + protected Map managedUsers = new HashMap(); + + protected boolean clearAll; + + public DefaultCacheUserProvider(UserCache cache, KeycloakSession session) { + this.cache = cache; + this.session = session; + + session.getTransaction().enlistAfterCompletion(getTransaction()); + } + + @Override + public UserProvider getDelegate() { + if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction"); + if (delegate != null) return delegate; + delegate = session.getProvider(UserProvider.class); + return delegate; + } + + @Override + public void registerUserInvalidation(RealmModel realm, String id) { + userInvalidations.put(id, realm.getId()); + } + + protected void runInvalidations() { + for (Map.Entry invalidation : userInvalidations.entrySet()) { + cache.invalidateCachedUserById(invalidation.getValue(), invalidation.getKey()); + } + for (String realmId : realmInvalidations) { + cache.invalidateRealmUsers(realmId); + } + } + + private KeycloakTransaction getTransaction() { + return new KeycloakTransaction() { + @Override + public void begin() { + transactionActive = true; + } + + @Override + public void commit() { + if (delegate == null) return; + if (clearAll) { + cache.clear(); + } + runInvalidations(); + } + + @Override + public void rollback() { + setRollbackOnly = true; + runInvalidations(); + } + + @Override + public void setRollbackOnly() { + setRollbackOnly = true; + } + + @Override + public boolean getRollbackOnly() { + return setRollbackOnly; + } + + @Override + public boolean isActive() { + return transactionActive; + } + }; + } + + @Override + public UserModel getUserById(String id, RealmModel realm) { + if (realmInvalidations.contains(realm.getId())) { + return getDelegate().getUserById(id, realm); + } + if (userInvalidations.containsKey(id)) { + return getDelegate().getUserById(id, realm); + } + + CachedUser cached = cache.getCachedUser(realm.getId(), id); + if (cached == null) { + UserModel model = getDelegate().getUserById(id, realm); + if (model == null) return null; + if (userInvalidations.containsKey(id)) return model; + cached = new CachedUser(realm, model); + cache.addCachedUser(realm.getId(), cached); + } else if (managedUsers.containsKey(id)) { + return managedUsers.get(id); + } + UserAdapter adapter = new UserAdapter(cached, this, session, realm); + managedUsers.put(id, adapter); + return adapter; + } + + @Override + public UserModel getUserByUsername(String username, RealmModel realm) { + if (realmInvalidations.contains(realm.getId())) { + return getDelegate().getUserByUsername(username, realm); + } + CachedUser cached = cache.getCachedUserByUsername(realm.getId(), username); + if (cached == null) { + UserModel model = getDelegate().getUserByUsername(username, realm); + if (model == null) return null; + if (userInvalidations.containsKey(model.getId())) return model; + cached = new CachedUser(realm, model); + cache.addCachedUser(realm.getId(), cached); + } else if (userInvalidations.containsKey(cached.getId())) { + return getDelegate().getUserById(cached.getId(), realm); + } else if (managedUsers.containsKey(cached.getId())) { + return managedUsers.get(cached.getId()); + } + UserAdapter adapter = new UserAdapter(cached, this, session, realm); + managedUsers.put(cached.getId(), adapter); + return adapter; + } + + @Override + public UserModel getUserByEmail(String email, RealmModel realm) { + if (realmInvalidations.contains(realm.getId())) { + return getDelegate().getUserByEmail(email, realm); + } + CachedUser cached = cache.getCachedUserByEmail(realm.getId(), email); + if (cached == null) { + UserModel model = getDelegate().getUserByEmail(email, realm); + if (model == null) return null; + if (userInvalidations.containsKey(model.getId())) return model; + cached = new CachedUser(realm, model); + cache.addCachedUser(realm.getId(), cached); + } else if (userInvalidations.containsKey(cached.getId())) { + return getDelegate().getUserByEmail(email, realm); + } else if (managedUsers.containsKey(cached.getId())) { + return managedUsers.get(cached.getId()); + } + UserAdapter adapter = new UserAdapter(cached, this, session, realm); + managedUsers.put(cached.getId(), adapter); + return adapter; + } + + @Override + public void close() { + if (delegate != null) delegate.close(); + } + + @Override + public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) { + return getDelegate().getUserBySocialLink(socialLink, realm); + } + + @Override + public List getUsers(RealmModel realm) { + return getDelegate().getUsers(realm); + } + + @Override + public List searchForUser(String search, RealmModel realm) { + return getDelegate().searchForUser(search, realm); + } + + @Override + public List searchForUserByAttributes(Map attributes, RealmModel realm) { + return getDelegate().searchForUserByAttributes(attributes, realm); + } + + @Override + public Set getSocialLinks(UserModel user, RealmModel realm) { + return getDelegate().getSocialLinks(user, realm); + } + + @Override + public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) { + return getDelegate().getSocialLink(user, socialProvider, realm); + } + + @Override + public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles) { + return getDelegate().addUser(realm, id, username, addDefaultRoles); + } + + @Override + public UserModel addUser(RealmModel realm, String username) { + return getDelegate().addUser(realm, username); + } + + @Override + public boolean removeUser(RealmModel realm, String name) { + return getDelegate().removeUser(realm, name); + } + + @Override + public void addSocialLink(RealmModel realm, UserModel user, SocialLinkModel socialLink) { + getDelegate().addSocialLink(realm, user, socialLink); + } + + @Override + public boolean removeSocialLink(RealmModel realm, UserModel user, String socialProvider) { + return getDelegate().removeSocialLink(realm, user, socialProvider); + } + + @Override + public void preRemove(RealmModel realm) { + realmInvalidations.add(realm.getId()); + getDelegate().preRemove(realm); + } + + @Override + public void preRemove(RoleModel role) { + getDelegate().preRemove(role); + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheModelProvider.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheModelProvider.java index 4ba1f53a9f..a705c2d034 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheModelProvider.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheModelProvider.java @@ -83,21 +83,6 @@ public class NoCacheModelProvider implements CacheModelProvider { return getDelegate().getRealmByName(name); } - @Override - public UserModel getUserById(String id, RealmModel realm) { - return getDelegate().getUserById(id, realm); - } - - @Override - public UserModel getUserByUsername(String username, RealmModel realm) { - return getDelegate().getUserByUsername(username, realm); - } - - @Override - public UserModel getUserByEmail(String email, RealmModel realm) { - return getDelegate().getUserByEmail(email, realm); - } - @Override public List getRealms() { // we don't cache this for now @@ -114,36 +99,6 @@ public class NoCacheModelProvider implements CacheModelProvider { if (delegate != null) delegate.close(); } - @Override - public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) { - return getDelegate().getUserBySocialLink(socialLink, realm); - } - - @Override - public List getUsers(RealmModel realm) { - return getDelegate().getUsers(realm); - } - - @Override - public List searchForUser(String search, RealmModel realm) { - return getDelegate().searchForUser(search, realm); - } - - @Override - public List searchForUserByAttributes(Map attributes, RealmModel realm) { - return getDelegate().searchForUserByAttributes(attributes, realm); - } - - @Override - public Set getSocialLinks(UserModel user, RealmModel realm) { - return getDelegate().getSocialLinks(user, realm); - } - - @Override - public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) { - return getDelegate().getSocialLink(user, socialProvider, realm); - } - @Override public RoleModel getRoleById(String id, RealmModel realm) { return getDelegate().getRoleById(id, realm); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java index 2831ea0bee..37e55439f9 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/OAuthClientAdapter.java @@ -12,7 +12,7 @@ public class OAuthClientAdapter extends ClientAdapter implements OAuthClientMode protected OAuthClientModel updated; protected CachedOAuthClient cached; - public OAuthClientAdapter(RealmModel cachedRealm, CachedOAuthClient cached, CacheModelProvider cacheSession, KeycloakCache cache) { + public OAuthClientAdapter(RealmModel cachedRealm, CachedOAuthClient cached, CacheModelProvider cacheSession, RealmCache cache) { super(cachedRealm, cached, cache, cacheSession); this.cached = cached; } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java index 922065daf9..b1813c7245 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java @@ -13,11 +13,8 @@ import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserModel; -import org.keycloak.models.UserSessionModel; -import org.keycloak.models.UsernameLoginFailureModel; import org.keycloak.models.cache.entities.CachedRealm; import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.models.utils.Pbkdf2PasswordEncoder; import org.keycloak.models.utils.TimeBasedOTP; import java.security.PrivateKey; @@ -37,7 +34,7 @@ public class RealmAdapter implements RealmModel { protected CachedRealm cached; protected CacheModelProvider cacheSession; protected RealmModel updated; - protected KeycloakCache cache; + protected RealmCache cache; protected volatile transient PublicKey publicKey; protected volatile transient PrivateKey privateKey; @@ -395,39 +392,6 @@ public class RealmAdapter implements RealmModel { return false; } - @Override - public UserModel getUser(String name) { - return cacheSession.getUserByUsername(name, this); - } - - @Override - public UserModel getUserByEmail(String email) { - return cacheSession.getUserByEmail(email, this); - } - - @Override - public UserModel getUserById(String id) { - return cacheSession.getUserById(id, this); - } - - @Override - public UserModel addUser(String id, String username, boolean addDefaultRoles) { - getDelegateForUpdate(); - return updated.addUser(id, username, addDefaultRoles); - } - - @Override - public UserModel addUser(String username) { - getDelegateForUpdate(); - return updated.addUser(username); - } - - @Override - public boolean removeUser(String name) { - getDelegateForUpdate(); - return updated.removeUser(name); - } - @Override public RoleModel getRoleById(String id) { if (updated != null) return updated.getRoleById(id); @@ -538,36 +502,6 @@ public class RealmAdapter implements RealmModel { updated.updateRequiredCredentials(creds); } - @Override - public UserModel getUserBySocialLink(SocialLinkModel socialLink) { - if (updated != null) return updated.getUserBySocialLink(socialLink); - return cacheSession.getUserBySocialLink(socialLink, this); - } - - @Override - public Set getSocialLinks(UserModel user) { - if (updated != null) return updated.getSocialLinks(user); - return cacheSession.getSocialLinks(user, this); - } - - @Override - public SocialLinkModel getSocialLink(UserModel user, String socialProvider) { - if (updated != null) return updated.getSocialLink(user, socialProvider); - return cacheSession.getSocialLink(user, socialProvider, this); - } - - @Override - public void addSocialLink(UserModel user, SocialLinkModel socialLink) { - getDelegateForUpdate(); - updated.addSocialLink(user, socialLink); - } - - @Override - public boolean removeSocialLink(UserModel user, String socialProvider) { - getDelegateForUpdate(); - return updated.removeSocialLink(user, socialProvider); - } - @Override public boolean isSocial() { if (updated != null) return updated.isSocial(); @@ -592,24 +526,6 @@ public class RealmAdapter implements RealmModel { updated.setUpdateProfileOnInitialSocialLogin(updateProfileOnInitialSocialLogin); } - @Override - public List getUsers() { - if (updated != null) return updated.getUsers(); - return cacheSession.getUsers(this); - } - - @Override - public List searchForUser(String search) { - if (updated != null) return updated.searchForUser(search); - return cacheSession.searchForUser(search, this); - } - - @Override - public List searchForUserByAttributes(Map attributes) { - if (updated != null) return updated.searchForUserByAttributes(attributes); - return cacheSession.searchForUserByAttributes(attributes, this); - } - @Override public OAuthClientModel addOAuthClient(String name) { getDelegateForUpdate(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java similarity index 74% rename from model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java rename to model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java index dca8fa17af..3dd15b1f31 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/KeycloakCache.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmCache.java @@ -11,7 +11,7 @@ import org.keycloak.models.cache.entities.CachedUser; * @author Bill Burke * @version $Revision: 1 $ */ -public interface KeycloakCache { +public interface RealmCache { void clear(); CachedRealm getCachedRealm(String id); @@ -51,16 +51,4 @@ public interface KeycloakCache { void invalidateRoleById(String id); - CachedUser getCachedUser(String id); - - void invalidateCachedUser(CachedUser user); - - void addCachedUser(CachedUser user); - - CachedUser getCachedUserByUsername(String name, RealmModel realm); - CachedUser getCachedUserByEmail(String name, RealmModel realm); - - void invalidedCachedUserById(String id); - - void invalidateCachedUserById(String id); } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java index bbf27660cf..ea8ce6aaf7 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RoleAdapter.java @@ -19,11 +19,11 @@ public class RoleAdapter implements RoleModel { protected RoleModel updated; protected CachedRole cached; - protected KeycloakCache cache; + protected RealmCache cache; protected CacheModelProvider cacheSession; protected RealmModel realm; - public RoleAdapter(CachedRole cached, KeycloakCache cache, CacheModelProvider session, RealmModel realm) { + public RoleAdapter(CachedRole cached, RealmCache cache, CacheModelProvider session, RealmModel realm) { this.cached = cached; this.cache = cache; this.cacheSession = session; diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java deleted file mode 100755 index f40723b48a..0000000000 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCache.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.keycloak.models.cache; - -import org.keycloak.models.RealmModel; -import org.keycloak.models.cache.entities.CachedApplication; -import org.keycloak.models.cache.entities.CachedOAuthClient; -import org.keycloak.models.cache.entities.CachedRealm; -import org.keycloak.models.cache.entities.CachedRole; -import org.keycloak.models.cache.entities.CachedUser; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class SimpleCache implements KeycloakCache { - - protected ConcurrentHashMap realmCache = new ConcurrentHashMap(); - protected ConcurrentHashMap realmCacheByName = new ConcurrentHashMap(); - protected ConcurrentHashMap applicationCache = new ConcurrentHashMap(); - protected ConcurrentHashMap clientCache = new ConcurrentHashMap(); - protected ConcurrentHashMap roleCache = new ConcurrentHashMap(); - - protected int maxUserCacheSize = 10000; - protected boolean userCacheEnabled = true; - - protected Map usersById = Collections.synchronizedMap(new LRUCache()); - protected Map usersByUsername = new ConcurrentHashMap(); - protected Map usersByEmail = new ConcurrentHashMap(); - - protected class LRUCache extends LinkedHashMap { - public LRUCache() { - super(1000, 1.1F, true); - } - - @Override - public CachedUser put(String key, CachedUser value) { - usersByUsername.put(value.getUsernameKey(), value); - if (value.getEmail() != null) { - usersByEmail.put(value.getEmailKey(), value); - } - return super.put(key, value); - } - - @Override - public CachedUser remove(Object key) { - CachedUser user = super.remove(key); - if (user == null) return null; - removeUser(user); - return user; - } - - @Override - public void clear() { - super.clear(); - usersByUsername.clear(); - usersByEmail.clear(); - } - - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - boolean evict = size() > maxUserCacheSize; - if (evict) { - removeUser(eldest.getValue()); - } - return evict; - } - - private void removeUser(CachedUser value) { - usersByUsername.remove(value.getUsernameKey()); - if (value.getEmail() != null) usersByEmail.remove(value.getEmailKey()); - } - } - - public int getMaxUserCacheSize() { - return maxUserCacheSize; - } - - public void setMaxUserCacheSize(int maxUserCacheSize) { - this.maxUserCacheSize = maxUserCacheSize; - } - - public boolean isUserCacheEnabled() { - return userCacheEnabled; - } - - public void setUserCacheEnabled(boolean userCacheEnabled) { - this.userCacheEnabled = userCacheEnabled; - } - - @Override - public CachedUser getCachedUser(String id) { - if (!userCacheEnabled) return null; - return usersById.get(id); - } - - @Override - public void invalidateCachedUser(CachedUser user) { - if (!userCacheEnabled) return; - usersById.remove(user.getId()); - } - - @Override - public void invalidateCachedUserById(String id) { - if (!userCacheEnabled) return; - usersById.remove(id); - } - - @Override - public void addCachedUser(CachedUser user) { - if (!userCacheEnabled) return; - usersById.put(user.getId(), user); - } - - @Override - public CachedUser getCachedUserByUsername(String name, RealmModel realm) { - if (!userCacheEnabled) return null; - CachedUser user = usersByUsername.get(realm.getId() + "." +name); - if (user == null) return null; - usersById.get(user.getId()); // refresh cache entry age - return user; - } - - @Override - public CachedUser getCachedUserByEmail(String name, RealmModel realm) { - if (!userCacheEnabled) return null; - CachedUser user = usersByEmail.get(realm.getId() + "." +name); - if (user == null) return null; - usersById.get(user.getId()); // refresh cache entry age - return user; - } - - @Override - public void invalidedCachedUserById(String id) { - if (!userCacheEnabled) return; - usersById.remove(id); - } - - @Override - public void clear() { - realmCache.clear(); - realmCacheByName.clear(); - applicationCache.clear(); - clientCache.clear(); - roleCache.clear(); - usersById.clear(); - } - - @Override - public CachedRealm getCachedRealm(String id) { - return realmCache.get(id); - } - - @Override - public void invalidateCachedRealm(CachedRealm realm) { - realmCache.remove(realm.getId()); - realmCacheByName.remove(realm.getName()); - } - - @Override - public void invalidateCachedRealmById(String id) { - CachedRealm cached = realmCache.remove(id); - if (cached != null) realmCacheByName.remove(cached.getName()); - } - - - @Override - public void addCachedRealm(CachedRealm realm) { - realmCache.put(realm.getId(), realm); - realmCacheByName.put(realm.getName(), realm); - - } - - @Override - public CachedRealm getCachedRealmByName(String name) { - return realmCacheByName.get(name); - } - - @Override - public CachedApplication getApplication(String id) { - return applicationCache.get(id); - } - - @Override - public void invalidateApplication(CachedApplication app) { - applicationCache.remove(app.getId()); - } - - @Override - public void addCachedApplication(CachedApplication app) { - applicationCache.put(app.getId(), app); - } - - @Override - public void invalidateCachedApplicationById(String id) { - applicationCache.remove(id); - } - - @Override - public CachedOAuthClient getOAuthClient(String id) { - return clientCache.get(id); - } - - @Override - public void invalidateOAuthClient(CachedOAuthClient client) { - clientCache.remove(client.getId()); - } - - @Override - public void addCachedOAuthClient(CachedOAuthClient client) { - clientCache.put(client.getId(), client); - } - - @Override - public void invalidateCachedOAuthClientById(String id) { - clientCache.remove(id); - } - - @Override - public CachedRole getRole(String id) { - return roleCache.get(id); - } - - @Override - public void invalidateRole(CachedRole role) { - roleCache.remove(role); - } - - @Override - public void invalidateRoleById(String id) { - roleCache.remove(id); - } - - @Override - public void addCachedRole(CachedRole role) { - roleCache.put(role.getId(), role); - } - - @Override - public void invalidateCachedRoleById(String id) { - roleCache.remove(id); - } -} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheModelProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheModelProviderFactory.java index 5032303813..bb512ee23e 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheModelProviderFactory.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheModelProviderFactory.java @@ -8,7 +8,7 @@ import org.keycloak.models.KeycloakSession; * @version $Revision: 1 $ */ public class SimpleCacheModelProviderFactory implements CacheModelProviderFactory { - protected KeycloakCache cache = new SimpleCache(); + protected RealmCache cache = new SimpleRealmCache(); @Override public CacheModelProvider create(KeycloakSession session) { diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheUserProviderFactory.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheUserProviderFactory.java new file mode 100755 index 0000000000..6d12653ffa --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleCacheUserProviderFactory.java @@ -0,0 +1,33 @@ +package org.keycloak.models.cache; + +import org.keycloak.Config; +import org.keycloak.models.KeycloakSession; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class SimpleCacheUserProviderFactory implements CacheUserProviderFactory { + protected UserCache cache = new SimpleUserCache(); + + @Override + public CacheUserProvider create(KeycloakSession session) { + return new DefaultCacheUserProvider(cache, session); + } + + @Override + public void init(Config.Scope config) { + config.get(""); + + } + + @Override + public void close() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String getId() { + return "simple"; + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleRealmCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleRealmCache.java new file mode 100755 index 0000000000..94e5b28588 --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleRealmCache.java @@ -0,0 +1,130 @@ +package org.keycloak.models.cache; + +import org.keycloak.models.RealmModel; +import org.keycloak.models.cache.entities.CachedApplication; +import org.keycloak.models.cache.entities.CachedOAuthClient; +import org.keycloak.models.cache.entities.CachedRealm; +import org.keycloak.models.cache.entities.CachedRole; +import org.keycloak.models.cache.entities.CachedUser; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class SimpleRealmCache implements RealmCache { + + protected ConcurrentHashMap realmCache = new ConcurrentHashMap(); + protected ConcurrentHashMap realmCacheByName = new ConcurrentHashMap(); + protected ConcurrentHashMap applicationCache = new ConcurrentHashMap(); + protected ConcurrentHashMap clientCache = new ConcurrentHashMap(); + protected ConcurrentHashMap roleCache = new ConcurrentHashMap(); + + @Override + public void clear() { + realmCache.clear(); + realmCacheByName.clear(); + applicationCache.clear(); + clientCache.clear(); + roleCache.clear(); + } + + @Override + public CachedRealm getCachedRealm(String id) { + return realmCache.get(id); + } + + @Override + public void invalidateCachedRealm(CachedRealm realm) { + realmCache.remove(realm.getId()); + realmCacheByName.remove(realm.getName()); + } + + @Override + public void invalidateCachedRealmById(String id) { + CachedRealm cached = realmCache.remove(id); + if (cached != null) realmCacheByName.remove(cached.getName()); + } + + + @Override + public void addCachedRealm(CachedRealm realm) { + realmCache.put(realm.getId(), realm); + realmCacheByName.put(realm.getName(), realm); + + } + + @Override + public CachedRealm getCachedRealmByName(String name) { + return realmCacheByName.get(name); + } + + @Override + public CachedApplication getApplication(String id) { + return applicationCache.get(id); + } + + @Override + public void invalidateApplication(CachedApplication app) { + applicationCache.remove(app.getId()); + } + + @Override + public void addCachedApplication(CachedApplication app) { + applicationCache.put(app.getId(), app); + } + + @Override + public void invalidateCachedApplicationById(String id) { + applicationCache.remove(id); + } + + @Override + public CachedOAuthClient getOAuthClient(String id) { + return clientCache.get(id); + } + + @Override + public void invalidateOAuthClient(CachedOAuthClient client) { + clientCache.remove(client.getId()); + } + + @Override + public void addCachedOAuthClient(CachedOAuthClient client) { + clientCache.put(client.getId(), client); + } + + @Override + public void invalidateCachedOAuthClientById(String id) { + clientCache.remove(id); + } + + @Override + public CachedRole getRole(String id) { + return roleCache.get(id); + } + + @Override + public void invalidateRole(CachedRole role) { + roleCache.remove(role); + } + + @Override + public void invalidateRoleById(String id) { + roleCache.remove(id); + } + + @Override + public void addCachedRole(CachedRole role) { + roleCache.put(role.getId(), role); + } + + @Override + public void invalidateCachedRoleById(String id) { + roleCache.remove(id); + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleUserCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleUserCache.java new file mode 100755 index 0000000000..0468cf2ff1 --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/SimpleUserCache.java @@ -0,0 +1,148 @@ +package org.keycloak.models.cache; + +import org.keycloak.models.RealmModel; +import org.keycloak.models.cache.entities.CachedApplication; +import org.keycloak.models.cache.entities.CachedOAuthClient; +import org.keycloak.models.cache.entities.CachedRealm; +import org.keycloak.models.cache.entities.CachedRole; +import org.keycloak.models.cache.entities.CachedUser; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class SimpleUserCache implements UserCache { + + protected int maxUserCacheSize = 10000; + + + protected class RealmUsers { + protected class LRUCache extends LinkedHashMap { + public LRUCache() { + super(1000, 1.1F, true); + } + + @Override + public CachedUser put(String key, CachedUser value) { + usersByUsername.put(value.getUsername(), value); + if (value.getEmail() != null) { + usersByEmail.put(value.getEmail(), value); + } + return super.put(key, value); + } + + @Override + public CachedUser remove(Object key) { + CachedUser user = super.remove(key); + if (user == null) return null; + removeUser(user); + return user; + } + + @Override + public void clear() { + super.clear(); + usersByUsername.clear(); + usersByEmail.clear(); + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + boolean evict = size() > maxUserCacheSize; + if (evict) { + removeUser(eldest.getValue()); + } + return evict; + } + + private void removeUser(CachedUser value) { + usersByUsername.remove(value.getUsername()); + if (value.getEmail() != null) usersByEmail.remove(value.getEmail()); + } + } + + protected Map usersById = Collections.synchronizedMap(new LRUCache()); + protected Map usersByUsername = new ConcurrentHashMap(); + protected Map usersByEmail = new ConcurrentHashMap(); + + } + + protected ConcurrentHashMap realmUsers = new ConcurrentHashMap(); + + public int getMaxUserCacheSize() { + return maxUserCacheSize; + } + + public void setMaxUserCacheSize(int maxUserCacheSize) { + this.maxUserCacheSize = maxUserCacheSize; + } + + @Override + public CachedUser getCachedUser(String realmId, String id) { + if (realmId == null || id == null) return null; + RealmUsers users = realmUsers.get(realmId); + if (users == null) return null; + return users.usersById.get(id); + } + + @Override + public void invalidateCachedUser(String realmId, CachedUser user) { + RealmUsers users = realmUsers.get(realmId); + if (users == null) return; + users.usersById.remove(user.getId()); + } + + @Override + public void invalidateCachedUserById(String realmId, String id) { + RealmUsers users = realmUsers.get(realmId); + if (users == null) return; + users.usersById.remove(id); + } + + @Override + public void addCachedUser(String realmId, CachedUser user) { + RealmUsers users = realmUsers.get(realmId); + if (users == null) { + users = new RealmUsers(); + realmUsers.put(realmId, users); + } + users.usersById.put(user.getId(), user); + } + + @Override + public CachedUser getCachedUserByUsername(String realmId, String name) { + if (realmId == null || name == null) return null; + RealmUsers users = realmUsers.get(realmId); + if (users == null) return null; + CachedUser user = users.usersByUsername.get(name); + if (user == null) return null; + users.usersById.get(user.getId()); // refresh cache entry age + return user; + } + + @Override + public CachedUser getCachedUserByEmail(String realmId, String email) { + if (realmId == null || email == null) return null; + RealmUsers users = realmUsers.get(realmId); + if (users == null) return null; + CachedUser user = users.usersByEmail.get(email); + if (user == null) return null; + users.usersById.get(user.getId()); // refresh cache entry age + return user; + } + + @Override + public void invalidateRealmUsers(String realmId) { + realmUsers.remove(realmId); + } + + @Override + public void clear() { + realmUsers.clear(); + } +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java index b48e1c5d37..3f940772c9 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserAdapter.java @@ -2,6 +2,8 @@ package org.keycloak.models.cache; import org.keycloak.models.ApplicationModel; import org.keycloak.models.AuthenticationLinkModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ModelProvider; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; @@ -22,21 +24,21 @@ import java.util.Set; public class UserAdapter implements UserModel { protected UserModel updated; protected CachedUser cached; - protected KeycloakCache cache; - protected CacheModelProvider cacheSession; + protected CacheUserProvider userProviderCache; + protected KeycloakSession keycloakSession; protected RealmModel realm; - public UserAdapter(CachedUser cached, KeycloakCache cache, CacheModelProvider session, RealmModel realm) { + public UserAdapter(CachedUser cached, CacheUserProvider userProvider, KeycloakSession keycloakSession, RealmModel realm) { this.cached = cached; - this.cache = cache; - this.cacheSession = session; + this.userProviderCache = userProvider; + this.keycloakSession = keycloakSession; this.realm = realm; } protected void getDelegateForUpdate() { if (updated == null) { - cacheSession.registerUserInvalidation(getId()); - updated = cacheSession.getDelegate().getUserById(getId(), realm); + userProviderCache.registerUserInvalidation(realm, getId()); + updated = userProviderCache.getDelegate().getUserById(getId(), realm); if (updated == null) throw new IllegalStateException("Not found in database"); } } @@ -257,7 +259,13 @@ public class UserAdapter implements UserModel { if (updated != null) return updated.getRoleMappings(); Set roles = new HashSet(); for (String id : cached.getRoleMappings()) { - roles.add(cacheSession.getRoleById(id, realm)); + RoleModel roleById = keycloakSession.model().getRoleById(id, realm); + if (roleById == null) { + // chance that role was removed, so just delete to persistence and get user invalidated + getDelegateForUpdate(); + return updated.getRoleMappings(); + } + roles.add(roleById); } return roles; diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java new file mode 100755 index 0000000000..48a02b6e52 --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java @@ -0,0 +1,26 @@ +package org.keycloak.models.cache; + +import org.keycloak.models.RealmModel; +import org.keycloak.models.cache.entities.CachedUser; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public interface UserCache { + void clear(); + + CachedUser getCachedUser(String realmId, String id); + + void invalidateCachedUser(String realmId, CachedUser user); + + void addCachedUser(String realmId, CachedUser user); + + CachedUser getCachedUserByUsername(String realmId, String name); + + CachedUser getCachedUserByEmail(String realmId, String name); + + void invalidateCachedUserById(String realmId, String id); + + void invalidateRealmUsers(String realmId); +} diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java index 06cc7fef9f..9f78a04320 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedApplication.java @@ -1,21 +1,15 @@ package org.keycloak.models.cache.entities; import org.keycloak.models.ApplicationModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelProvider; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.UserSessionModel; -import org.keycloak.models.cache.KeycloakCache; +import org.keycloak.models.cache.RealmCache; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; /** * @author Bill Burke @@ -29,7 +23,7 @@ public class CachedApplication extends CachedClient { private boolean bearerOnly; private Map roles = new HashMap(); - public CachedApplication(KeycloakCache cache, ModelProvider delegate, RealmModel realm, ApplicationModel model) { + public CachedApplication(RealmCache cache, ModelProvider delegate, RealmModel realm, ApplicationModel model) { super(cache, delegate, realm, model); surrogateAuthRequired = model.isSurrogateAuthRequired(); managementUrl = model.getManagementUrl(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java index 7e6242279e..46a98c7f67 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java @@ -1,12 +1,10 @@ package org.keycloak.models.cache.entities; -import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; -import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelProvider; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; -import org.keycloak.models.cache.KeycloakCache; +import org.keycloak.models.cache.RealmCache; import java.util.HashSet; import java.util.Set; @@ -28,7 +26,7 @@ public class CachedClient { protected Set scope = new HashSet(); protected Set webOrigins = new HashSet(); - public CachedClient(KeycloakCache cache, ModelProvider delegate, RealmModel realm, ClientModel model) { + public CachedClient(RealmCache cache, ModelProvider delegate, RealmModel realm, ClientModel model) { id = model.getId(); secret = model.getSecret(); name = model.getClientId(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java index 397010febd..00ab503a31 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedOAuthClient.java @@ -1,17 +1,16 @@ package org.keycloak.models.cache.entities; -import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelProvider; import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; -import org.keycloak.models.cache.KeycloakCache; +import org.keycloak.models.cache.RealmCache; /** * @author Bill Burke * @version $Revision: 1 $ */ public class CachedOAuthClient extends CachedClient { - public CachedOAuthClient(KeycloakCache cache, ModelProvider delegate, RealmModel realm, OAuthClientModel model) { + public CachedOAuthClient(RealmCache cache, ModelProvider delegate, RealmModel realm, OAuthClientModel model) { super(cache, delegate, realm, model); } diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java index ffaa6c50a1..132d2cb8df 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java @@ -2,14 +2,13 @@ package org.keycloak.models.cache.entities; import org.keycloak.models.ApplicationModel; import org.keycloak.models.AuthenticationProviderModel; -import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelProvider; import org.keycloak.models.OAuthClientModel; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; -import org.keycloak.models.cache.KeycloakCache; +import org.keycloak.models.cache.RealmCache; import java.util.ArrayList; import java.util.HashMap; @@ -81,7 +80,7 @@ public class CachedRealm { public CachedRealm() { } - public CachedRealm(KeycloakCache cache, ModelProvider delegate, RealmModel model) { + public CachedRealm(RealmCache cache, ModelProvider delegate, RealmModel model) { id = model.getId(); name = model.getName(); enabled = model.isEnabled(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java index ee0318f662..587bf325d1 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedUser.java @@ -20,11 +20,9 @@ import java.util.Set; public class CachedUser { private String id; private String username; - private String usernameKey; private String firstName; private String lastName; private String email; - private String emailKey; private boolean emailVerified; private List credentials = new LinkedList(); private boolean enabled; @@ -38,14 +36,10 @@ public class CachedUser { public CachedUser(RealmModel realm, UserModel user) { this.id = user.getId(); this.username = user.getUsername(); - this.usernameKey = realm.getId() + "." + this.username; this.firstName = user.getFirstName(); this.lastName = user.getLastName(); this.attributes.putAll(user.getAttributes()); this.email = user.getEmail(); - if (this.email != null) { - this.emailKey = realm.getId() + "." + this.email; - } this.emailVerified = user.isEmailVerified(); this.credentials.addAll(user.getCredentialsDirectly()); this.enabled = user.isEnabled(); @@ -65,14 +59,6 @@ public class CachedUser { return username; } - public String getUsernameKey() { - return usernameKey; - } - - public String getEmailKey() { - return emailKey; - } - public String getFirstName() { return firstName; } diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory new file mode 100755 index 0000000000..880596e48e --- /dev/null +++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.models.cache.CacheUserProviderFactory @@ -0,0 +1 @@ +org.keycloak.models.cache.SimpleCacheUserProviderFactory diff --git a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi index eb9e1162b6..20a4503a9d 100755 --- a/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/model/invalidation-cache/model-adapters/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -1 +1,2 @@ -org.keycloak.models.cache.CacheModelProviderSpi \ No newline at end of file +org.keycloak.models.cache.CacheModelProviderSpi +org.keycloak.models.cache.CacheUserProviderSpi \ No newline at end of file diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java index 0ebe0170be..c91d132333 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java @@ -2,6 +2,7 @@ package org.keycloak.models.jpa; import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleContainerModel; @@ -25,10 +26,12 @@ import java.util.Set; public class ApplicationAdapter extends ClientAdapter implements ApplicationModel { protected EntityManager em; + protected KeycloakSession session; protected ApplicationEntity applicationEntity; - public ApplicationAdapter(RealmModel realm, EntityManager em, ApplicationEntity applicationEntity) { + public ApplicationAdapter(RealmModel realm, EntityManager em, KeycloakSession session, ApplicationEntity applicationEntity) { super(realm, applicationEntity, em); + this.session = session; this.realm = realm; this.em = em; this.applicationEntity = applicationEntity; @@ -135,6 +138,7 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode } if (!roleModel.getContainer().equals(this)) return false; + session.users().preRemove(roleModel); RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em); if (!role.isApplicationRole()) return false; @@ -143,7 +147,6 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode applicationEntity.getDefaultRoles().remove(role); em.createNativeQuery("delete from CompositeRole where childRole = :role").setParameter("role", role).executeUpdate(); em.createQuery("delete from " + ScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate(); - em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", role).executeUpdate(); role.setApplication(null); em.flush(); em.remove(role); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java index c324c94d84..e780760954 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java @@ -84,38 +84,6 @@ public class JpaModelProvider implements ModelProvider { return new RealmAdapter(session, em, realm); } - @Override - public UserModel getUserById(String id, RealmModel realmModel) { - TypedQuery query = em.createNamedQuery("getRealmUserById", UserEntity.class); - query.setParameter("id", id); - RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId()); - query.setParameter("realm", realm); - List entities = query.getResultList(); - if (entities.size() == 0) return null; - return new UserAdapter(realmModel, em, entities.get(0)); - } - - @Override - public UserModel getUserByUsername(String username, RealmModel realmModel) { - TypedQuery query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class); - query.setParameter("username", username); - RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId()); - query.setParameter("realm", realm); - List results = query.getResultList(); - if (results.size() == 0) return null; - return new UserAdapter(realmModel, em, results.get(0)); - } - - @Override - public UserModel getUserByEmail(String email, RealmModel realmModel) { - TypedQuery query = em.createNamedQuery("getRealmUserByEmail", UserEntity.class); - query.setParameter("email", email); - RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId()); - query.setParameter("realm", realm); - List results = query.getResultList(); - return results.isEmpty() ? null : new UserAdapter(realmModel, em, results.get(0)); - } - @Override public boolean removeRealm(String id) { RealmEntity realm = em.find(RealmEntity.class, id); @@ -124,6 +92,7 @@ public class JpaModelProvider implements ModelProvider { } RealmAdapter adapter = new RealmAdapter(session, em, realm); + session.users().preRemove(adapter); for (ApplicationEntity a : new LinkedList(realm.getApplications())) { adapter.removeApplication(a.getId()); } @@ -132,11 +101,7 @@ public class JpaModelProvider implements ModelProvider { adapter.removeOAuthClient(oauth.getId()); } - for (UserEntity u : em.createQuery("from UserEntity u where u.realm = :realm", UserEntity.class).setParameter("realm", realm).getResultList()) { - adapter.removeUser(u.getUsername()); - } - - em.remove(realm); + em.remove(realm); return true; } @@ -144,111 +109,6 @@ public class JpaModelProvider implements ModelProvider { public void close() { } - @Override - public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) { - TypedQuery query = em.createNamedQuery("findUserByLinkAndRealm", UserEntity.class); - RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId()); - query.setParameter("realm", realmEntity); - query.setParameter("socialProvider", socialLink.getSocialProvider()); - query.setParameter("socialUserId", socialLink.getSocialUserId()); - List results = query.getResultList(); - if (results.isEmpty()) { - return null; - } else if (results.size() > 1) { - throw new IllegalStateException("More results found for socialProvider=" + socialLink.getSocialProvider() + - ", socialUserId=" + socialLink.getSocialUserId() + ", results=" + results); - } else { - UserEntity user = results.get(0); - return new UserAdapter(realm, em, user); - } - } - - @Override - public List getUsers(RealmModel realm) { - TypedQuery query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class); - RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId()); - query.setParameter("realm", realmEntity); - List results = query.getResultList(); - List users = new ArrayList(); - for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity)); - return users; - } - - @Override - public List searchForUser(String search, RealmModel realm) { - TypedQuery query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.username) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class); - RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId()); - query.setParameter("realm", realmEntity); - query.setParameter("search", "%" + search.toLowerCase() + "%"); - List results = query.getResultList(); - List users = new ArrayList(); - for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity)); - return users; - } - - @Override - public List searchForUserByAttributes(Map attributes, RealmModel realm) { - StringBuilder builder = new StringBuilder("select u from UserEntity u"); - boolean first = true; - for (Map.Entry entry : attributes.entrySet()) { - String attribute = null; - if (entry.getKey().equals(UserModel.LOGIN_NAME)) { - attribute = "lower(username)"; - } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) { - attribute = "lower(firstName)"; - } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) { - attribute = "lower(lastName)"; - } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) { - attribute = "lower(email)"; - } - if (attribute == null) continue; - if (first) { - first = false; - builder.append(" where realm = :realm"); - } else { - builder.append(" and "); - } - builder.append(attribute).append(" like '%").append(entry.getValue().toLowerCase()).append("%'"); - } - String q = builder.toString(); - TypedQuery query = em.createQuery(q, UserEntity.class); - RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId()); - query.setParameter("realm", realmEntity); - List results = query.getResultList(); - List users = new ArrayList(); - for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity)); - return users; - } - - private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) { - TypedQuery query = em.createNamedQuery("findSocialLinkByUserAndProvider", SocialLinkEntity.class); - UserEntity userEntity = em.getReference(UserEntity.class, user.getId()); - query.setParameter("user", userEntity); - query.setParameter("socialProvider", socialProvider); - List results = query.getResultList(); - return results.size() > 0 ? results.get(0) : null; - } - - - @Override - public Set getSocialLinks(UserModel user, RealmModel realm) { - TypedQuery query = em.createNamedQuery("findSocialLinkByUser", SocialLinkEntity.class); - UserEntity userEntity = em.getReference(UserEntity.class, user.getId()); - query.setParameter("user", userEntity); - List results = query.getResultList(); - Set set = new HashSet(); - for (SocialLinkEntity entity : results) { - set.add(new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUserId(), entity.getSocialUsername())); - } - return set; - } - - @Override - public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) { - SocialLinkEntity entity = findSocialLink(user, socialProvider); - return (entity != null) ? new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUserId(), entity.getSocialUsername()) : null; - } - @Override public RoleModel getRoleById(String id, RealmModel realm) { RoleEntity entity = em.find(RoleEntity.class, id); @@ -263,7 +123,7 @@ public class JpaModelProvider implements ModelProvider { // Check if application belongs to this realm if (app == null || !realm.getId().equals(app.getRealm().getId())) return null; - return new ApplicationAdapter(realm, em, app); + return new ApplicationAdapter(realm, em, session, app); } @Override diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java index 48b47300d3..ba232a5994 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java @@ -39,7 +39,6 @@ public class JpaUserProvider implements UserProvider { public JpaUserProvider(KeycloakSession session, EntityManager em) { this.session = session; this.em = em; - this.em = PersistenceExceptionConverter.create(em); } @Override @@ -98,6 +97,34 @@ public class JpaUserProvider implements UserProvider { em.remove(user); } + @Override + public void addSocialLink(RealmModel realm, UserModel user, SocialLinkModel socialLink) { + SocialLinkEntity entity = new SocialLinkEntity(); + RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId()); + entity.setRealm(realmEntity); + entity.setSocialProvider(socialLink.getSocialProvider()); + entity.setSocialUserId(socialLink.getSocialUserId()); + entity.setSocialUsername(socialLink.getSocialUsername()); + UserEntity userEntity = em.getReference(UserEntity.class, user.getId()); + entity.setUser(userEntity); + em.persist(entity); + em.flush(); + } + + @Override + public boolean removeSocialLink(RealmModel realm, UserModel user, String socialProvider) { + SocialLinkEntity entity = findSocialLink(user, socialProvider); + if (entity != null) { + em.remove(entity); + em.flush(); + return true; + } else { + return false; + } + } + + + @Override public void preRemove(RealmModel realm) { TypedQuery query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class); @@ -114,12 +141,6 @@ public class JpaUserProvider implements UserProvider { em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate(); } - - @Override - public KeycloakTransaction getTransaction() { - return new JpaKeycloakTransaction(em); - } - @Override public UserModel getUserById(String id, RealmModel realmModel) { TypedQuery query = em.createNamedQuery("getRealmUserById", UserEntity.class); @@ -154,8 +175,6 @@ public class JpaUserProvider implements UserProvider { @Override public void close() { - if (em.getTransaction().isActive()) em.getTransaction().rollback(); - if (em.isOpen()) em.close(); } @Override diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java new file mode 100755 index 0000000000..3242489b5f --- /dev/null +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java @@ -0,0 +1,38 @@ +package org.keycloak.models.jpa; + +import org.keycloak.Config; +import org.keycloak.connections.jpa.JpaConnectionProvider; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ModelProvider; +import org.keycloak.models.ModelProviderFactory; +import org.keycloak.models.UserProvider; +import org.keycloak.models.UserProviderFactory; + +import javax.persistence.EntityManager; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class JpaUserProviderFactory implements UserProviderFactory { + + @Override + public void init(Config.Scope config) { + } + + @Override + public String getId() { + return "jpa"; + } + + @Override + public UserProvider create(KeycloakSession session) { + EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager(); + return new JpaUserProvider(session, em); + } + + @Override + public void close() { + } + +} diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index a656b0a1ff..0d8dad0d05 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -22,9 +22,6 @@ import org.keycloak.models.jpa.entities.RealmEntity; import org.keycloak.models.jpa.entities.RequiredCredentialEntity; import org.keycloak.models.jpa.entities.RoleEntity; import org.keycloak.models.jpa.entities.ScopeMappingEntity; -import org.keycloak.models.jpa.entities.SocialLinkEntity; -import org.keycloak.models.jpa.entities.UserEntity; -import org.keycloak.models.jpa.entities.UserRoleMappingEntity; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.TimeBasedOTP; @@ -411,75 +408,6 @@ public class RealmAdapter implements RealmModel { } - @Override - public UserModel getUser(String name) { - return session.model().getUserByUsername(name, this); - } - - @Override - public UserModel getUserByEmail(String email) { - return session.model().getUserByEmail(email, this); - } - - @Override - public UserModel getUserById(String id) { - return session.model().getUserById(id, this); - } - - @Override - public UserModel addUser(String username) { - return this.addUser(KeycloakModelUtils.generateId(), username, true); - } - - @Override - public UserModel addUser(String id, String username, boolean addDefaultRoles) { - if (id == null) { - id = KeycloakModelUtils.generateId(); - } - - UserEntity entity = new UserEntity(); - entity.setId(id); - entity.setUsername(username); - entity.setRealm(realm); - em.persist(entity); - em.flush(); - UserModel userModel = new UserAdapter(this, em, entity); - - if (addDefaultRoles) { - for (String r : getDefaultRoles()) { - userModel.grantRole(getRole(r)); - } - - for (ApplicationModel application : getApplications()) { - for (String r : application.getDefaultRoles()) { - userModel.grantRole(application.getRole(r)); - } - } - } - - return userModel; - } - - @Override - public boolean removeUser(String name) { - TypedQuery query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class); - query.setParameter("username", name); - query.setParameter("realm", realm); - List results = query.getResultList(); - if (results.size() == 0) return false; - removeUser(results.get(0)); - return true; - } - - private void removeUser(UserEntity user) { - em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate(); - em.createQuery("delete from " + SocialLinkEntity.class.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate(); - if (user.getAuthenticationLink() != null) { - em.remove(user.getAuthenticationLink()); - } - em.remove(user); - } - @Override public List getDefaultRoles() { Collection entities = realm.getDefaultRoles(); @@ -567,7 +495,7 @@ public class RealmAdapter implements RealmModel { List list = new ArrayList(); if (realm.getApplications() == null) return list; for (ApplicationEntity entity : realm.getApplications()) { - list.add(new ApplicationAdapter(this, em, entity)); + list.add(new ApplicationAdapter(this, em, session, entity)); } return list; } @@ -587,7 +515,7 @@ public class RealmAdapter implements RealmModel { realm.getApplications().add(applicationData); em.persist(applicationData); em.flush(); - ApplicationModel resource = new ApplicationAdapter(this, em, applicationData); + ApplicationModel resource = new ApplicationAdapter(this, em, session, applicationData); em.flush(); return resource; } @@ -636,57 +564,6 @@ public class RealmAdapter implements RealmModel { return getApplicationNameMap().get(name); } - @Override - public UserModel getUserBySocialLink(SocialLinkModel socialLink) { - return session.model().getUserBySocialLink(socialLink, this); - } - - @Override - public Set getSocialLinks(UserModel user) { - return session.model().getSocialLinks(user, this); - } - - @Override - public SocialLinkModel getSocialLink(UserModel user, String socialProvider) { - return session.model().getSocialLink(user, socialProvider, this); - } - - @Override - public void addSocialLink(UserModel user, SocialLinkModel socialLink) { - SocialLinkEntity entity = new SocialLinkEntity(); - entity.setRealm(realm); - entity.setSocialProvider(socialLink.getSocialProvider()); - entity.setSocialUserId(socialLink.getSocialUserId()); - entity.setSocialUsername(socialLink.getSocialUsername()); - UserEntity userEntity = em.getReference(UserEntity.class, user.getId()); - entity.setUser(userEntity); - em.persist(entity); - em.flush(); - } - - private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) { - TypedQuery query = em.createNamedQuery("findSocialLinkByUserAndProvider", SocialLinkEntity.class); - UserEntity userEntity = em.getReference(UserEntity.class, user.getId()); - query.setParameter("user", userEntity); - query.setParameter("socialProvider", socialProvider); - List results = query.getResultList(); - return results.size() > 0 ? results.get(0) : null; - } - - - @Override - public boolean removeSocialLink(UserModel user, String socialProvider) { - SocialLinkEntity entity = findSocialLink(user, socialProvider); - if (entity != null) { - em.remove(entity); - em.flush(); - return true; - } else { - return false; - } - } - - @Override public boolean isSocial() { return realm.isSocial(); @@ -709,21 +586,6 @@ public class RealmAdapter implements RealmModel { em.flush(); } - @Override - public List getUsers() { - return session.model().getUsers(this); - } - - @Override - public List searchForUser(String search) { - return session.model().searchForUser(search, this); - } - - @Override - public List searchForUserByAttributes(Map attributes) { - return session.model().searchForUserByAttributes(attributes, this); - } - @Override public OAuthClientModel addOAuthClient(String name) { return this.addOAuthClient(KeycloakModelUtils.generateId(), name); @@ -899,13 +761,12 @@ public class RealmAdapter implements RealmModel { return false; } if (!role.getContainer().equals(this)) return false; - + session.users().preRemove(role); RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); realm.getRoles().remove(role); realm.getDefaultRoles().remove(role); em.createNativeQuery("delete from CompositeRole where childRole = :role").setParameter("role", roleEntity).executeUpdate(); - em.createQuery("delete from " + UserRoleMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate(); em.createQuery("delete from " + ScopeMappingEntity.class.getSimpleName() + " where role = :role").setParameter("role", roleEntity).executeUpdate(); em.remove(roleEntity); @@ -1060,7 +921,7 @@ public class RealmAdapter implements RealmModel { @Override public ApplicationModel getMasterAdminApp() { - return new ApplicationAdapter(this, em, realm.getMasterAdminApp()); + return new ApplicationAdapter(this, em, session, realm.getMasterAdminApp()); } @Override diff --git a/model/jpa/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory b/model/jpa/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory new file mode 100755 index 0000000000..6c80343bc1 --- /dev/null +++ b/model/jpa/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory @@ -0,0 +1 @@ +org.keycloak.models.jpa.JpaUserProviderFactory \ No newline at end of file diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java index 6cfc06ae9a..525d33ca97 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java @@ -141,6 +141,7 @@ public class ApplicationAdapter extends ClientAdapter im @Override public boolean removeRole(RoleModel role) { + session.users().preRemove(role); return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext); } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java index 94b632df73..b5147cb109 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoModelProvider.java @@ -94,50 +94,11 @@ public class MongoModelProvider implements ModelProvider { return new RealmAdapter(session, realm, invocationContext); } - @Override - public UserModel getUserById(String id, RealmModel realm) { - MongoUserEntity user = getMongoStore().loadEntity(MongoUserEntity.class, id, invocationContext); - - // Check that it's user from this realm - if (user == null || !realm.getId().equals(user.getRealmId())) { - return null; - } else { - return new UserAdapter(session, realm, user, invocationContext); - } - } - - @Override - public UserModel getUserByUsername(String username, RealmModel realm) { - DBObject query = new QueryBuilder() - .and("username").is(username) - .and("realmId").is(realm.getId()) - .get(); - MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext); - - if (user == null) { - return null; - } else { - return new UserAdapter(session, realm, user, invocationContext); - } - } - - @Override - public UserModel getUserByEmail(String email, RealmModel realm) { - DBObject query = new QueryBuilder() - .and("email").is(email) - .and("realmId").is(realm.getId()) - .get(); - MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext); - - if (user == null) { - return null; - } else { - return new UserAdapter(session, realm, user, invocationContext); - } - } - @Override public boolean removeRealm(String id) { + RealmModel realm = getRealm(id); + if (realm == null) return false; + session.users().preRemove(realm); return getMongoStore().removeEntity(MongoRealmEntity.class, id, invocationContext); } @@ -145,138 +106,6 @@ public class MongoModelProvider implements ModelProvider { return invocationContext.getMongoStore(); } - @Override - public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) { - DBObject query = new QueryBuilder() - .and("socialLinks.socialProvider").is(socialLink.getSocialProvider()) - .and("socialLinks.socialUserId").is(socialLink.getSocialUserId()) - .and("realmId").is(realm.getId()) - .get(); - MongoUserEntity userEntity = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext); - return userEntity == null ? null : new UserAdapter(session, realm, userEntity, invocationContext); - } - - protected List convertUserEntities(RealmModel realm, List userEntities) { - List userModels = new ArrayList(); - for (MongoUserEntity user : userEntities) { - userModels.add(new UserAdapter(session, realm, user, invocationContext)); - } - return userModels; - } - - - @Override - public List getUsers(RealmModel realm) { - DBObject query = new QueryBuilder() - .and("realmId").is(realm.getId()) - .get(); - List users = getMongoStore().loadEntities(MongoUserEntity.class, query, invocationContext); - return convertUserEntities(realm, users); - } - - @Override - public List searchForUser(String search, RealmModel realm) { - search = search.trim(); - Pattern caseInsensitivePattern = Pattern.compile("(?i:" + search + ")"); - - QueryBuilder nameBuilder; - int spaceInd = search.lastIndexOf(" "); - - // Case when we have search string like "ohn Bow". Then firstName must end with "ohn" AND lastName must start with "bow" (everything case-insensitive) - if (spaceInd != -1) { - String firstName = search.substring(0, spaceInd); - String lastName = search.substring(spaceInd + 1); - Pattern firstNamePattern = Pattern.compile("(?i:" + firstName + "$)"); - Pattern lastNamePattern = Pattern.compile("(?i:^" + lastName + ")"); - nameBuilder = new QueryBuilder().and( - new QueryBuilder().put("firstName").regex(firstNamePattern).get(), - new QueryBuilder().put("lastName").regex(lastNamePattern).get() - ); - } else { - // Case when we have search without spaces like "foo". The firstName OR lastName could be "foo" (everything case-insensitive) - nameBuilder = new QueryBuilder().or( - new QueryBuilder().put("firstName").regex(caseInsensitivePattern).get(), - new QueryBuilder().put("lastName").regex(caseInsensitivePattern).get() - ); - } - - QueryBuilder builder = new QueryBuilder().and( - new QueryBuilder().and("realmId").is(realm.getId()).get(), - new QueryBuilder().or( - new QueryBuilder().put("username").regex(caseInsensitivePattern).get(), - new QueryBuilder().put("email").regex(caseInsensitivePattern).get(), - nameBuilder.get() - - ).get() - ); - - List users = getMongoStore().loadEntities(MongoUserEntity.class, builder.get(), invocationContext); - return convertUserEntities(realm, users); } - - @Override - public List searchForUserByAttributes(Map attributes, RealmModel realm) { - QueryBuilder queryBuilder = new QueryBuilder() - .and("realmId").is(realm.getId()); - - for (Map.Entry entry : attributes.entrySet()) { - if (entry.getKey().equals(UserModel.LOGIN_NAME)) { - queryBuilder.and("username").regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); - } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) { - queryBuilder.and(UserModel.FIRST_NAME).regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); - - } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) { - queryBuilder.and(UserModel.LAST_NAME).regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); - - } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) { - queryBuilder.and(UserModel.EMAIL).regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); - } - } - List users = getMongoStore().loadEntities(MongoUserEntity.class, queryBuilder.get(), invocationContext); - return convertUserEntities(realm, users); - } - - @Override - public Set getSocialLinks(UserModel userModel, RealmModel realm) { - UserModel user = getUserById(userModel.getId(), realm); - MongoUserEntity userEntity = ((UserAdapter) user).getUser(); - List linkEntities = userEntity.getSocialLinks(); - - if (linkEntities == null) { - return Collections.EMPTY_SET; - } - - Set result = new HashSet(); - for (SocialLinkEntity socialLinkEntity : linkEntities) { - SocialLinkModel model = new SocialLinkModel(socialLinkEntity.getSocialProvider(), - socialLinkEntity.getSocialUserId(), socialLinkEntity.getSocialUsername()); - result.add(model); - } - return result; - } - - private SocialLinkEntity findSocialLink(UserModel userModel, String socialProvider, RealmModel realm) { - UserModel user = getUserById(userModel.getId(), realm); - MongoUserEntity userEntity = ((UserAdapter) user).getUser(); - List linkEntities = userEntity.getSocialLinks(); - if (linkEntities == null) { - return null; - } - - for (SocialLinkEntity socialLinkEntity : linkEntities) { - if (socialLinkEntity.getSocialProvider().equals(socialProvider)) { - return socialLinkEntity; - } - } - return null; - } - - - @Override - public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) { - SocialLinkEntity socialLinkEntity = findSocialLink(user, socialProvider, realm); - return socialLinkEntity != null ? new SocialLinkModel(socialLinkEntity.getSocialProvider(), socialLinkEntity.getSocialUserId(), socialLinkEntity.getSocialUsername()) : null; - } - @Override public RoleModel getRoleById(String id, RealmModel realm) { MongoRoleEntity role = getMongoStore().loadEntity(MongoRoleEntity.class, id, invocationContext); diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java new file mode 100755 index 0000000000..f6a8d8e606 --- /dev/null +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java @@ -0,0 +1,322 @@ +package org.keycloak.models.mongo.keycloak.adapters; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; +import com.mongodb.QueryBuilder; +import org.keycloak.connections.mongo.api.MongoStore; +import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; +import org.keycloak.models.ApplicationModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ModelProvider; +import org.keycloak.models.OAuthClientModel; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.SocialLinkModel; +import org.keycloak.models.UserModel; +import org.keycloak.models.UserProvider; +import org.keycloak.models.entities.SocialLinkEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; +import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity; +import org.keycloak.models.utils.KeycloakModelUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * @author Marek Posolda + */ +public class MongoUserProvider implements UserProvider { + + private final MongoStoreInvocationContext invocationContext; + private final KeycloakSession session; + private final MongoStore mongoStore; + + public MongoUserProvider(KeycloakSession session, MongoStore mongoStore, MongoStoreInvocationContext invocationContext) { + this.session = session; + this.mongoStore = mongoStore; + this.invocationContext = invocationContext; + } + + @Override + public void close() { + // TODO + } + + @Override + public UserModel getUserById(String id, RealmModel realm) { + MongoUserEntity user = getMongoStore().loadEntity(MongoUserEntity.class, id, invocationContext); + + // Check that it's user from this realm + if (user == null || !realm.getId().equals(user.getRealmId())) { + return null; + } else { + return new UserAdapter(session, realm, user, invocationContext); + } + } + + @Override + public UserModel getUserByUsername(String username, RealmModel realm) { + DBObject query = new QueryBuilder() + .and("username").is(username) + .and("realmId").is(realm.getId()) + .get(); + MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext); + + if (user == null) { + return null; + } else { + return new UserAdapter(session, realm, user, invocationContext); + } + } + + @Override + public UserModel getUserByEmail(String email, RealmModel realm) { + DBObject query = new QueryBuilder() + .and("email").is(email) + .and("realmId").is(realm.getId()) + .get(); + MongoUserEntity user = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext); + + if (user == null) { + return null; + } else { + return new UserAdapter(session, realm, user, invocationContext); + } + } + + protected MongoStore getMongoStore() { + return invocationContext.getMongoStore(); + } + + @Override + public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) { + DBObject query = new QueryBuilder() + .and("socialLinks.socialProvider").is(socialLink.getSocialProvider()) + .and("socialLinks.socialUserId").is(socialLink.getSocialUserId()) + .and("realmId").is(realm.getId()) + .get(); + MongoUserEntity userEntity = getMongoStore().loadSingleEntity(MongoUserEntity.class, query, invocationContext); + return userEntity == null ? null : new UserAdapter(session, realm, userEntity, invocationContext); + } + + protected List convertUserEntities(RealmModel realm, List userEntities) { + List userModels = new ArrayList(); + for (MongoUserEntity user : userEntities) { + userModels.add(new UserAdapter(session, realm, user, invocationContext)); + } + return userModels; + } + + + @Override + public List getUsers(RealmModel realm) { + DBObject query = new QueryBuilder() + .and("realmId").is(realm.getId()) + .get(); + List users = getMongoStore().loadEntities(MongoUserEntity.class, query, invocationContext); + return convertUserEntities(realm, users); + } + + @Override + public List searchForUser(String search, RealmModel realm) { + search = search.trim(); + Pattern caseInsensitivePattern = Pattern.compile("(?i:" + search + ")"); + + QueryBuilder nameBuilder; + int spaceInd = search.lastIndexOf(" "); + + // Case when we have search string like "ohn Bow". Then firstName must end with "ohn" AND lastName must start with "bow" (everything case-insensitive) + if (spaceInd != -1) { + String firstName = search.substring(0, spaceInd); + String lastName = search.substring(spaceInd + 1); + Pattern firstNamePattern = Pattern.compile("(?i:" + firstName + "$)"); + Pattern lastNamePattern = Pattern.compile("(?i:^" + lastName + ")"); + nameBuilder = new QueryBuilder().and( + new QueryBuilder().put("firstName").regex(firstNamePattern).get(), + new QueryBuilder().put("lastName").regex(lastNamePattern).get() + ); + } else { + // Case when we have search without spaces like "foo". The firstName OR lastName could be "foo" (everything case-insensitive) + nameBuilder = new QueryBuilder().or( + new QueryBuilder().put("firstName").regex(caseInsensitivePattern).get(), + new QueryBuilder().put("lastName").regex(caseInsensitivePattern).get() + ); + } + + QueryBuilder builder = new QueryBuilder().and( + new QueryBuilder().and("realmId").is(realm.getId()).get(), + new QueryBuilder().or( + new QueryBuilder().put("username").regex(caseInsensitivePattern).get(), + new QueryBuilder().put("email").regex(caseInsensitivePattern).get(), + nameBuilder.get() + + ).get() + ); + + List users = getMongoStore().loadEntities(MongoUserEntity.class, builder.get(), invocationContext); + return convertUserEntities(realm, users); } + + @Override + public List searchForUserByAttributes(Map attributes, RealmModel realm) { + QueryBuilder queryBuilder = new QueryBuilder() + .and("realmId").is(realm.getId()); + + for (Map.Entry entry : attributes.entrySet()) { + if (entry.getKey().equals(UserModel.LOGIN_NAME)) { + queryBuilder.and("username").regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); + } else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) { + queryBuilder.and(UserModel.FIRST_NAME).regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); + + } else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) { + queryBuilder.and(UserModel.LAST_NAME).regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); + + } else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) { + queryBuilder.and(UserModel.EMAIL).regex(Pattern.compile("(?i:" + entry.getValue() + "$)")); + } + } + List users = getMongoStore().loadEntities(MongoUserEntity.class, queryBuilder.get(), invocationContext); + return convertUserEntities(realm, users); + } + + @Override + public Set getSocialLinks(UserModel userModel, RealmModel realm) { + UserModel user = getUserById(userModel.getId(), realm); + MongoUserEntity userEntity = ((UserAdapter) user).getUser(); + List linkEntities = userEntity.getSocialLinks(); + + if (linkEntities == null) { + return Collections.EMPTY_SET; + } + + Set result = new HashSet(); + for (SocialLinkEntity socialLinkEntity : linkEntities) { + SocialLinkModel model = new SocialLinkModel(socialLinkEntity.getSocialProvider(), + socialLinkEntity.getSocialUserId(), socialLinkEntity.getSocialUsername()); + result.add(model); + } + return result; + } + + private SocialLinkEntity findSocialLink(UserModel userModel, String socialProvider, RealmModel realm) { + UserModel user = getUserById(userModel.getId(), realm); + MongoUserEntity userEntity = ((UserAdapter) user).getUser(); + List linkEntities = userEntity.getSocialLinks(); + if (linkEntities == null) { + return null; + } + + for (SocialLinkEntity socialLinkEntity : linkEntities) { + if (socialLinkEntity.getSocialProvider().equals(socialProvider)) { + return socialLinkEntity; + } + } + return null; + } + + + @Override + public SocialLinkModel getSocialLink(UserModel user, String socialProvider, RealmModel realm) { + SocialLinkEntity socialLinkEntity = findSocialLink(user, socialProvider, realm); + return socialLinkEntity != null ? new SocialLinkModel(socialLinkEntity.getSocialProvider(), socialLinkEntity.getSocialUserId(), socialLinkEntity.getSocialUsername()) : null; + } + + @Override + public UserAdapter addUser(RealmModel realm, String id, String username, boolean addDefaultRoles) { + UserAdapter userModel = addUserEntity(realm, id, username); + + if (addDefaultRoles) { + for (String r : realm.getDefaultRoles()) { + userModel.grantRole(realm.getRole(r)); + } + + for (ApplicationModel application : realm.getApplications()) { + for (String r : application.getDefaultRoles()) { + userModel.grantRole(application.getRole(r)); + } + } + } + + return userModel; + } + + protected UserAdapter addUserEntity(RealmModel realm, String id, String username) { + MongoUserEntity userEntity = new MongoUserEntity(); + userEntity.setId(id); + userEntity.setUsername(username); + // Compatibility with JPA model, which has user disabled by default + // userEntity.setEnabled(true); + userEntity.setRealmId(realm.getId()); + + getMongoStore().insertEntity(userEntity, invocationContext); + return new UserAdapter(session, realm, userEntity, invocationContext); + } + + @Override + public boolean removeUser(RealmModel realm, String name) { + DBObject query = new QueryBuilder() + .and("username").is(name) + .and("realmId").is(realm.getId()) + .get(); + return getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext); + } + + + @Override + public void addSocialLink(RealmModel realm, UserModel user, SocialLinkModel socialLink) { + MongoUserEntity userEntity = ((UserAdapter) user).getUser(); + SocialLinkEntity socialLinkEntity = new SocialLinkEntity(); + socialLinkEntity.setSocialProvider(socialLink.getSocialProvider()); + socialLinkEntity.setSocialUserId(socialLink.getSocialUserId()); + socialLinkEntity.setSocialUsername(socialLink.getSocialUsername()); + + getMongoStore().pushItemToList(userEntity, "socialLinks", socialLinkEntity, true, invocationContext); + } + + @Override + public boolean removeSocialLink(RealmModel realm, UserModel userModel, String socialProvider) { + UserModel user = getUserById(userModel.getId(), realm); + MongoUserEntity userEntity = ((UserAdapter) user).getUser(); + SocialLinkEntity socialLinkEntity = findSocialLink(userEntity, socialProvider); + if (socialLinkEntity == null) { + return false; + } + return getMongoStore().pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext); + } + + private SocialLinkEntity findSocialLink(MongoUserEntity userEntity, String socialProvider) { + List linkEntities = userEntity.getSocialLinks(); + if (linkEntities == null) { + return null; + } + + for (SocialLinkEntity socialLinkEntity : linkEntities) { + if (socialLinkEntity.getSocialProvider().equals(socialProvider)) { + return socialLinkEntity; + } + } + return null; + } + + @Override + public UserModel addUser(RealmModel realm, String username) { + return this.addUser(realm, null, username, true); + } + + @Override + public void preRemove(RealmModel realm) { + // todo not sure what to do for this + } + + @Override + public void preRemove(RoleModel role) { + // todo not sure what to do for this + } +} diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java new file mode 100755 index 0000000000..b40127e887 --- /dev/null +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProviderFactory.java @@ -0,0 +1,40 @@ +package org.keycloak.models.mongo.keycloak.adapters; + +import org.jboss.logging.Logger; +import org.keycloak.Config; +import org.keycloak.connections.mongo.MongoConnectionProvider; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ModelProvider; +import org.keycloak.models.ModelProviderFactory; +import org.keycloak.models.UserProvider; +import org.keycloak.models.UserProviderFactory; + +/** + * KeycloakSessionFactory implementation based on MongoDB + * + * @author Marek Posolda + */ +public class MongoUserProviderFactory implements UserProviderFactory { + protected static final Logger logger = Logger.getLogger(MongoUserProviderFactory.class); + + @Override + public String getId() { + return "mongo"; + } + + @Override + public void init(Config.Scope config) { + } + + @Override + public UserProvider create(KeycloakSession session) { + MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class); + return new MongoUserProvider(session, connection.getMongoStore(), connection.getInvocationContext()); + } + + @Override + public void close() { + } + +} + diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index 361d2692a4..f9b9d04be2 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -438,66 +438,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme updateRealm(); } - @Override - public UserModel getUser(String name) { - return model.getUserByUsername(name, this); - } - - @Override - public UserModel getUserByEmail(String email) { - return model.getUserByEmail(email, this); - } - - @Override - public UserModel getUserById(String id) { - return model.getUserById(id, this); - } - - @Override - public UserAdapter addUser(String username) { - return this.addUser(null, username, true); - } - - @Override - public UserAdapter addUser(String id, String username, boolean addDefaultRoles) { - UserAdapter userModel = addUserEntity(id, username); - - if (addDefaultRoles) { - for (String r : getDefaultRoles()) { - userModel.grantRole(getRole(r)); - } - - for (ApplicationModel application : getApplications()) { - for (String r : application.getDefaultRoles()) { - userModel.grantRole(application.getRole(r)); - } - } - } - - return userModel; - } - - protected UserAdapter addUserEntity(String id, String username) { - MongoUserEntity userEntity = new MongoUserEntity(); - userEntity.setId(id); - userEntity.setUsername(username); - // Compatibility with JPA model, which has user disabled by default - // userEntity.setEnabled(true); - userEntity.setRealmId(getId()); - - getMongoStore().insertEntity(userEntity, invocationContext); - return new UserAdapter(session, this, userEntity, invocationContext); - } - - @Override - public boolean removeUser(String name) { - DBObject query = new QueryBuilder() - .and("username").is(name) - .and("realmId").is(getId()) - .get(); - return getMongoStore().removeEntities(MongoUserEntity.class, query, invocationContext); - } - @Override public RoleAdapter getRole(String name) { DBObject query = new QueryBuilder() @@ -536,6 +476,9 @@ public class RealmAdapter extends AbstractMongoAdapter impleme @Override public boolean removeRoleById(String id) { + RoleModel role = getRoleById(id); + if (role == null) return false; + session.users().preRemove(role); return getMongoStore().removeEntity(MongoRoleEntity.class, id, invocationContext); } @@ -799,60 +742,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme return false; } - - - - @Override - public UserModel getUserBySocialLink(SocialLinkModel socialLink) { - return model.getUserBySocialLink(socialLink, this); - } - - @Override - public Set getSocialLinks(UserModel user) { - return model.getSocialLinks(user, this); - } - - @Override - public SocialLinkModel getSocialLink(UserModel user, String socialProvider) { - return model.getSocialLink(user, socialProvider, this); - } - - @Override - public void addSocialLink(UserModel user, SocialLinkModel socialLink) { - MongoUserEntity userEntity = ((UserAdapter) user).getUser(); - SocialLinkEntity socialLinkEntity = new SocialLinkEntity(); - socialLinkEntity.setSocialProvider(socialLink.getSocialProvider()); - socialLinkEntity.setSocialUserId(socialLink.getSocialUserId()); - socialLinkEntity.setSocialUsername(socialLink.getSocialUsername()); - - getMongoStore().pushItemToList(userEntity, "socialLinks", socialLinkEntity, true, invocationContext); - } - - @Override - public boolean removeSocialLink(UserModel userModel, String socialProvider) { - UserModel user = getUserById(userModel.getId()); - MongoUserEntity userEntity = ((UserAdapter) user).getUser(); - SocialLinkEntity socialLinkEntity = findSocialLink(userEntity, socialProvider); - if (socialLinkEntity == null) { - return false; - } - return getMongoStore().pullItemFromList(userEntity, "socialLinks", socialLinkEntity, invocationContext); - } - - private SocialLinkEntity findSocialLink(MongoUserEntity userEntity, String socialProvider) { - List linkEntities = userEntity.getSocialLinks(); - if (linkEntities == null) { - return null; - } - - for (SocialLinkEntity socialLinkEntity : linkEntities) { - if (socialLinkEntity.getSocialProvider().equals(socialProvider)) { - return socialLinkEntity; - } - } - return null; - } - protected void updateRealm() { super.updateMongoEntity(); } @@ -865,23 +754,6 @@ public class RealmAdapter extends AbstractMongoAdapter impleme return model; } - @Override - public List getUsers() { - return model.getUsers(this); - } - - @Override - public List searchForUser(String search) { - return model.searchForUser(search, this); - - } - - @Override - public List searchForUserByAttributes(Map attributes) { - return model.searchForUserByAttributes(attributes, this); - } - - @Override public Map getSmtpConfig() { return realm.getSmtpConfig(); diff --git a/model/mongo/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory b/model/mongo/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory new file mode 100755 index 0000000000..ddc04d8852 --- /dev/null +++ b/model/mongo/src/main/resources/META-INF/services/org.keycloak.models.UserProviderFactory @@ -0,0 +1 @@ +org.keycloak.models.mongo.keycloak.adapters.MongoUserProviderFactory \ No newline at end of file diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java index aef6f2e246..490134f05d 100755 --- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java +++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/UserSessionAdapter.java @@ -45,7 +45,7 @@ public class UserSessionAdapter implements UserSessionModel { @Override public UserModel getUser() { - return realm.getUserById(entity.getUserId()); + return session.users().getUserById(entity.getUserId(), realm); } @Override diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java old mode 100644 new mode 100755 index 1ff9326dcb..6a62ba7096 --- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java +++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/UserSessionAdapter.java @@ -36,7 +36,7 @@ public class UserSessionAdapter implements UserSessionModel { } public UserModel getUser() { - return realm.getUserById(entity.getUser()); + return session.users().getUserById(entity.getUser(), realm); } public void setUser(UserModel user) { diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java old mode 100644 new mode 100755 index 1cbcb4137c..cbce2bd1e3 --- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java +++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/MongoUserSessionProvider.java @@ -47,7 +47,7 @@ public class MongoUserSessionProvider implements UserSessionProvider { entity.setLastSessionRefresh(currentTime); mongoStore.insertEntity(entity, invocationContext); - return new UserSessionAdapter(entity, realm, invocationContext); + return new UserSessionAdapter(session, entity, realm, invocationContext); } @Override @@ -56,7 +56,7 @@ public class MongoUserSessionProvider implements UserSessionProvider { if (entity == null) { return null; } else { - return new UserSessionAdapter(entity, realm, invocationContext); + return new UserSessionAdapter(session, entity, realm, invocationContext); } } @@ -65,7 +65,7 @@ public class MongoUserSessionProvider implements UserSessionProvider { DBObject query = new BasicDBObject("user", user.getId()); List sessions = new LinkedList(); for (MongoUserSessionEntity e : mongoStore.loadEntities(MongoUserSessionEntity.class, query, invocationContext)) { - sessions.add(new UserSessionAdapter(e, realm, invocationContext)); + sessions.add(new UserSessionAdapter(session, e, realm, invocationContext)); } return sessions; } @@ -79,7 +79,7 @@ public class MongoUserSessionProvider implements UserSessionProvider { List result = new LinkedList(); for (MongoUserSessionEntity session : sessions) { - result.add(new UserSessionAdapter(session, realm, invocationContext)); + result.add(new UserSessionAdapter(this.session, session, realm, invocationContext)); } return result; } @@ -93,7 +93,7 @@ public class MongoUserSessionProvider implements UserSessionProvider { List sessions = mongoStore.loadEntities(MongoUserSessionEntity.class, query, sort, invocationContext, firstResult, maxResults); List result = new LinkedList(); for (MongoUserSessionEntity session : sessions) { - result.add(new UserSessionAdapter(session, realm, invocationContext)); + result.add(new UserSessionAdapter(this.session, session, realm, invocationContext)); } return result; } diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java index 45863451c0..901dd24632 100755 --- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java +++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/UserSessionAdapter.java @@ -3,6 +3,7 @@ package org.keycloak.models.sessions.mongo; import org.jboss.logging.Logger; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; @@ -20,12 +21,14 @@ public class UserSessionAdapter extends AbstractMongoAdapter roles = realmModel.getRoles(); Assert.assertEquals(3, roles.size()); - UserModel user = realmModel.addUser("bburke"); + UserModel user = realmManager.getSession().users().addUser(realmModel, "bburke"); RoleModel realmUserRole = realmModel.getRole("user"); user.grantRole(realmUserRole); Assert.assertTrue(user.hasRole(realmUserRole)); @@ -618,13 +618,16 @@ public class AdapterTest extends AbstractModelTest { @Test public void testUsernameCollisions() throws Exception { - realmManager.createRealm("JUGGLER1").addUser("user1"); - realmManager.createRealm("JUGGLER2").addUser("user1"); + RealmModel juggler1 = realmManager.createRealm("JUGGLER1"); + realmManager.getSession().users().addUser(juggler1, "user1"); + RealmModel juggler2 = realmManager.createRealm("JUGGLER2"); + realmManager.getSession().users().addUser(juggler2, "user1"); commit(); // Try to create user with duplicate login name try { - realmManager.getRealmByName("JUGGLER1").addUser("user1"); + juggler1 = realmManager.getRealmByName("JUGGLER1"); + realmManager.getSession().users().addUser(juggler1, "user1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -632,10 +635,12 @@ public class AdapterTest extends AbstractModelTest { commit(true); // Ty to rename user to duplicate login name - realmManager.getRealmByName("JUGGLER1").addUser("user2"); + juggler1 = realmManager.getRealmByName("JUGGLER1"); + realmManager.getSession().users().addUser(juggler1, "user2"); commit(); try { - realmManager.getRealmByName("JUGGLER1").getUser("user2").setUsername("user1"); + juggler1 = realmManager.getRealmByName("JUGGLER1"); + realmManager.getSession().users().getUserByUsername("user2", juggler1).setUsername("user1"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -646,13 +651,16 @@ public class AdapterTest extends AbstractModelTest { @Test public void testEmailCollisions() throws Exception { - realmManager.createRealm("JUGGLER1").addUser("user1").setEmail("email@example.com"); - realmManager.createRealm("JUGGLER2").addUser("user1").setEmail("email@example.com"); + RealmModel juggler1 = realmManager.createRealm("JUGGLER1"); + realmManager.getSession().users().addUser(juggler1, "user1").setEmail("email@example.com"); + RealmModel juggler2 = realmManager.createRealm("JUGGLER2"); + realmManager.getSession().users().addUser(juggler2, "user1").setEmail("email@example.com"); commit(); // Try to create user with duplicate email + juggler1 = realmManager.getRealmByName("JUGGLER1"); try { - realmManager.getRealmByName("JUGGLER1").addUser("user2").setEmail("email@example.com"); + realmManager.getSession().users().addUser(juggler1, "user2").setEmail("email@example.com"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { @@ -661,10 +669,12 @@ public class AdapterTest extends AbstractModelTest { resetSession(); // Ty to rename user to duplicate email - realmManager.getRealmByName("JUGGLER1").addUser("user3").setEmail("email2@example.com"); + juggler1 = realmManager.getRealmByName("JUGGLER1"); + realmManager.getSession().users().addUser(juggler1, "user3").setEmail("email2@example.com"); commit(); try { - realmManager.getRealmByName("JUGGLER1").getUser("user3").setEmail("email@example.com"); + juggler1 = realmManager.getRealmByName("JUGGLER1"); + realmManager.getSession().users().getUserByUsername("user3", juggler1).setEmail("email@example.com"); commit(); Assert.fail("Expected exception"); } catch (ModelDuplicateException e) { diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java index 12c11c911c..0de953e10d 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersExternalModelTest.java @@ -54,7 +54,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest { realm1.setAuthenticationProviders(Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER)); realm2.setAuthenticationProviders(Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER)); - UserModel john = realm1.addUser("john"); + UserModel john = realmManager.getSession().users().addUser(realm1, "john"); john.setEnabled(true); john.setFirstName("John"); john.setLastName("Doe"); @@ -78,7 +78,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest { // Verify that user doesn't exists in realm2 and can't authenticate here Assert.assertEquals(AuthenticationManager.AuthenticationStatus.INVALID_USER, am.authenticateForm(session, null, realm2, formData)); - Assert.assertNull(realm2.getUser("john")); + Assert.assertNull(realmManager.getSession().users().getUserByUsername("john", realm2)); // Add externalModel authenticationProvider into realm2 and point to realm1 setupAuthenticationProviders(); @@ -89,7 +89,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest { // Authenticate john in realm2 and verify that now he exists here. Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(session, null, realm2, formData)); - UserModel john2 = realm2.getUser("john"); + UserModel john2 = realmManager.getSession().users().getUserByUsername("john", realm2); Assert.assertNotNull(john2); Assert.assertEquals("john", john2.getUsername()); Assert.assertEquals("John", john2.getFirstName()); @@ -100,7 +100,7 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest { AuthenticationLinkModel authLink = john2.getAuthenticationLink(); Assert.assertNotNull(authLink); Assert.assertEquals(authLink.getAuthProvider(), AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL); - Assert.assertEquals(authLink.getAuthUserId(), realm1.getUser("john").getId()); + Assert.assertEquals(authLink.getAuthUserId(), realmManager.getSession().users().getUserByUsername("john", realm1).getId()); } finally { ResteasyProviderFactory.clearContextData(); } @@ -113,9 +113,9 @@ public class AuthProvidersExternalModelTest extends AbstractModelTest { setupAuthenticationProviders(); // Add john to realm2 and set authentication link - UserModel john = realm2.addUser("john"); + UserModel john = realmManager.getSession().users().addUser(realm2, "john"); john.setEnabled(true); - john.setAuthenticationLink(new AuthenticationLinkModel(AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL, realm1.getUser("john").getId())); + john.setAuthenticationLink(new AuthenticationLinkModel(AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL, realmManager.getSession().users().getUserByUsername("john", realm1).getId())); try { // this is needed for externalModel provider diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java index ae927f8350..0c98722293 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/AuthProvidersLDAPTest.java @@ -80,14 +80,14 @@ public class AuthProvidersLDAPTest extends AbstractModelTest { // Verify that user doesn't exists in realm2 and can't authenticate here Assert.assertEquals(AuthenticationManager.AuthenticationStatus.INVALID_USER, am.authenticateForm(session, null, realm, formData)); - Assert.assertNull(realm.getUser("johnkeycloak")); + Assert.assertNull(session.users().getUserByUsername("johnkeycloak", realm)); // Add ldap authenticationProvider setupAuthenticationProviders(); // Authenticate john and verify that now he exists in realm Assert.assertEquals(AuthenticationManager.AuthenticationStatus.SUCCESS, am.authenticateForm(session, null, realm, formData)); - UserModel john = realm.getUser("johnkeycloak"); + UserModel john = session.users().getUserByUsername("johnkeycloak", realm); Assert.assertNotNull(john); Assert.assertEquals("johnkeycloak", john.getUsername()); Assert.assertEquals("John", john.getFirstName()); @@ -103,9 +103,8 @@ public class AuthProvidersLDAPTest extends AbstractModelTest { @Test public void testLdapInvalidAuthentication() { setupAuthenticationProviders(); - // Add some user and password to realm - UserModel realmUser = realm.addUser("realmUser"); + UserModel realmUser = session.users().addUser(realm, "realmUser"); realmUser.setEnabled(true); UserCredentialModel credential = new UserCredentialModel(); credential.setType(CredentialRepresentation.PASSWORD); @@ -149,7 +148,7 @@ public class AuthProvidersLDAPTest extends AbstractModelTest { // Change credential and validate that user can authenticate AuthenticationProviderManager authProviderManager = AuthenticationProviderManager.getManager(realm, session); - UserModel john = realm.getUser("johnkeycloak"); + UserModel john = session.users().getUserByUsername("johnkeycloak", realm); try { Assert.assertTrue(authProviderManager.updatePassword(john, "password-updated")); } catch (AuthenticationProviderException ape) { diff --git a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java index 5c186251f4..da603ba59a 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/AuthenticationManagerTest.java @@ -168,7 +168,7 @@ public class AuthenticationManagerTest extends AbstractModelTest { protector.start(); am = new AuthenticationManager(protector); - user = realm.addUser("test"); + user = realmManager.getSession().users().addUser(realm, "test"); user.setEnabled(true); UserCredentialModel credential = new UserCredentialModel(); diff --git a/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java index 071fcefcde..38c1c2ae23 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java @@ -57,7 +57,7 @@ public class CompositeRolesModelTest extends AbstractModelTest { Set requestedRoles = new HashSet(); RealmModel realm = realmManager.getRealm("Test"); - UserModel user = realm.getUser(username); + UserModel user = realmManager.getSession().users().getUserByUsername(username, realm); ApplicationModel application = realm.getApplicationByName(applicationName); Set roleMappings = user.getRoleMappings(); diff --git a/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java b/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java index a2a0c394e7..a3bfa24e07 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/ImportTest.java @@ -10,6 +10,7 @@ import org.keycloak.models.AuthenticationLinkModel; import org.keycloak.models.AuthenticationProviderModel; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; @@ -50,7 +51,7 @@ public class ImportTest extends AbstractModelTest { commit(); realm = realmManager.getRealm("demo"); - assertDataImportedInRealm(realm); + assertDataImportedInRealm(realmManager.getSession(), realm); commit(); @@ -59,7 +60,7 @@ public class ImportTest extends AbstractModelTest { } // Moved to static method, so it's possible to test this from other places too (for example export-import tests) - public static void assertDataImportedInRealm(RealmModel realm) { + public static void assertDataImportedInRealm(KeycloakSession session, RealmModel realm) { Assert.assertTrue(realm.isVerifyEmail()); Assert.assertFalse(realm.isUpdateProfileOnInitialSocialLogin()); @@ -72,9 +73,9 @@ public class ImportTest extends AbstractModelTest { Assert.assertNotNull(realm.getRole("foo")); Assert.assertNotNull(realm.getRole("bar")); - UserModel user = realm.getUser("loginclient"); + UserModel user = session.users().getUserByUsername("loginclient", realm); Assert.assertNotNull(user); - Assert.assertEquals(0, realm.getSocialLinks(user).size()); + Assert.assertEquals(0, session.users().getSocialLinks(user, realm).size()); List resources = realm.getApplications(); for (ApplicationModel app : resources) { @@ -103,14 +104,14 @@ public class ImportTest extends AbstractModelTest { // Test role mappings - UserModel admin = realm.getUser("admin"); + UserModel admin = session.users().getUserByUsername("admin", realm); Set allRoles = admin.getRoleMappings(); Assert.assertEquals(3, allRoles.size()); Assert.assertTrue(allRoles.contains(realm.getRole("admin"))); Assert.assertTrue(allRoles.contains(application.getRole("app-admin"))); Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-admin"))); - UserModel wburke = realm.getUser("wburke"); + UserModel wburke = session.users().getUserByUsername("wburke", realm); allRoles = wburke.getRoleMappings(); Assert.assertEquals(2, allRoles.size()); Assert.assertFalse(allRoles.contains(realm.getRole("admin"))); @@ -147,8 +148,8 @@ public class ImportTest extends AbstractModelTest { // Test social linking - UserModel socialUser = realm.getUser("mySocialUser"); - Set socialLinks = realm.getSocialLinks(socialUser); + UserModel socialUser = session.users().getUserByUsername("mySocialUser", realm); + Set socialLinks = session.users().getSocialLinks(socialUser, realm); Assert.assertEquals(3, socialLinks.size()); boolean facebookFound = false; boolean googleFound = false; @@ -170,19 +171,19 @@ public class ImportTest extends AbstractModelTest { } Assert.assertTrue(facebookFound && twitterFound && googleFound); - UserModel foundSocialUser = realm.getUserBySocialLink(new SocialLinkModel("facebook", "facebook1", "fbuser1")); + UserModel foundSocialUser = session.users().getUserBySocialLink(new SocialLinkModel("facebook", "facebook1", "fbuser1"), realm); Assert.assertEquals(foundSocialUser.getUsername(), socialUser.getUsername()); - Assert.assertNull(realm.getUserBySocialLink(new SocialLinkModel("facebook", "not-existing", "not-existing"))); + Assert.assertNull(session.users().getUserBySocialLink(new SocialLinkModel("facebook", "not-existing", "not-existing"), realm)); - SocialLinkModel foundSocialLink = realm.getSocialLink(socialUser, "facebook"); + SocialLinkModel foundSocialLink = session.users().getSocialLink(socialUser, "facebook", realm); Assert.assertEquals("facebook1", foundSocialLink.getSocialUserId()); Assert.assertEquals("fbuser1", foundSocialLink.getSocialUsername()); Assert.assertEquals("facebook", foundSocialLink.getSocialProvider()); // Test removing social link - Assert.assertTrue(realm.removeSocialLink(socialUser, "facebook")); - Assert.assertNull(realm.getSocialLink(socialUser, "facebook")); - Assert.assertFalse(realm.removeSocialLink(socialUser, "facebook")); + Assert.assertTrue(session.users().removeSocialLink(realm, socialUser, "facebook")); + Assert.assertNull(session.users().getSocialLink(socialUser, "facebook", realm)); + Assert.assertFalse(session.users().removeSocialLink(realm, socialUser, "facebook")); // Test smtp config Map smtpConfig = realm.getSmtpConfig(); diff --git a/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java b/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java index ce6b937c1f..3aa4d4bfab 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/MultipleRealmsTest.java @@ -31,8 +31,8 @@ public class MultipleRealmsTest extends AbstractModelTest { @Test public void testUsers() { - UserModel r1user1 = realm1.getUser("user1"); - UserModel r2user1 = realm2.getUser("user1"); + UserModel r1user1 = realmManager.getSession().users().getUserByUsername("user1", realm1); + UserModel r2user1 = realmManager.getSession().users().getUserByUsername("user1", realm2); Assert.assertEquals(r1user1.getUsername(), r2user1.getUsername()); Assert.assertNotEquals(r1user1.getId(), r2user1.getId()); @@ -46,16 +46,16 @@ public class MultipleRealmsTest extends AbstractModelTest { Assert.assertTrue(realm2.validatePassword(r2user1, "pass2")); // Test searching - Assert.assertEquals(2, realm1.searchForUser("user").size()); + Assert.assertEquals(2, realmManager.getSession().users().searchForUser("user", realm1).size()); commit(); realm1 = model.getRealm("id1"); realm2 = model.getRealm("id2"); - realm1.removeUser("user1"); - realm1.removeUser("user2"); - Assert.assertEquals(0, realm1.searchForUser("user").size()); - Assert.assertEquals(2, realm2.searchForUser("user").size()); + realmManager.getSession().users().removeUser(realm1, "user1"); + realmManager.getSession().users().removeUser(realm1, "user2"); + Assert.assertEquals(0, realmManager.getSession().users().searchForUser("user", realm1).size()); + Assert.assertEquals(2, realmManager.getSession().users().searchForUser("user", realm2).size()); } @Test @@ -90,8 +90,8 @@ public class MultipleRealmsTest extends AbstractModelTest { ApplicationModel app1 = realm.addApplication("app1"); realm.addApplication("app2"); - realm.addUser("user1"); - realm.addUser("user2"); + realmManager.getSession().users().addUser(realm, "user1"); + realmManager.getSession().users().addUser(realm, "user2"); realm.addRole("role1"); realm.addRole("role2"); diff --git a/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java index 3de0ae2e75..578c84d176 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/UserModelTest.java @@ -4,6 +4,7 @@ import org.junit.Assert; import org.junit.Test; import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserModel.RequiredAction; @@ -16,7 +17,8 @@ public class UserModelTest extends AbstractModelTest { @Test public void persistUser() { RealmModel realm = realmManager.createRealm("original"); - UserModel user = realm.addUser("user"); + KeycloakSession session = realmManager.getSession(); + UserModel user = session.users().addUser(realm, "user"); user.setFirstName("first-name"); user.setLastName("last-name"); user.setEmail("email"); @@ -24,11 +26,13 @@ public class UserModelTest extends AbstractModelTest { user.addRequiredAction(RequiredAction.CONFIGURE_TOTP); user.addRequiredAction(RequiredAction.UPDATE_PASSWORD); - UserModel persisted = realmManager.getRealm(realm.getId()).getUser("user"); + RealmModel searchRealm = realmManager.getRealm(realm.getId()); + UserModel persisted = session.users().getUserByUsername("user", searchRealm); assertEquals(user, persisted); - UserModel persisted2 = realmManager.getRealm(realm.getId()).getUserById(user.getId()); + searchRealm = realmManager.getRealm(realm.getId()); + UserModel persisted2 = session.users().getUserById(user.getId(), searchRealm); assertEquals(user, persisted2); } @@ -72,7 +76,8 @@ public class UserModelTest extends AbstractModelTest { @Test public void testUserRequiredActions() throws Exception { RealmModel realm = realmManager.createRealm("original"); - UserModel user = realm.addUser("user"); + KeycloakSession session = realmManager.getSession(); + UserModel user = session.users().addUser(realm, "user"); Assert.assertTrue(user.getRequiredActions().isEmpty()); @@ -80,32 +85,32 @@ public class UserModelTest extends AbstractModelTest { String id = realm.getId(); commit(); realm = realmManager.getRealm(id); - user = realm.getUser("user"); + user = session.users().getUserByUsername("user", realm); Assert.assertEquals(1, user.getRequiredActions().size()); Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP)); user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP); - user = realm.getUser("user"); + user = session.users().getUserByUsername("user", realm); Assert.assertEquals(1, user.getRequiredActions().size()); Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP)); user.addRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL); - user = realm.getUser("user"); + user = session.users().getUserByUsername("user", realm); Assert.assertEquals(2, user.getRequiredActions().size()); Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.CONFIGURE_TOTP)); Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL)); user.removeRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP); - user = realm.getUser("user"); + user = session.users().getUserByUsername("user", realm); Assert.assertEquals(1, user.getRequiredActions().size()); Assert.assertTrue(user.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL)); user.removeRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL); - user = realm.getUser("user"); + user = session.users().getUserByUsername("user", realm); Assert.assertTrue(user.getRequiredActions().isEmpty()); } diff --git a/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java b/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java index ef7a1efe89..af9fbed834 100755 --- a/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java +++ b/project-integrations/aerogear-ups/auth-server/src/main/java/org/aerogear/ups/security/UpsSecurityApplication.java @@ -30,8 +30,8 @@ public class UpsSecurityApplication extends KeycloakApplication { try { RealmManager manager = new RealmManager(session); RealmModel master = manager.getKeycloakAdminstrationRealm(); - UserModel admin = master.getUser("admin"); - if (admin != null) master.removeUser(admin.getUsername()); + UserModel admin = session.users().getUserByUsername("admin", master); + if (admin != null) session.users().removeUser(master, admin.getUsername()); session.getTransaction().commit(); } finally { session.close(); diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java index caa0b80aad..be3cf34fc6 100755 --- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java +++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java @@ -7,6 +7,7 @@ import org.keycloak.models.ModelProvider; import org.keycloak.models.UserProvider; import org.keycloak.models.UserSessionProvider; import org.keycloak.models.cache.CacheModelProvider; +import org.keycloak.models.cache.CacheUserProvider; import org.keycloak.provider.Provider; import org.keycloak.provider.ProviderFactory; @@ -24,6 +25,7 @@ public class DefaultKeycloakSession implements KeycloakSession { private final Map providers = new HashMap(); private final DefaultKeycloakTransactionManager transactionManager; private ModelProvider model; + private UserProvider userModel; private UserSessionProvider sessionProvider; public DefaultKeycloakSession(DefaultKeycloakSessionFactory factory) { @@ -39,6 +41,14 @@ public class DefaultKeycloakSession implements KeycloakSession { } } + private UserProvider getUserProvider() { + if (factory.getDefaultProvider(CacheUserProvider.class) != null) { + return getProvider(CacheUserProvider.class); + } else { + return getProvider(UserProvider.class); + } + } + @Override public KeycloakTransactionManager getTransaction() { return transactionManager; @@ -91,6 +101,14 @@ public class DefaultKeycloakSession implements KeycloakSession { return model; } + @Override + public UserProvider users() { + if (userModel == null) { + userModel = getUserProvider(); + } + return userModel; + } + @Override public UserSessionProvider sessions() { if (sessionProvider == null) { diff --git a/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java b/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java index 1f7605fa40..9c556d1c6d 100755 --- a/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java +++ b/services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java @@ -3,6 +3,7 @@ package org.keycloak.services.managers; import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; @@ -26,10 +27,12 @@ import java.util.UUID; public class AccessCodeEntry { protected AccessCode accessCode; protected RealmModel realm; + KeycloakSession keycloakSession; - public AccessCodeEntry(RealmModel realm, AccessCode accessCode) { + public AccessCodeEntry(KeycloakSession keycloakSession, RealmModel realm, AccessCode accessCode) { this.realm = realm; this.accessCode = accessCode; + this.keycloakSession = keycloakSession; } public String getCodeId() { @@ -37,7 +40,7 @@ public class AccessCodeEntry { } public UserModel getUser() { - return realm.getUserById(accessCode.getAccessToken().getSubject()); + return keycloakSession.users().getUserById(accessCode.getAccessToken().getSubject(), realm); } public String getSessionState() { diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java index 56cee64ac2..cf8f35e30b 100755 --- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java +++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java @@ -63,7 +63,7 @@ public class ApplianceBootstrap { realm.setAuditListeners(Collections.singleton("jboss-logging")); - UserModel adminUser = realm.addUser("admin"); + UserModel adminUser = session.users().addUser(realm, "admin"); adminUser.setEnabled(true); UserCredentialModel password = new UserCredentialModel(); password.setType(UserCredentialModel.PASSWORD); diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java index c1798122f0..8ce0a51fc9 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -196,7 +196,7 @@ public class AuthenticationManager { } } - UserModel user = realm.getUserById(token.getSubject()); + UserModel user = session.users().getUserById(token.getSubject(), realm); if (user == null || !user.isEnabled() ) { logger.info("Unknown user in identity token"); return null; @@ -253,12 +253,12 @@ public class AuthenticationManager { } protected AuthenticationStatus authenticateInternal(KeycloakSession session, RealmModel realm, MultivaluedMap formData, String username) { - UserModel user = KeycloakModelUtils.findUserByNameOrEmail(realm, username); + UserModel user = KeycloakModelUtils.findUserByNameOrEmail(session, realm, username); if (user == null) { AuthUser authUser = AuthenticationProviderManager.getManager(realm, session).getUser(username); if (authUser != null) { // Create new user and link him with authentication provider - user = realm.addUser(authUser.getUsername()); + user = session.users().addUser(realm, authUser.getUsername()); user.setEnabled(true); user.setFirstName(authUser.getFirstName()); user.setLastName(authUser.getLastName()); diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index 29cc8b2487..9ab783133c 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -244,6 +244,8 @@ public class RealmManager { } } + + private void setupMasterAdminManagement(RealmModel realm) { RealmModel adminRealm; RoleModel adminRole; @@ -527,7 +529,7 @@ public class RealmManager { public UserModel createUser(RealmModel newRealm, UserRepresentation userRep, Map appMap) { - UserModel user = newRealm.addUser(userRep.getId(), userRep.getUsername(), false); + UserModel user = session.users().addUser(newRealm, userRep.getId(), userRep.getUsername(), false); user.setEnabled(userRep.isEnabled()); user.setEmail(userRep.getEmail()); user.setFirstName(userRep.getFirstName()); @@ -556,7 +558,7 @@ public class RealmManager { if (userRep.getSocialLinks() != null) { for (SocialLinkRepresentation socialLink : userRep.getSocialLinks()) { SocialLinkModel mappingModel = new SocialLinkModel(socialLink.getSocialProvider(), socialLink.getSocialUserId(), socialLink.getSocialUsername()); - newRealm.addSocialLink(user, mappingModel); + session.users().addSocialLink(newRealm, user, mappingModel); } } if (userRep.getRealmRoles() != null) { @@ -603,7 +605,7 @@ public class RealmManager { if (searchString == null) { return Collections.emptyList(); } - return realmModel.searchForUser(searchString.trim()); + return session.users().searchForUser(searchString.trim(), realmModel); } public void addRequiredCredential(RealmModel newRealm, String requiredCred) { diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java index 35a118e018..a47892fd68 100755 --- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java @@ -8,6 +8,7 @@ import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor; import org.keycloak.TokenIdGenerator; import org.keycloak.adapters.AdapterConstants; import org.keycloak.models.ApplicationModel; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.representations.adapters.action.LogoutAction; @@ -34,11 +35,11 @@ import java.util.Map; public class ResourceAdminManager { protected static Logger logger = Logger.getLogger(ResourceAdminManager.class); - public SessionStats getSessionStats(URI requestUri, RealmModel realm, ApplicationModel application, boolean users) { + public SessionStats getSessionStats(URI requestUri, KeycloakSession session, RealmModel realm, ApplicationModel application, boolean users) { ApacheHttpClient4Executor executor = createExecutor(); try { - return getSessionStats(requestUri, realm, application, users, executor); + return getSessionStats(requestUri, session, realm, application, users, executor); } finally { executor.getHttpClient().getConnectionManager().shutdown(); } @@ -52,7 +53,7 @@ public class ResourceAdminManager { return new ApacheHttpClient4Executor(client); } - public SessionStats getSessionStats(URI requestUri, RealmModel realm, ApplicationModel application, boolean users, ApacheHttpClient4Executor client) { + public SessionStats getSessionStats(URI requestUri, KeycloakSession session, RealmModel realm, ApplicationModel application, boolean users, ApacheHttpClient4Executor client) { String managementUrl = getManagementUrl(requestUri, application); if (managementUrl != null) { SessionStatsAction adminAction = new SessionStatsAction(TokenIdGenerator.generateId(), Time.currentTime() + 30, application.getName()); @@ -77,7 +78,7 @@ public class ResourceAdminManager { if (users && stats.getUsers() != null) { Map newUsers = new HashMap(); for (Map.Entry entry : stats.getUsers().entrySet()) { - UserModel user = realm.getUserById(entry.getKey()); + UserModel user = session.users().getUserById(entry.getKey(), realm); if (user == null) continue; newUsers.put(user.getUsername(), entry.getValue()); diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java index 6ab2b754e8..e8e1161040 100755 --- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java +++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java @@ -43,7 +43,7 @@ import java.util.UUID; public class TokenManager { protected static final Logger logger = Logger.getLogger(TokenManager.class); - public AccessCodeEntry parseCode(String code, RealmModel realm) { + public AccessCodeEntry parseCode(String code, KeycloakSession session, RealmModel realm) { try { JWSInput input = new JWSInput(code); if (!RSAProvider.verify(input, realm.getPublicKey())) { @@ -51,7 +51,7 @@ public class TokenManager { return null; } AccessCode accessCode = input.readJsonContent(AccessCode.class); - return new AccessCodeEntry(realm, accessCode); + return new AccessCodeEntry(session, realm, accessCode); } catch (Exception e) { logger.error("error parsing access code", e); return null; @@ -75,11 +75,11 @@ public class TokenManager { - public AccessCodeEntry createAccessCode(String scopeParam, String state, String redirect, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) { - return createAccessCodeEntry(scopeParam, state, redirect, realm, client, user, session); + public AccessCodeEntry createAccessCode(String scopeParam, String state, String redirect, KeycloakSession keycloakSession, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) { + return createAccessCodeEntry(scopeParam, state, redirect, keycloakSession, realm, client, user, session); } - private AccessCodeEntry createAccessCodeEntry(String scopeParam, String state, String redirect, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) { + private AccessCodeEntry createAccessCodeEntry(String scopeParam, String state, String redirect, KeycloakSession keycloakSession, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) { List realmRolesRequested = new LinkedList(); MultivaluedMap resourceRolesRequested = new MultivaluedMapImpl(); @@ -92,7 +92,7 @@ public class TokenManager { code.setExpiration(Time.currentTime() + realm.getAccessCodeLifespan()); code.setState(state); code.setRedirectUri(redirect); - AccessCodeEntry entry = new AccessCodeEntry(realm, code); + AccessCodeEntry entry = new AccessCodeEntry(keycloakSession, realm, code); return entry; } @@ -118,7 +118,7 @@ public class TokenManager { audit.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()); - UserModel user = realm.getUserById(refreshToken.getSubject()); + UserModel user = session.users().getUserById(refreshToken.getSubject(), realm); if (user == null) { throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user"); } diff --git a/services/src/main/java/org/keycloak/services/managers/UserManager.java b/services/src/main/java/org/keycloak/services/managers/UserManager.java old mode 100644 new mode 100755 index 4a18d30357..eb7c98f83d --- a/services/src/main/java/org/keycloak/services/managers/UserManager.java +++ b/services/src/main/java/org/keycloak/services/managers/UserManager.java @@ -17,7 +17,7 @@ public class UserManager { } public boolean removeUser(RealmModel realm, UserModel user) { - if (realm.removeUser(user.getUsername())) { + if (session.users().removeUser(realm, user.getUsername())) { UserSessionProvider sessions = session.sessions(); if (sessions != null) { sessions.onUserRemoved(realm, user); diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java index 68fe12fa68..a71c87ca72 100755 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -516,12 +516,12 @@ public class AccountService { return account.setError(Messages.SOCIAL_REDIRECT_ERROR).createResponse(AccountPages.SOCIAL); } case REMOVE: - SocialLinkModel link = realm.getSocialLink(user, providerId); + SocialLinkModel link = session.users().getSocialLink(user, providerId, realm); if (link != null) { // Removing last social provider is not possible if you don't have other possibility to authenticate - if (realm.getSocialLinks(user).size() > 1 || user.getAuthenticationLink() != null) { - realm.removeSocialLink(user, providerId); + if (session.users().getSocialLinks(user, realm).size() > 1 || user.getAuthenticationLink() != null) { + session.users().removeSocialLink(realm, user, providerId); logger.debug("Social provider " + providerId + " removed successfully from user " + user.getUsername()); diff --git a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java index bfee8dafb8..e66c00094a 100755 --- a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java @@ -226,7 +226,7 @@ public class RequiredActionsService { // Password reset through email won't have an associated session if (accessCode.getSessionState() == null) { - UserSessionModel userSession = session.sessions().createUserSession(realm, realm.getUserById(accessCode.getUser().getId()), clientConnection.getRemoteAddr()); + UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserById(accessCode.getUser().getId(), realm), clientConnection.getRemoteAddr()); accessCode.getToken().setSessionState(userSession.getId()); audit.session(userSession); } @@ -239,7 +239,7 @@ public class RequiredActionsService { @GET public Response emailVerification() { if (uriInfo.getQueryParameters().containsKey("key")) { - AccessCodeEntry accessCode = tokenManager.parseCode(uriInfo.getQueryParameters().getFirst("key"), realm); + AccessCodeEntry accessCode = tokenManager.parseCode(uriInfo.getQueryParameters().getFirst("key"), session, realm); if (accessCode == null || accessCode.isExpired() || !accessCode.hasRequiredAction(RequiredAction.VERIFY_EMAIL)) { return unauthorized(); @@ -275,7 +275,7 @@ public class RequiredActionsService { @GET public Response passwordReset() { if (uriInfo.getQueryParameters().containsKey("key")) { - AccessCodeEntry accessCode = tokenManager.parseCode(uriInfo.getQueryParameters().getFirst("key"), realm); + AccessCodeEntry accessCode = tokenManager.parseCode(uriInfo.getQueryParameters().getFirst("key"), session, realm); accessCode.setAuthMethod("form"); if (accessCode == null || accessCode.isExpired() || !accessCode.hasRequiredAction(RequiredAction.UPDATE_PASSWORD)) { @@ -317,9 +317,9 @@ public class RequiredActionsService { .detail(Details.AUTH_METHOD, "form") .detail(Details.USERNAME, username); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null && username.contains("@")) { - user = realm.getUserByEmail(username); + user = session.users().getUserByEmail(username, realm); } if (user == null) { @@ -329,7 +329,7 @@ public class RequiredActionsService { Set requiredActions = new HashSet(user.getRequiredActions()); requiredActions.add(RequiredAction.UPDATE_PASSWORD); - AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, realm, client, user, null); + AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, session, realm, client, user, null); accessCode.setRequiredActions(requiredActions); accessCode.setAuthMethod("form"); accessCode.setUsernameUsed(username); @@ -360,7 +360,7 @@ public class RequiredActionsService { return null; } - AccessCodeEntry accessCodeEntry = tokenManager.parseCode(code, realm); + AccessCodeEntry accessCodeEntry = tokenManager.parseCode(code, session, realm); if (accessCodeEntry == null) { logger.debug("getAccessCodeEntry access code entry null"); return null; @@ -381,7 +381,7 @@ public class RequiredActionsService { } private UserModel getUser(AccessCodeEntry accessCode) { - return realm.getUser(accessCode.getUser().getUsername()); + return session.users().getUserByUsername(accessCode.getUser().getUsername(), realm); } private Response redirectOauth(UserModel user, AccessCodeEntry accessCode) { diff --git a/services/src/main/java/org/keycloak/services/resources/SocialResource.java b/services/src/main/java/org/keycloak/services/resources/SocialResource.java index 55dae8f42e..2411706883 100755 --- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java +++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java @@ -182,12 +182,12 @@ public class SocialResource { audit.detail(Details.USERNAME, socialUser.getId() + "@" + provider.getId()); SocialLinkModel socialLink = new SocialLinkModel(provider.getId(), socialUser.getId(), socialUser.getUsername()); - UserModel user = realm.getUserBySocialLink(socialLink); + UserModel user = session.users().getUserBySocialLink(socialLink, realm); // Check if user is already authenticated (this means linking social into existing user account) String userId = initialRequest.getUser(); if (userId != null) { - UserModel authenticatedUser = realm.getUserById(userId); + UserModel authenticatedUser = session.users().getUserById(userId, realm); audit.event(EventType.SOCIAL_LINK).user(userId); @@ -211,7 +211,7 @@ public class SocialResource { return oauth.forwardToSecurityFailure("Unknown redirectUri"); } - realm.addSocialLink(authenticatedUser, socialLink); + session.users().addSocialLink(realm, authenticatedUser, socialLink); logger.debug("Social provider " + provider.getId() + " linked with user " + authenticatedUser.getUsername()); audit.success(); @@ -225,7 +225,7 @@ public class SocialResource { return oauth.forwardToSecurityFailure("Registration not allowed"); } - user = realm.addUser(KeycloakModelUtils.generateId()); + user = session.users().addUser(realm, KeycloakModelUtils.generateId()); user.setEnabled(true); user.setFirstName(socialUser.getFirstName()); user.setLastName(socialUser.getLastName()); @@ -235,7 +235,7 @@ public class SocialResource { user.addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE); } - realm.addSocialLink(user, socialLink); + session.users().addSocialLink(realm, user, socialLink); audit.clone().user(user).event(EventType.REGISTER) .detail(Details.REGISTER_METHOD, "social@" + provider.getId()) diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java index 2a373600ff..8aa68ff1d8 100755 --- a/services/src/main/java/org/keycloak/services/resources/TokenService.java +++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java @@ -232,7 +232,7 @@ public class TokenService { } audit.detail(Details.USERNAME, username); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user != null) audit.user(user); ClientModel client = authorizeClient(authorizationHeader, form, audit); @@ -418,7 +418,7 @@ public class TokenService { authManager.expireRememberMeCookie(realm, uriInfo); } - UserModel user = KeycloakModelUtils.findUserByNameOrEmail(realm, username); + UserModel user = KeycloakModelUtils.findUserByNameOrEmail(session, realm, username); if (user != null) { audit.user(user); } @@ -534,12 +534,12 @@ public class TokenService { AuthenticationProviderManager authenticationProviderManager = AuthenticationProviderManager.getManager(realm, session); // Validate that user with this username doesn't exist in realm or any authentication provider - if (realm.getUser(username) != null || authenticationProviderManager.getUser(username) != null) { + if (session.users().getUserByUsername(username, realm) != null || authenticationProviderManager.getUser(username) != null) { audit.error(Errors.USERNAME_IN_USE); return Flows.forms(session, realm, uriInfo).setError(Messages.USERNAME_EXISTS).setFormData(formData).createRegistration(); } - UserModel user = realm.addUser(username); + UserModel user = session.users().addUser(realm, username); user.setEnabled(true); user.setFirstName(formData.getFirst("firstName")); user.setLastName(formData.getFirst("lastName")); @@ -624,7 +624,7 @@ public class TokenService { - AccessCodeEntry accessCode = tokenManager.parseCode(code, realm); + AccessCodeEntry accessCode = tokenManager.parseCode(code, session, realm); if (accessCode == null) { Map res = new HashMap(); res.put(OAuth2Constants.ERROR, "invalid_grant"); @@ -665,7 +665,7 @@ public class TokenService { .build(); } - UserModel user = realm.getUserById(accessCode.getUser().getId()); + UserModel user = session.users().getUserById(accessCode.getUser().getId(), realm); if (user == null) { Map res = new HashMap(); res.put(OAuth2Constants.ERROR, "invalid_grant"); @@ -969,7 +969,7 @@ public class TokenService { String code = formData.getFirst(OAuth2Constants.CODE); - AccessCodeEntry accessCodeEntry = tokenManager.parseCode(code, realm); + AccessCodeEntry accessCodeEntry = tokenManager.parseCode(code, session, realm); if (accessCodeEntry == null) { audit.error(Errors.INVALID_CODE); return oauth.forwardToSecurityFailure("Unknown access code."); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java index 919fcce413..2afdda7c81 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java @@ -301,7 +301,7 @@ public class ApplicationResource { if (users) stats.setUsers(new HashMap()); return stats; } - SessionStats stats = new ResourceAdminManager().getSessionStats(uriInfo.getRequestUri(), realm, application, users); + SessionStats stats = new ResourceAdminManager().getSessionStats(uriInfo.getRequestUri(), session, realm, application, users); if (stats == null) { logger.info("app returned null stats"); } else { @@ -371,7 +371,7 @@ public class ApplicationResource { @POST public void logout(final @PathParam("username") String username) { auth.requireManage(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java index b9243491e8..99d64e8693 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java @@ -260,7 +260,7 @@ public class RealmAdminResource { Map stats = new HashMap(); for (ApplicationModel applicationModel : realm.getApplications()) { if (applicationModel.getManagementUrl() == null) continue; - SessionStats appStats = new ResourceAdminManager().getSessionStats(uriInfo.getRequestUri(), realm, applicationModel, false); + SessionStats appStats = new ResourceAdminManager().getSessionStats(uriInfo.getRequestUri(), this.session, realm, applicationModel, false); stats.put(applicationModel.getName(), appStats); } return stats; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java index e86781d6e7..d9c4e64ac0 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java @@ -99,7 +99,7 @@ public class UsersResource { auth.requireManage(); try { - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -124,7 +124,7 @@ public class UsersResource { auth.requireManage(); try { - UserModel user = realm.addUser(rep.getUsername()); + UserModel user = session.users().addUser(realm, rep.getUsername()); updateUserFromRep(user, rep); return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getUsername()).build()).build(); @@ -174,7 +174,7 @@ public class UsersResource { public UserRepresentation getUser(final @PathParam("username") String username) { auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -197,7 +197,7 @@ public class UsersResource { public Map getSessionStats(final @PathParam("username") String username) { logger.info("session-stats"); auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -224,7 +224,7 @@ public class UsersResource { public List getSessions(final @PathParam("username") String username) { logger.info("sessions"); auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -249,11 +249,11 @@ public class UsersResource { @Produces(MediaType.APPLICATION_JSON) public List getSocialLinks(final @PathParam("username") String username) { auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } - Set socialLinks = realm.getSocialLinks(user); + Set socialLinks = session.users().getSocialLinks(user, realm); List result = new ArrayList(); for (SocialLinkModel socialLink : socialLinks) { SocialLinkRepresentation rep = ModelToRepresentation.toRepresentation(socialLink); @@ -272,7 +272,7 @@ public class UsersResource { @POST public void logout(final @PathParam("username") String username) { auth.requireManage(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -291,7 +291,7 @@ public class UsersResource { public void deleteUser(final @PathParam("username") String username) { auth.requireManage(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -338,12 +338,12 @@ public class UsersResource { if (username != null) { attributes.put(UserModel.LOGIN_NAME, username); } - userModels = realm.searchForUserByAttributes(attributes); + userModels = session.users().searchForUserByAttributes(attributes, realm); for (UserModel user : userModels) { results.add(ModelToRepresentation.toRepresentation(user)); } } else { - userModels = realm.getUsers(); + userModels = session.users().getUsers(realm); } for (UserModel user : userModels) { @@ -365,7 +365,7 @@ public class UsersResource { public MappingsRepresentation getRoleMappings(@PathParam("username") String username) { auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -416,7 +416,7 @@ public class UsersResource { public List getRealmRoleMappings(@PathParam("username") String username) { auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -442,7 +442,7 @@ public class UsersResource { public List getCompositeRealmRoleMappings(@PathParam("username") String username) { auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -470,7 +470,7 @@ public class UsersResource { public List getAvailableRealmRoleMappings(@PathParam("username") String username) { auth.requireView(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -492,7 +492,7 @@ public class UsersResource { auth.requireManage(); logger.debugv("** addRealmRoleMappings: {0}", roles); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -521,7 +521,7 @@ public class UsersResource { auth.requireManage(); logger.debug("deleteRealmRoleMappings"); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -559,7 +559,7 @@ public class UsersResource { logger.debug("getApplicationRoleMappings"); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -595,7 +595,7 @@ public class UsersResource { logger.debug("getCompositeApplicationRoleMappings"); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -631,7 +631,7 @@ public class UsersResource { logger.debug("getApplicationRoleMappings"); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -673,7 +673,7 @@ public class UsersResource { auth.requireManage(); logger.debug("addApplicationRoleMapping"); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -707,7 +707,7 @@ public class UsersResource { public void deleteApplicationRoleMapping(@PathParam("username") String username, @PathParam("app") String appName, List roles) { auth.requireManage(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -752,7 +752,7 @@ public class UsersResource { public void resetPassword(@PathParam("username") String username, CredentialRepresentation pass) { auth.requireManage(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -776,7 +776,7 @@ public class UsersResource { public void removeTotp(@PathParam("username") String username) { auth.requireManage(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -796,7 +796,7 @@ public class UsersResource { public Response resetPasswordEmail(@PathParam("username") String username) { auth.requireManage(); - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); if (user == null) { throw new NotFoundException("User not found"); } @@ -818,7 +818,7 @@ public class UsersResource { Set requiredActions = new HashSet(user.getRequiredActions()); requiredActions.add(UserModel.RequiredAction.UPDATE_PASSWORD); - AccessCodeEntry accessCode = tokenManager.createAccessCode(scope, state, redirect, realm, client, user, null); + AccessCodeEntry accessCode = tokenManager.createAccessCode(scope, state, redirect, session, realm, client, user, null); accessCode.setRequiredActions(requiredActions); accessCode.setUsernameUsed(username); accessCode.resetExpiration(); diff --git a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java index 5027f1996b..c843fbe25d 100755 --- a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java @@ -130,7 +130,7 @@ public class OAuthFlows { isEmailVerificationRequired(user); boolean isResource = client instanceof ApplicationModel; - AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, realm, client, user, session); + AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, this.session, realm, client, user, session); accessCode.setRememberMe(rememberMe); accessCode.setAuthMethod(authMethod); accessCode.setUsernameUsed(username); diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java index 45bb7cc755..4e22fc5f7d 100755 --- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java +++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java @@ -246,7 +246,7 @@ public class KeycloakServer { RealmManager manager = new RealmManager(session); RealmModel adminRealm = manager.getKeycloakAdminstrationRealm(); - UserModel admin = adminRealm.getUser("admin"); + UserModel admin = session.users().getUserByUsername("admin", adminRealm); admin.removeRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD); session.getTransaction().commit(); diff --git a/testsuite/integration/src/main/resources/META-INF/keycloak-server.json b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json index a73908792a..f0c40b2022 100755 --- a/testsuite/integration/src/main/resources/META-INF/keycloak-server.json +++ b/testsuite/integration/src/main/resources/META-INF/keycloak-server.json @@ -11,6 +11,10 @@ "provider": "${keycloak.model.provider:jpa}" }, + "user": { + "provider": "${keycloak.user.provider:jpa}" + }, + "userSessions": { "provider" : "${keycloak.userSessions.provider:mem}" }, diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java index 770ef84838..7c3c3da8d8 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java @@ -76,11 +76,11 @@ public class AccountTest { public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP); - UserModel user2 = appRealm.addUser("test-user-no-access@localhost"); + UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost"); user2.setEnabled(true); for (String r : accountApp.getDefaultRoles()) { user2.deleteRoleMapping(accountApp.getRole(r)); @@ -148,7 +148,7 @@ public class AccountTest { keycloakRule.update(new KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); UserCredentialModel cred = new UserCredentialModel(); cred.setType(CredentialRepresentation.PASSWORD); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java index ad78f4a92b..18ca83899e 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java @@ -48,7 +48,7 @@ public class ProfileTest { public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); user.setFirstName("First"); user.setLastName("Last"); user.setAttribute("key1", "value1"); @@ -56,7 +56,7 @@ public class ProfileTest { ApplicationModel accountApp = appRealm.getApplicationByName(org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_APP); - UserModel user2 = appRealm.addUser("test-user-no-access@localhost"); + UserModel user2 = manager.getSession().users().addUser(appRealm, "test-user-no-access@localhost"); user2.setEnabled(true); for (String r : accountApp.getDefaultRoles()) { user2.deleteRoleMapping(accountApp.getRole(r)); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java index 476cdcc944..9ca52a3a25 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java @@ -94,7 +94,7 @@ public class RequiredActionEmailVerificationTest { public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { appRealm.setVerifyEmail(true); - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); user.setEmailVerified(false); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java index 49f97ed4f8..4f9f7409af 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java @@ -54,7 +54,7 @@ public class RequiredActionMultipleActionsTest { @Override public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); user.addRequiredAction(RequiredAction.UPDATE_PROFILE); user.addRequiredAction(RequiredAction.UPDATE_PASSWORD); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java index d4cc32e153..e357843d87 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java @@ -56,7 +56,7 @@ public class RequiredActionResetPasswordTest { public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { appRealm.setResetPasswordAllowed(true); - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); user.addRequiredAction(RequiredAction.UPDATE_PASSWORD); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java index 056e6fd48a..a5a87c12a4 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java @@ -72,7 +72,7 @@ public class RequiredActionUpdateProfileTest { keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); user.addRequiredAction(UserModel.RequiredAction.UPDATE_PROFILE); } }); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java index f403858750..41e3916582 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java @@ -99,7 +99,7 @@ public class AdapterTest { RealmModel adminRealm = manager.getRealm(Config.getAdminRealm()); ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); TokenManager tm = new TokenManager(); - UserModel admin = adminRealm.getUser("admin"); + UserModel admin = session.users().getUserByUsername("admin", adminRealm); UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null); AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession); return tm.encodeToken(adminRealm, token); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java index ae4d367ab2..f3da0af33a 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java @@ -86,7 +86,7 @@ public class RelativeUriAdapterTest { deployApplication("product-portal", "/product-portal", ProductServlet.class, url.getPath(), "user"); ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); TokenManager tm = new TokenManager(); - UserModel admin = adminRealm.getUser("admin"); + UserModel admin = session.users().getUserByUsername("admin", adminRealm); UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null); AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession); adminToken = tm.encodeToken(adminRealm, token); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java index afd1c2690d..416cc3d348 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java @@ -78,7 +78,7 @@ public class AdminAPITest { RealmModel adminRealm = manager.getRealm(Config.getAdminRealm()); ApplicationModel adminConsole = adminRealm.getApplicationByName(Constants.ADMIN_CONSOLE_APPLICATION); TokenManager tm = new TokenManager(); - UserModel admin = adminRealm.getUser("admin"); + UserModel admin = session.users().getUserByUsername("admin", adminRealm); UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, null); AccessToken token = tm.createClientAccessToken(null, adminRealm, adminConsole, admin, userSession); return tm.encodeToken(adminRealm, token); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java index 5c7bc52279..cf46738b0d 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java @@ -76,12 +76,12 @@ public class CompositeRoleTest { final RoleModel realmComposite1 = realm.addRole("REALM_COMPOSITE_1"); realmComposite1.addCompositeRole(realmRole1); - final UserModel realmComposite1User = realm.addUser("REALM_COMPOSITE_1_USER"); + final UserModel realmComposite1User = session.users().addUser(realm, "REALM_COMPOSITE_1_USER"); realmComposite1User.setEnabled(true); realmComposite1User.updateCredential(UserCredentialModel.password("password")); realmComposite1User.grantRole(realmComposite1); - final UserModel realmRole1User = realm.addUser("REALM_ROLE_1_USER"); + final UserModel realmRole1User = session.users().addUser(realm, "REALM_ROLE_1_USER"); realmRole1User.setEnabled(true); realmRole1User.updateCredential(UserCredentialModel.password("password")); realmRole1User.grantRole(realmRole1); @@ -115,12 +115,12 @@ public class CompositeRoleTest { final RoleModel realmAppCompositeRole = realm.addRole("REALM_APP_COMPOSITE_ROLE"); realmAppCompositeRole.addCompositeRole(appRole1); - final UserModel realmAppCompositeUser = realm.addUser("REALM_APP_COMPOSITE_USER"); + final UserModel realmAppCompositeUser = session.users().addUser(realm, "REALM_APP_COMPOSITE_USER"); realmAppCompositeUser.setEnabled(true); realmAppCompositeUser.updateCredential(UserCredentialModel.password("password")); realmAppCompositeUser.grantRole(realmAppCompositeRole); - final UserModel realmAppRoleUser = realm.addUser("REALM_APP_ROLE_USER"); + final UserModel realmAppRoleUser = session.users().addUser(realm, "REALM_APP_ROLE_USER"); realmAppRoleUser.setEnabled(true); realmAppRoleUser.updateCredential(UserCredentialModel.password("password")); realmAppRoleUser.grantRole(appRole2); @@ -138,7 +138,7 @@ public class CompositeRoleTest { appCompositeRole.addCompositeRole(realmRole3); appCompositeRole.addCompositeRole(appRole1); - final UserModel appCompositeUser = realm.addUser("APP_COMPOSITE_USER"); + final UserModel appCompositeUser = session.users().addUser(realm, "APP_COMPOSITE_USER"); appCompositeUser.setEnabled(true); appCompositeUser.updateCredential(UserCredentialModel.password("password")); appCompositeUser.grantRole(realmAppCompositeRole); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java index e47c714320..ede84bf74a 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/AuthProvidersIntegrationTest.java @@ -11,6 +11,7 @@ import org.junit.runners.MethodSorters; import org.keycloak.OAuth2Constants; import org.keycloak.model.test.LDAPTestUtils; import org.keycloak.models.AuthenticationProviderModel; +import org.keycloak.models.KeycloakSession; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; @@ -47,8 +48,8 @@ public class AuthProvidersIntegrationTest { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - addUser(appRealm, "mary", "mary@test.com", "password-app"); - addUser(adminstrationRealm, "mary-admin", "mary@admin.com", "password-admin"); + addUser(manager.getSession(), appRealm, "mary", "mary@test.com", "password-app"); + addUser(manager.getSession(), adminstrationRealm, "mary-admin", "mary@admin.com", "password-admin"); AuthenticationProviderModel modelProvider = new AuthenticationProviderModel(AuthProviderConstants.PROVIDER_NAME_MODEL, false, Collections.EMPTY_MAP); AuthenticationProviderModel picketlinkProvider = new AuthenticationProviderModel(AuthProviderConstants.PROVIDER_NAME_PICKETLINK, true, Collections.EMPTY_MAP); @@ -95,8 +96,8 @@ public class AuthProvidersIntegrationTest { @WebResource protected AccountPasswordPage changePasswordPage; - private static UserModel addUser(RealmModel realm, String username, String email, String password) { - UserModel user = realm.addUser(username); + private static UserModel addUser(KeycloakSession session, RealmModel realm, String username, String email, String password) { + UserModel user = session.users().addUser(realm, username); user.setEmail(email); user.setEnabled(true); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java index 277bc7a64b..ad0a4c1075 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java @@ -51,7 +51,7 @@ public class LoginTest { public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = appRealm.addUser("login-test"); + UserModel user = manager.getSession().users().addUser(appRealm, "login-test"); user.setEmail("login@test.com"); user.setEnabled(true); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java index eadf367337..9575f462a7 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java @@ -58,7 +58,7 @@ public class LoginTotpTest { @Override public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { - UserModel user = appRealm.getUser("test-user@localhost"); + UserModel user = manager.getSession().users().getUserByUsername("test-user@localhost", appRealm); UserCredentialModel credentials = new UserCredentialModel(); credentials.setType(CredentialRepresentation.TOTP); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java index de74d0a041..2bf82173ce 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java @@ -62,7 +62,7 @@ public class ResetPasswordTest { public static KeycloakRule keycloakRule = new KeycloakRule((new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - UserModel user = appRealm.addUser("login-test"); + UserModel user = manager.getSession().users().addUser(appRealm, "login-test"); user.setEmail("login@test.com"); user.setEnabled(true); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java old mode 100644 new mode 100755 index cb58949071..6219764816 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java @@ -37,16 +37,16 @@ public class UserSessionProviderTest { public void before() { session = kc.startSession(); realm = session.model().getRealm("test"); - realm.addUser("user1"); - realm.addUser("user2"); + session.users().addUser(realm, "user1"); + session.users().addUser(realm, "user2"); } @After public void after() { resetSession(); session.sessions().removeUserSessions(realm); - realm.removeUser("user1"); - realm.removeUser("user2"); + session.users().removeUser(realm, "user1"); + session.users().removeUser(realm, "user2"); kc.stopSession(session, true); } @@ -55,27 +55,27 @@ public class UserSessionProviderTest { int started = Time.currentTime(); UserSessionModel[] sessions = createSessions(); - assertSession(session.sessions().getUserSession(realm, sessions[0].getId()), realm.getUser("user1"), "127.0.0.1", started, started, "test-app", "third-party"); - assertSession(session.sessions().getUserSession(realm, sessions[1].getId()), realm.getUser("user1"), "127.0.0.2", started, started, "test-app"); - assertSession(session.sessions().getUserSession(realm, sessions[2].getId()), realm.getUser("user2"), "127.0.0.3", started, started); + assertSession(session.sessions().getUserSession(realm, sessions[0].getId()), session.users().getUserByUsername("user1", realm), "127.0.0.1", started, started, "test-app", "third-party"); + assertSession(session.sessions().getUserSession(realm, sessions[1].getId()), session.users().getUserByUsername("user1", realm), "127.0.0.2", started, started, "test-app"); + assertSession(session.sessions().getUserSession(realm, sessions[2].getId()), session.users().getUserByUsername("user2", realm), "127.0.0.3", started, started); } @Test public void testGetUserSessions() { UserSessionModel[] sessions = createSessions(); - assertSessions(session.sessions().getUserSessions(realm, realm.getUser("user1")), sessions[0], sessions[1]); - assertSessions(session.sessions().getUserSessions(realm, realm.getUser("user2")), sessions[2]); + assertSessions(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)), sessions[0], sessions[1]); + assertSessions(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)), sessions[2]); } @Test public void testRemoveUserSessionsByUser() { createSessions(); - session.sessions().removeUserSessions(realm, realm.getUser("user1")); + session.sessions().removeUserSessions(realm, session.users().getUserByUsername("user1", realm)); resetSession(); - assertTrue(session.sessions().getUserSessions(realm, realm.getUser("user1")).isEmpty()); - assertFalse(session.sessions().getUserSessions(realm, realm.getUser("user2")).isEmpty()); + assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)).isEmpty()); + assertFalse(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty()); } @Test @@ -84,8 +84,8 @@ public class UserSessionProviderTest { session.sessions().removeUserSessions(realm); resetSession(); - assertTrue(session.sessions().getUserSessions(realm, realm.getUser("user1")).isEmpty()); - assertTrue(session.sessions().getUserSessions(realm, realm.getUser("user2")).isEmpty()); + assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user1", realm)).isEmpty()); + assertTrue(session.sessions().getUserSessions(realm, session.users().getUserByUsername("user2", realm)).isEmpty()); } @Test @@ -116,7 +116,7 @@ public class UserSessionProviderTest { @Test public void testGetByClientPaginated() { for (int i = 0; i < 25; i++) { - UserSessionModel userSession = session.sessions().createUserSession(realm, realm.getUser("user1"), "127.0.0." + i); + UserSessionModel userSession = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "127.0.0." + i); userSession.setStarted(Time.currentTime() + i); userSession.associateClient(realm.findClient("test-app")); } @@ -157,14 +157,14 @@ public class UserSessionProviderTest { private UserSessionModel[] createSessions() { UserSessionModel[] sessions = new UserSessionModel[4]; - sessions[0] = session.sessions().createUserSession(realm, realm.getUser("user1"), "127.0.0.1"); + sessions[0] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "127.0.0.1"); sessions[0].associateClient(realm.findClient("test-app")); sessions[0].associateClient(realm.findClient("third-party")); - sessions[1] = session.sessions().createUserSession(realm, realm.getUser("user1"), "127.0.0.2"); + sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "127.0.0.2"); sessions[1].associateClient(realm.findClient("test-app")); - sessions[2] = session.sessions().createUserSession(realm, realm.getUser("user2"), "127.0.0.3"); + sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "127.0.0.3"); resetSession(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java index 0ba9ed3048..eac0cee606 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java @@ -40,7 +40,8 @@ public abstract class AbstractKeycloakRule extends ExternalResource { KeycloakSession session = server.getSessionFactory().create(); session.getTransaction().begin(); try { - UserModel user = session.model().getRealmByName(realm).getUser(name); + RealmModel realmByName = session.model().getRealmByName(realm); + UserModel user = session.users().getUserByUsername(name, realmByName); return user != null ? ModelToRepresentation.toRepresentation(user) : null; } finally { session.close(); @@ -51,7 +52,8 @@ public abstract class AbstractKeycloakRule extends ExternalResource { KeycloakSession session = server.getSessionFactory().create(); session.getTransaction().begin(); try { - return ModelToRepresentation.toRepresentation(session.model().getRealmByName(realm).getUserById(id)); + RealmModel realmByName = session.model().getRealmByName(realm); + return ModelToRepresentation.toRepresentation(session.users().getUserById(id, realmByName)); } finally { session.close(); } diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java index 12f600c5b9..c9ca90ebf2 100755 --- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java +++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/CreateUsersWorker.java @@ -68,7 +68,7 @@ public class CreateUsersWorker implements Worker { String username = PerfTestUtils.getUsername(userNumber); - UserModel user = realm.addUser(username); + UserModel user = session.users().addUser(realm, username); // Add basic user attributes (NOTE: Actually backend is automatically upgraded during each setter call) if (addBasicUserAttributes) { @@ -97,7 +97,7 @@ public class CreateUsersWorker implements Worker { } SocialLinkModel socialLink = new SocialLinkModel(socialProvider, username, username); - realm.addSocialLink(user, socialLink); + session.users().addSocialLink(realm, user, socialLink); } log.info("Finished creation of user " + username + " in realm: " + realm.getId()); diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java index 05d47c625c..53c324275a 100755 --- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java +++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/ReadUsersWorker.java @@ -86,7 +86,7 @@ public class ReadUsersWorker implements Worker { String username = PerfTestUtils.getUsername(userCounterInRealm); lastUsername = username; - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); // Read roles of user in realm if (readRoles) { @@ -106,13 +106,13 @@ public class ReadUsersWorker implements Worker { // Read socialLinks of user if (readSocialLinks) { - realm.getSocialLinks(user); + session.users().getSocialLinks(user, realm); } // Try to search by social links if (searchBySocialLinks) { SocialLinkModel socialLink = new SocialLinkModel("facebook", username, username); - realm.getUserBySocialLink(socialLink); + session.users().getUserBySocialLink(socialLink, realm); } } diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java old mode 100644 new mode 100755 index 4b89245ecb..ab5735ae32 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/PerfTools.java @@ -174,9 +174,9 @@ public class PerfTools { // TODO: method for count on model if (prefix == null) { - return realm.getUsers().size(); + return session.users().getUsers(realm).size(); } else { - return realm.searchForUser(prefix).size(); + return session.users().searchForUser(prefix, realm).size(); } } diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java old mode 100644 new mode 100755 index b00f08fbf2..32599b5f16 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/CreateUsersJob.java @@ -28,9 +28,9 @@ public class CreateUsersJob extends UsersJob { } @Override - protected void runIteration(RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { + protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { String username = prefix + "-" + counter; - UserModel user = realm.addUser(username); + UserModel user = session.users().addUser(realm, username); user.setEnabled(true); user.setFirstName("First"); user.setLastName("Last"); diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java old mode 100644 new mode 100755 index 0f98cb4b93..b215e89958 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/DeleteUsersJob.java @@ -24,15 +24,15 @@ public class DeleteUsersJob extends UsersJob { RealmModel realm = new RealmManager(session).getRealmByName(realmName); // TODO: pagination - List users = (prefix==null) ? realm.getUsers() : realm.searchForUser(prefix); + List users = (prefix==null) ? session.users().getUsers(realm) : session.users().searchForUser(prefix, realm); users = users.subList(start, start + count); this.users = users.iterator(); } @Override - protected void runIteration(RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { + protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { String username = users.next().getUsername(); - realm.removeUser(username); + session.users().removeUser(realm, username); } } diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java old mode 100644 new mode 100755 index d0a1af99b4..37e61a5b07 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UpdateUsersJob.java @@ -29,18 +29,18 @@ public class UpdateUsersJob extends UsersJob { RealmModel realm = new RealmManager(session).getRealmByName(realmName); // TODO: pagination - List users = (prefix==null) ? realm.getUsers() : realm.searchForUser(prefix); + List users = (prefix==null) ? session.users().getUsers(realm) : session.users().searchForUser(prefix, realm); users = users.subList(start, start + count); this.users = users.iterator(); } @Override - protected void runIteration(RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { + protected void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter) { String username = users.next().getUsername(); // Remove all role mappings first - UserModel user = realm.getUser(username); + UserModel user = session.users().getUserByUsername(username, realm); Set currRoles = user.getRoleMappings(); for (RoleModel role : currRoles) { user.deleteRoleMapping(role); diff --git a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java old mode 100644 new mode 100755 index efc598ab55..5b7fc55288 --- a/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java +++ b/testsuite/tools/src/main/java/org/keycloak/test/tools/jobs/UsersJob.java @@ -70,7 +70,7 @@ public abstract class UsersJob implements Runnable { } for (int i = start; i < (start + count); i++) { - runIteration(realm, apps, realmRoles, appRoles, i); + runIteration(session, realm, apps, realmRoles, appRoles, i); job.increment(); } @@ -86,7 +86,7 @@ public abstract class UsersJob implements Runnable { protected abstract void before(KeycloakSession keycloakSession); - protected abstract void runIteration(RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter); + protected abstract void runIteration(KeycloakSession session, RealmModel realm, Map apps, Set realmRoles, Map> appRoles, int counter); protected RoleModel findRole(Set roles, String roleName) { for (RoleModel role : roles) {