commit
e4b3007ce2
213 changed files with 2101 additions and 2043 deletions
8
audit/email/src/main/java/org/keycloak/audit/email/EmailAuditListener.java
Normal file → Executable file
8
audit/email/src/main/java/org/keycloak/audit/email/EmailAuditListener.java
Normal file → Executable file
|
@ -7,7 +7,7 @@ import org.keycloak.audit.EventType;
|
|||
import org.keycloak.email.EmailException;
|
||||
import org.keycloak.email.EmailProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
|
@ -21,13 +21,13 @@ public class EmailAuditListener implements AuditListener {
|
|||
private static final Logger log = Logger.getLogger(EmailAuditListener.class);
|
||||
|
||||
private KeycloakSession session;
|
||||
private ModelProvider model;
|
||||
private RealmProvider model;
|
||||
private EmailProvider emailProvider;
|
||||
private Set<EventType> includedEvents;
|
||||
|
||||
public EmailAuditListener(KeycloakSession session, EmailProvider emailProvider, Set<EventType> includedEvents) {
|
||||
this.session = session;
|
||||
this.model = session.model();
|
||||
this.model = session.realms();
|
||||
this.emailProvider = emailProvider;
|
||||
this.includedEvents = includedEvents;
|
||||
}
|
||||
|
@ -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);
|
||||
|
|
|
@ -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<String, String> 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<String, String> 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<String, String> 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;
|
||||
|
|
6
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProvider.java
Normal file → Executable file
6
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ExternalModelAuthenticationProvider.java
Normal file → Executable file
|
@ -3,7 +3,6 @@ package org.keycloak.authentication.model;
|
|||
import org.keycloak.authentication.AuthProviderConstants;
|
||||
import org.keycloak.authentication.AuthenticationProviderException;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -17,10 +16,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 +38,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.realms().getRealm(realmId);
|
||||
if (realm == null) {
|
||||
throw new AuthenticationProviderException("Realm with id '" + realmId + "' doesn't exists");
|
||||
}
|
||||
|
|
5
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProvider.java
Normal file → Executable file
5
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProvider.java
Normal file → Executable file
|
@ -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;
|
||||
|
|
2
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java
Normal file → Executable file
2
authentication/authentication-model/src/main/java/org/keycloak/authentication/model/ModelAuthenticationProviderFactory.java
Normal file → Executable file
|
@ -13,7 +13,7 @@ public class ModelAuthenticationProviderFactory implements AuthenticationProvide
|
|||
|
||||
@Override
|
||||
public AuthenticationProvider create(KeycloakSession session) {
|
||||
return new ModelAuthenticationProvider();
|
||||
return new ModelAuthenticationProvider(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
15
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
Normal file → Executable file
15
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ExportUtils.java
Normal file → Executable file
|
@ -22,6 +22,7 @@ import org.keycloak.exportimport.Strategy;
|
|||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.AuthenticationLinkModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OAuthClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
|
@ -47,7 +48,7 @@ import org.keycloak.representations.idm.UserRepresentation;
|
|||
*/
|
||||
public class ExportUtils {
|
||||
|
||||
public static RealmRepresentation exportRealm(RealmModel realm, boolean includeUsers) {
|
||||
public static RealmRepresentation exportRealm(KeycloakSession session, RealmModel realm, boolean includeUsers) {
|
||||
RealmRepresentation rep = ModelToRepresentation.toRepresentation(realm);
|
||||
|
||||
// Audit
|
||||
|
@ -147,10 +148,10 @@ public class ExportUtils {
|
|||
|
||||
// Finally users if needed
|
||||
if (includeUsers) {
|
||||
List<UserModel> allUsers = realm.getUsers();
|
||||
List<UserModel> allUsers = session.users().getUsers(realm);
|
||||
List<UserRepresentation> users = new ArrayList<UserRepresentation>();
|
||||
for (UserModel user : allUsers) {
|
||||
UserRepresentation userRep = exportUser(realm, user);
|
||||
UserRepresentation userRep = exportUser(session, realm, user);
|
||||
users.add(userRep);
|
||||
}
|
||||
|
||||
|
@ -251,7 +252,7 @@ public class ExportUtils {
|
|||
* @param user
|
||||
* @return fully exported user representation
|
||||
*/
|
||||
public static UserRepresentation exportUser(RealmModel realm, UserModel user) {
|
||||
public static UserRepresentation exportUser(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
UserRepresentation userRep = ModelToRepresentation.toRepresentation(user);
|
||||
|
||||
// AuthenticationLink
|
||||
|
@ -262,7 +263,7 @@ public class ExportUtils {
|
|||
}
|
||||
|
||||
// Social links
|
||||
Set<SocialLinkModel> socialLinks = realm.getSocialLinks(user);
|
||||
Set<SocialLinkModel> socialLinks = session.users().getSocialLinks(user, realm);
|
||||
List<SocialLinkRepresentation> socialLinkReps = new ArrayList<SocialLinkRepresentation>();
|
||||
for (SocialLinkModel socialLink : socialLinks) {
|
||||
SocialLinkRepresentation socialLinkRep = exportSocialLink(socialLink);
|
||||
|
@ -338,7 +339,7 @@ public class ExportUtils {
|
|||
|
||||
// Streaming API
|
||||
|
||||
public static void exportUsersToStream(RealmModel realm, List<UserModel> usersToExport, ObjectMapper mapper, OutputStream os) throws IOException {
|
||||
public static void exportUsersToStream(KeycloakSession session, RealmModel realm, List<UserModel> usersToExport, ObjectMapper mapper, OutputStream os) throws IOException {
|
||||
JsonFactory factory = mapper.getJsonFactory();
|
||||
JsonGenerator generator = factory.createJsonGenerator(os, JsonEncoding.UTF8);
|
||||
try {
|
||||
|
@ -352,7 +353,7 @@ public class ExportUtils {
|
|||
generator.writeStartArray();
|
||||
|
||||
for (UserModel user : usersToExport) {
|
||||
UserRepresentation userRep = ExportUtils.exportUser(realm, user);
|
||||
UserRepresentation userRep = ExportUtils.exportUser(session, realm, user);
|
||||
generator.writeObject(userRep);
|
||||
}
|
||||
|
||||
|
|
23
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
Normal file → Executable file
23
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
Normal file → Executable file
|
@ -2,17 +2,13 @@ package org.keycloak.exportimport.util;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codehaus.jackson.JsonEncoding;
|
||||
import org.codehaus.jackson.JsonFactory;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.JsonParser;
|
||||
import org.codehaus.jackson.JsonToken;
|
||||
import org.codehaus.jackson.io.SerializedString;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
|
@ -20,10 +16,9 @@ import org.keycloak.exportimport.Strategy;
|
|||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -46,7 +41,7 @@ public class ImportUtils {
|
|||
*/
|
||||
public static RealmModel importRealm(KeycloakSession session, RealmRepresentation rep, Strategy strategy) {
|
||||
String realmName = rep.getRealm();
|
||||
ModelProvider model = session.model();
|
||||
RealmProvider model = session.realms();
|
||||
RealmModel realm = model.getRealmByName(realmName);
|
||||
|
||||
if (realm != null) {
|
||||
|
@ -64,7 +59,7 @@ public class ImportUtils {
|
|||
|
||||
realm = rep.getId() != null ? model.createRealm(rep.getId(), realmName) : model.createRealm(realmName);
|
||||
|
||||
RepresentationToModel.importRealm(rep, realm);
|
||||
RepresentationToModel.importRealm(session, rep, realm);
|
||||
|
||||
refreshMasterAdminApps(model, realm);
|
||||
|
||||
|
@ -72,7 +67,7 @@ public class ImportUtils {
|
|||
return realm;
|
||||
}
|
||||
|
||||
private static void refreshMasterAdminApps(ModelProvider model, RealmModel realm) {
|
||||
private static void refreshMasterAdminApps(RealmProvider model, RealmModel realm) {
|
||||
String adminRealmId = Config.getAdminRealm();
|
||||
if (adminRealmId.equals(realm.getId())) {
|
||||
// We just imported master realm. All 'masterAdminApps' need to be refreshed
|
||||
|
@ -98,7 +93,7 @@ public class ImportUtils {
|
|||
}
|
||||
|
||||
// TODO: We need method here, so we are able to refresh masterAdmin applications after import. Should be RealmManager moved to model/api instead?
|
||||
public static void setupMasterAdminManagement(ModelProvider model, RealmModel realm) {
|
||||
public static void setupMasterAdminManagement(RealmProvider model, RealmModel realm) {
|
||||
RealmModel adminRealm;
|
||||
RoleModel adminRole;
|
||||
|
||||
|
@ -160,7 +155,7 @@ public class ImportUtils {
|
|||
|
||||
// Assuming that it's invoked inside transaction
|
||||
public static void importUsersFromStream(KeycloakSession session, String realmName, ObjectMapper mapper, InputStream is) throws IOException {
|
||||
ModelProvider model = session.model();
|
||||
RealmProvider model = session.realms();
|
||||
JsonFactory factory = mapper.getJsonFactory();
|
||||
JsonParser parser = factory.createJsonParser(is);
|
||||
try {
|
||||
|
@ -188,7 +183,7 @@ public class ImportUtils {
|
|||
parser.nextToken();
|
||||
}
|
||||
|
||||
importUsers(model, realmName, userReps);
|
||||
importUsers(session, model, realmName, userReps);
|
||||
|
||||
if (parser.getCurrentToken() == JsonToken.END_ARRAY) {
|
||||
parser.nextToken();
|
||||
|
@ -200,11 +195,11 @@ public class ImportUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static void importUsers(ModelProvider model, String realmName, List<UserRepresentation> userReps) {
|
||||
private static void importUsers(KeycloakSession session, RealmProvider model, String realmName, List<UserRepresentation> userReps) {
|
||||
RealmModel realm = model.getRealmByName(realmName);
|
||||
Map<String, ApplicationModel> apps = realm.getApplicationNameMap();
|
||||
for (UserRepresentation user : userReps) {
|
||||
RepresentationToModel.createUser(realm, user, apps);
|
||||
RepresentationToModel.createUser(session, realm, user, apps);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java
Normal file → Executable file
16
export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/MultipleStepsExportProvider.java
Normal file → Executable file
|
@ -28,7 +28,7 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
|
|||
|
||||
@Override
|
||||
public void run(KeycloakSession session) {
|
||||
List<RealmModel> realms = session.model().getRealms();
|
||||
List<RealmModel> realms = session.realms().getRealms();
|
||||
holder.realms = realms;
|
||||
}
|
||||
|
||||
|
@ -49,15 +49,15 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
|
|||
|
||||
@Override
|
||||
public void run(KeycloakSession session) throws IOException {
|
||||
RealmModel realm = session.model().getRealmByName(realmName);
|
||||
RealmRepresentation rep = ExportUtils.exportRealm(realm, exportUsersIntoSameFile);
|
||||
RealmModel realm = session.realms().getRealmByName(realmName);
|
||||
RealmRepresentation rep = ExportUtils.exportRealm(session, realm, exportUsersIntoSameFile);
|
||||
writeRealm(realmName + "-realm.json", rep);
|
||||
logger.info("Realm '" + realmName + "' - data exported");
|
||||
|
||||
// Count total number of users
|
||||
if (!exportUsersIntoSameFile) {
|
||||
// TODO: getUsersCount method on model
|
||||
usersHolder.totalCount = realm.getUsers().size();
|
||||
usersHolder.totalCount = session.users().getUsers(realm).size();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,12 +81,12 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
|
|||
|
||||
@Override
|
||||
public void run(KeycloakSession session) throws IOException {
|
||||
RealmModel realm = session.model().getRealmByName(realmName);
|
||||
RealmModel realm = session.realms().getRealmByName(realmName);
|
||||
// TODO: pagination
|
||||
List<UserModel> users = realm.getUsers();
|
||||
List<UserModel> users = session.users().getUsers(realm);
|
||||
usersHolder.users = users.subList(usersHolder.currentPageStart, usersHolder.currentPageEnd);
|
||||
|
||||
writeUsers(realmName + "-users-" + (usersHolder.currentPageStart / countPerPage) + ".json", realm, usersHolder.users);
|
||||
writeUsers(realmName + "-users-" + (usersHolder.currentPageStart / countPerPage) + ".json", session, realm, usersHolder.users);
|
||||
|
||||
logger.info("Users " + usersHolder.currentPageStart + "-" + usersHolder.currentPageEnd + " exported");
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
|
|||
|
||||
protected abstract void writeRealm(String fileName, RealmRepresentation rep) throws IOException;
|
||||
|
||||
protected abstract void writeUsers(String fileName, RealmModel realm, List<UserModel> users) throws IOException;
|
||||
protected abstract void writeUsers(String fileName, KeycloakSession session, RealmModel realm, List<UserModel> users) throws IOException;
|
||||
|
||||
public static class RealmsHolder {
|
||||
List<RealmModel> realms;
|
||||
|
|
5
export-import/export-import-dir/src/main/java/org/keycloak/exportimport/dir/DirExportProvider.java
Normal file → Executable file
5
export-import/export-import-dir/src/main/java/org/keycloak/exportimport/dir/DirExportProvider.java
Normal file → Executable file
|
@ -7,6 +7,7 @@ import java.util.List;
|
|||
|
||||
import org.keycloak.exportimport.util.ExportUtils;
|
||||
import org.keycloak.exportimport.util.MultipleStepsExportProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -61,10 +62,10 @@ public class DirExportProvider extends MultipleStepsExportProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void writeUsers(String fileName, RealmModel realm, List<UserModel> users) throws IOException {
|
||||
protected void writeUsers(String fileName, KeycloakSession session, RealmModel realm, List<UserModel> users) throws IOException {
|
||||
File file = new File(this.rootDirectory, fileName);
|
||||
FileOutputStream os = new FileOutputStream(file);
|
||||
ExportUtils.exportUsersToStream(realm, users, JsonSerialization.prettyMapper, os);
|
||||
ExportUtils.exportUsersToStream(session, realm, users, JsonSerialization.prettyMapper, os);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
8
export-import/export-import-single-file/src/main/java/org/keycloak/exportimport/singlefile/SingleFileExportProvider.java
Normal file → Executable file
8
export-import/export-import-single-file/src/main/java/org/keycloak/exportimport/singlefile/SingleFileExportProvider.java
Normal file → Executable file
|
@ -42,10 +42,10 @@ public class SingleFileExportProvider implements ExportProvider {
|
|||
|
||||
@Override
|
||||
public void run(KeycloakSession session) throws IOException {
|
||||
List<RealmModel> realms = session.model().getRealms();
|
||||
List<RealmModel> realms = session.realms().getRealms();
|
||||
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
|
||||
for (RealmModel realm : realms) {
|
||||
reps.add(ExportUtils.exportRealm(realm, true));
|
||||
reps.add(ExportUtils.exportRealm(session, realm, true));
|
||||
}
|
||||
|
||||
writeToFile(reps);
|
||||
|
@ -62,8 +62,8 @@ public class SingleFileExportProvider implements ExportProvider {
|
|||
|
||||
@Override
|
||||
public void run(KeycloakSession session) throws IOException {
|
||||
RealmModel realm = session.model().getRealmByName(realmName);
|
||||
RealmRepresentation realmRep = ExportUtils.exportRealm(realm, true);
|
||||
RealmModel realm = session.realms().getRealmByName(realmName);
|
||||
RealmRepresentation realmRep = ExportUtils.exportRealm(session, realm, true);
|
||||
writeToFile(realmRep);
|
||||
}
|
||||
|
||||
|
|
5
export-import/export-import-zip/src/main/java/org/keycloak/exportimport/zip/ZipExportProvider.java
Normal file → Executable file
5
export-import/export-import-zip/src/main/java/org/keycloak/exportimport/zip/ZipExportProvider.java
Normal file → Executable file
|
@ -12,6 +12,7 @@ import de.idyl.winzipaes.impl.AESEncrypterBC;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.exportimport.util.ExportUtils;
|
||||
import org.keycloak.exportimport.util.MultipleStepsExportProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -53,9 +54,9 @@ public class ZipExportProvider extends MultipleStepsExportProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void writeUsers(String fileName, RealmModel realm, List<UserModel> users) throws IOException {
|
||||
protected void writeUsers(String fileName, KeycloakSession session, RealmModel realm, List<UserModel> users) throws IOException {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
ExportUtils.exportUsersToStream(realm, users, JsonSerialization.mapper, stream);
|
||||
ExportUtils.exportUsersToStream(session, realm, users, JsonSerialization.mapper, stream);
|
||||
|
||||
byte[] byteArray = stream.toByteArray();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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<SocialLinkEntry> 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<SocialLinkEntry>();
|
||||
|
||||
Map<String, String> socialConfig = realm.getSocialConfig();
|
||||
Set<SocialLinkModel> userSocialLinks = realm.getSocialLinks(user);
|
||||
Set<SocialLinkModel> userSocialLinks = session.users().getSocialLinks(user, realm);
|
||||
|
||||
int availableLinks = 0;
|
||||
if (socialConfig != null && !socialConfig.isEmpty()) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,8 +2,6 @@ package org.keycloak.models;
|
|||
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +27,7 @@ public interface KeycloakSession {
|
|||
* @return
|
||||
* @throws IllegalStateException if transaction is not active
|
||||
*/
|
||||
ModelProvider model();
|
||||
RealmProvider realms();
|
||||
|
||||
/**
|
||||
* Returns a managed provider instance. Will start a provider transaction. This transaction is managed by the KeycloakSession
|
||||
|
@ -42,4 +40,5 @@ public interface KeycloakSession {
|
|||
|
||||
void close();
|
||||
|
||||
UserProvider users();
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ModelProvider extends Provider {
|
||||
// Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
|
||||
|
||||
RealmModel createRealm(String name);
|
||||
RealmModel createRealm(String id, String name);
|
||||
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<UserModel> getUsers(RealmModel realm);
|
||||
List<UserModel> searchForUser(String search, RealmModel realm);
|
||||
List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
|
||||
|
||||
Set<SocialLinkModel> 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);
|
||||
List<RealmModel> getRealms();
|
||||
boolean removeRealm(String id);
|
||||
|
||||
void close();
|
||||
}
|
|
@ -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<String> getDefaultRoles();
|
||||
|
@ -147,16 +135,6 @@ public interface RealmModel extends RoleContainerModel {
|
|||
|
||||
void updateRequiredCredentials(Set<String> creds);
|
||||
|
||||
UserModel getUserBySocialLink(SocialLinkModel socialLink);
|
||||
|
||||
Set<SocialLinkModel> 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<UserModel> getUsers();
|
||||
|
||||
List<UserModel> searchForUser(String search);
|
||||
|
||||
List<UserModel> searchForUserByAttributes(Map<String, String> attributes);
|
||||
|
||||
OAuthClientModel addOAuthClient(String name);
|
||||
|
||||
OAuthClientModel addOAuthClient(String id, String name);
|
||||
|
|
26
model/api/src/main/java/org/keycloak/models/RealmProvider.java
Executable file
26
model/api/src/main/java/org/keycloak/models/RealmProvider.java
Executable file
|
@ -0,0 +1,26 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface RealmProvider extends Provider {
|
||||
// Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
|
||||
|
||||
RealmModel createRealm(String name);
|
||||
RealmModel createRealm(String id, String name);
|
||||
RealmModel getRealm(String id);
|
||||
RealmModel getRealmByName(String name);
|
||||
|
||||
RoleModel getRoleById(String id, RealmModel realm);
|
||||
ApplicationModel getApplicationById(String id, RealmModel realm);
|
||||
OAuthClientModel getOAuthClientById(String id, RealmModel realm);
|
||||
List<RealmModel> getRealms();
|
||||
boolean removeRealm(String id);
|
||||
|
||||
void close();
|
||||
}
|
|
@ -6,5 +6,5 @@ import org.keycloak.provider.ProviderFactory;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ModelProviderFactory extends ProviderFactory<ModelProvider> {
|
||||
public interface RealmProviderFactory extends ProviderFactory<RealmProvider> {
|
||||
}
|
8
model/api/src/main/java/org/keycloak/models/ModelSpi.java → model/api/src/main/java/org/keycloak/models/RealmSpi.java
Normal file → Executable file
8
model/api/src/main/java/org/keycloak/models/ModelSpi.java → model/api/src/main/java/org/keycloak/models/RealmSpi.java
Normal file → Executable file
|
@ -7,21 +7,21 @@ import org.keycloak.provider.Spi;
|
|||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class ModelSpi implements Spi {
|
||||
public class RealmSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "model";
|
||||
return "realm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return ModelProvider.class;
|
||||
return RealmProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return ModelProviderFactory.class;
|
||||
return RealmProviderFactory.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
|
|
@ -3,8 +3,6 @@ package org.keycloak.models;
|
|||
import org.keycloak.provider.Provider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
|
27
model/api/src/main/java/org/keycloak/models/UserSpi.java
Executable file
27
model/api/src/main/java/org/keycloak/models/UserSpi.java
Executable file
|
@ -0,0 +1,27 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.Spi;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class UserSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return UserProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return UserProviderFactory.class;
|
||||
}
|
||||
|
||||
}
|
4
model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
Normal file → Executable file
4
model/api/src/main/java/org/keycloak/models/entities/UserEntity.java
Normal file → Executable file
|
@ -1,11 +1,11 @@
|
|||
package org.keycloak.models.entities;
|
||||
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
|
|
26
model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
Normal file → Executable file
26
model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
Normal file → Executable file
|
@ -1,5 +1,15 @@
|
|||
package org.keycloak.models.utils;
|
||||
|
||||
import org.bouncycastle.openssl.PEMWriter;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.util.PemUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.security.Key;
|
||||
|
@ -10,16 +20,6 @@ import java.security.PrivateKey;
|
|||
import java.security.PublicKey;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.bouncycastle.openssl.PEMWriter;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.util.PemUtils;
|
||||
|
||||
/**
|
||||
* Set of helper methods, which are useful in various model implementations.
|
||||
|
@ -122,10 +122,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;
|
||||
}
|
||||
|
|
31
model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
Normal file → Executable file
31
model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
Normal file → Executable file
|
@ -1,15 +1,5 @@
|
|||
package org.keycloak.models.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.iharder.Base64;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
|
@ -17,6 +7,7 @@ import org.keycloak.models.AuthenticationLinkModel;
|
|||
import org.keycloak.models.AuthenticationProviderModel;
|
||||
import org.keycloak.models.ClaimMask;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OAuthClientModel;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -37,11 +28,21 @@ import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
|||
import org.keycloak.representations.idm.SocialLinkRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class RepresentationToModel {
|
||||
|
||||
private static Logger logger = Logger.getLogger(RepresentationToModel.class);
|
||||
|
||||
public static void importRealm(RealmRepresentation rep, RealmModel newRealm) {
|
||||
public static void importRealm(KeycloakSession session, RealmRepresentation rep, RealmModel newRealm) {
|
||||
newRealm.setName(rep.getRealm());
|
||||
if (rep.isEnabled() != null) newRealm.setEnabled(rep.isEnabled());
|
||||
if (rep.isSocial() != null) newRealm.setSocial(rep.isSocial());
|
||||
|
@ -210,7 +211,7 @@ public class RepresentationToModel {
|
|||
|
||||
if (rep.getUsers() != null) {
|
||||
for (UserRepresentation userRep : rep.getUsers()) {
|
||||
UserModel user = createUser(newRealm, userRep, appMap);
|
||||
UserModel user = createUser(session, newRealm, userRep, appMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -571,8 +572,8 @@ public class RepresentationToModel {
|
|||
|
||||
// Users
|
||||
|
||||
public static UserModel createUser(RealmModel newRealm, UserRepresentation userRep, Map<String, ApplicationModel> appMap) {
|
||||
UserModel user = newRealm.addUser(userRep.getId(), userRep.getUsername(), false);
|
||||
public static UserModel createUser(KeycloakSession session, RealmModel newRealm, UserRepresentation userRep, Map<String, ApplicationModel> appMap) {
|
||||
UserModel user = session.users().addUser(newRealm, userRep.getId(), userRep.getUsername(), false);
|
||||
user.setEnabled(userRep.isEnabled());
|
||||
user.setEmail(userRep.getEmail());
|
||||
user.setFirstName(userRep.getFirstName());
|
||||
|
@ -600,7 +601,7 @@ public class RepresentationToModel {
|
|||
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) {
|
||||
|
|
2
model/api/src/main/java/org/keycloak/models/utils/reflection/Properties.java
Normal file → Executable file
2
model/api/src/main/java/org/keycloak/models/utils/reflection/Properties.java
Normal file → Executable file
|
@ -1,7 +1,5 @@
|
|||
package org.keycloak.models.utils.reflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
|
|
1
model/api/src/main/java/org/keycloak/models/utils/reflection/PropertyCriteria.java
Normal file → Executable file
1
model/api/src/main/java/org/keycloak/models/utils/reflection/PropertyCriteria.java
Normal file → Executable file
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.models.utils.reflection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
|
|
3
model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
Normal file → Executable file
3
model/api/src/main/resources/META-INF/services/org.keycloak.provider.Spi
Normal file → Executable file
|
@ -1,2 +1,3 @@
|
|||
org.keycloak.models.ModelSpi
|
||||
org.keycloak.models.RealmSpi
|
||||
org.keycloak.models.UserSessionSpi
|
||||
org.keycloak.models.UserSpi
|
5
model/hybrid/src/main/java/org/keycloak/models/hybrid/ApplicationAdapter.java
Normal file → Executable file
5
model/hybrid/src/main/java/org/keycloak/models/hybrid/ApplicationAdapter.java
Normal file → Executable file
|
@ -1,15 +1,12 @@
|
|||
package org.keycloak.models.hybrid;
|
||||
|
||||
import org.keycloak.models.realms.Application;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.realms.Application;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
|
1
model/hybrid/src/main/java/org/keycloak/models/hybrid/ClientAdapter.java
Normal file → Executable file
1
model/hybrid/src/main/java/org/keycloak/models/hybrid/ClientAdapter.java
Normal file → Executable file
|
@ -3,7 +3,6 @@ package org.keycloak.models.hybrid;
|
|||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.realms.Client;
|
||||
|
||||
import java.util.Set;
|
||||
|
|
3
model/hybrid/src/main/java/org/keycloak/models/hybrid/HybridModelProvider.java
Normal file → Executable file
3
model/hybrid/src/main/java/org/keycloak/models/hybrid/HybridModelProvider.java
Normal file → Executable file
|
@ -1,7 +1,6 @@
|
|||
package org.keycloak.models.hybrid;
|
||||
|
||||
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,13 +9,11 @@ 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.realms.RealmProvider;
|
||||
import org.keycloak.models.sessions.SessionProvider;
|
||||
import org.keycloak.models.users.UserProvider;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.util.Time;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
3
model/hybrid/src/main/java/org/keycloak/models/hybrid/HybridModelProviderFactory.java
Normal file → Executable file
3
model/hybrid/src/main/java/org/keycloak/models/hybrid/HybridModelProviderFactory.java
Normal file → Executable file
|
@ -1,12 +1,9 @@
|
|||
package org.keycloak.models.hybrid;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.realms.RealmProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.models.ModelProviderFactory;
|
||||
import org.keycloak.models.sessions.SessionProvider;
|
||||
import org.keycloak.models.users.UserProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
|
13
model/hybrid/src/main/java/org/keycloak/models/hybrid/RealmAdapter.java
Normal file → Executable file
13
model/hybrid/src/main/java/org/keycloak/models/hybrid/RealmAdapter.java
Normal file → Executable file
|
@ -1,11 +1,5 @@
|
|||
package org.keycloak.models.hybrid;
|
||||
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.realms.Application;
|
||||
import org.keycloak.models.realms.Client;
|
||||
import org.keycloak.models.realms.OAuthClient;
|
||||
import org.keycloak.models.realms.Realm;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.AuthenticationProviderModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
|
@ -15,9 +9,14 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
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.realms.Application;
|
||||
import org.keycloak.models.realms.Client;
|
||||
import org.keycloak.models.realms.OAuthClient;
|
||||
import org.keycloak.models.realms.Realm;
|
||||
import org.keycloak.models.users.Credentials;
|
||||
import org.keycloak.models.users.Feature;
|
||||
import org.keycloak.models.users.User;
|
||||
|
|
4
model/hybrid/src/main/java/org/keycloak/models/hybrid/RoleAdapter.java
Normal file → Executable file
4
model/hybrid/src/main/java/org/keycloak/models/hybrid/RoleAdapter.java
Normal file → Executable file
|
@ -1,10 +1,10 @@
|
|||
package org.keycloak.models.hybrid;
|
||||
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.realms.Application;
|
||||
import org.keycloak.models.realms.Realm;
|
||||
import org.keycloak.models.realms.Role;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
|
3
model/hybrid/src/main/java/org/keycloak/models/hybrid/UsernameLoginFailureAdapter.java
Normal file → Executable file
3
model/hybrid/src/main/java/org/keycloak/models/hybrid/UsernameLoginFailureAdapter.java
Normal file → Executable file
|
@ -3,9 +3,6 @@ package org.keycloak.models.hybrid;
|
|||
import org.keycloak.models.UsernameLoginFailureModel;
|
||||
import org.keycloak.models.sessions.LoginFailure;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
|
|
|
@ -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, CacheRealmProvider cacheSession, RealmCache cache) {
|
||||
super(cachedRealm, cached, cache, cacheSession);
|
||||
this.cached = cached;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface CacheModelProvider extends ModelProvider {
|
||||
ModelProvider getDelegate();
|
||||
public interface CacheRealmProvider extends RealmProvider {
|
||||
RealmProvider getDelegate();
|
||||
|
||||
void registerRealmInvalidation(String id);
|
||||
|
|
@ -6,6 +6,6 @@ import org.keycloak.provider.ProviderFactory;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface CacheModelProviderFactory extends ProviderFactory<CacheModelProvider> {
|
||||
public interface CacheRealmProviderFactory extends ProviderFactory<CacheRealmProvider> {
|
||||
|
||||
}
|
|
@ -8,20 +8,20 @@ import org.keycloak.provider.Spi;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CacheModelProviderSpi implements Spi {
|
||||
public class CacheRealmProviderSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "modelCache";
|
||||
return "realmCache";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return CacheModelProvider.class;
|
||||
return CacheRealmProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return CacheModelProviderFactory.class;
|
||||
return CacheRealmProviderFactory.class;
|
||||
}
|
||||
}
|
14
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
vendored
Executable file
14
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProvider.java
vendored
Executable file
|
@ -0,0 +1,14 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface CacheUserProvider extends UserProvider {
|
||||
UserProvider getDelegate();
|
||||
|
||||
void registerUserInvalidation(RealmModel realm, String id);
|
||||
}
|
11
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java
vendored
Executable file
11
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderFactory.java
vendored
Executable file
|
@ -0,0 +1,11 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface CacheUserProviderFactory extends ProviderFactory<CacheUserProvider> {
|
||||
|
||||
}
|
27
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
vendored
Executable file
27
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/CacheUserProviderSpi.java
vendored
Executable file
|
@ -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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CacheUserProviderSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "userCache";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return CacheUserProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return CacheUserProviderFactory.class;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
@ -16,12 +15,12 @@ import java.util.Set;
|
|||
*/
|
||||
public abstract class ClientAdapter implements ClientModel {
|
||||
protected CachedClient cachedClient;
|
||||
protected CacheModelProvider cacheSession;
|
||||
protected CacheRealmProvider 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, CacheRealmProvider cacheSession) {
|
||||
this.cachedRealm = cachedRealm;
|
||||
this.cache = cache;
|
||||
this.cacheSession = cacheSession;
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
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;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
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.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;
|
||||
import org.keycloak.models.cache.entities.CachedRealm;
|
||||
import org.keycloak.models.cache.entities.CachedRealmRole;
|
||||
import org.keycloak.models.cache.entities.CachedRole;
|
||||
import org.keycloak.models.cache.entities.CachedUser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -30,10 +25,10 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class DefaultCacheModelProvider implements CacheModelProvider {
|
||||
protected KeycloakCache cache;
|
||||
public class DefaultCacheRealmProvider implements CacheRealmProvider {
|
||||
protected RealmCache cache;
|
||||
protected KeycloakSession session;
|
||||
protected ModelProvider delegate;
|
||||
protected RealmProvider delegate;
|
||||
protected boolean transactionActive;
|
||||
protected boolean setRollbackOnly;
|
||||
|
||||
|
@ -50,7 +45,7 @@ public class DefaultCacheModelProvider implements CacheModelProvider {
|
|||
|
||||
protected boolean clearAll;
|
||||
|
||||
public DefaultCacheModelProvider(KeycloakCache cache, KeycloakSession session) {
|
||||
public DefaultCacheRealmProvider(RealmCache cache, KeycloakSession session) {
|
||||
this.cache = cache;
|
||||
this.session = session;
|
||||
|
||||
|
@ -58,10 +53,10 @@ public class DefaultCacheModelProvider implements CacheModelProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ModelProvider getDelegate() {
|
||||
public RealmProvider getDelegate() {
|
||||
if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
|
||||
if (delegate != null) return delegate;
|
||||
delegate = session.getProvider(ModelProvider.class);
|
||||
delegate = session.getProvider(RealmProvider.class);
|
||||
return delegate;
|
||||
}
|
||||
|
||||
|
@ -103,10 +98,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 +191,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<RealmModel> getRealms() {
|
||||
// we don't cache this for now
|
||||
|
@ -291,36 +225,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<UserModel> getUsers(RealmModel realm) {
|
||||
return getDelegate().getUsers(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return getDelegate().searchForUser(search, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
|
||||
return getDelegate().searchForUserByAttributes(attributes, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> 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);
|
244
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java
vendored
Executable file
244
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/DefaultCacheUserProvider.java
vendored
Executable file
|
@ -0,0 +1,244 @@
|
|||
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @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<String, String> userInvalidations = new HashMap<String, String>();
|
||||
protected Set<String> realmInvalidations = new HashSet<String>();
|
||||
protected Map<String, UserModel> managedUsers = new HashMap<String, UserModel>();
|
||||
|
||||
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<String, String> 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<UserModel> getUsers(RealmModel realm) {
|
||||
return getDelegate().getUsers(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return getDelegate().searchForUser(search, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
|
||||
return getDelegate().searchForUserByAttributes(attributes, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> 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) {
|
||||
UserModel user = getUserByUsername(name, realm);
|
||||
if (user == null) return false;
|
||||
registerUserInvalidation(realm, user.getId());
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -7,12 +7,12 @@ import org.keycloak.models.KeycloakSession;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class SimpleCacheModelProviderFactory implements CacheModelProviderFactory {
|
||||
protected KeycloakCache cache = new SimpleCache();
|
||||
public class MemoryCacheRealmProviderFactory implements CacheRealmProviderFactory {
|
||||
protected RealmCache cache = new MemoryRealmCache();
|
||||
|
||||
@Override
|
||||
public CacheModelProvider create(KeycloakSession session) {
|
||||
return new DefaultCacheModelProvider(cache, session);
|
||||
public CacheRealmProvider create(KeycloakSession session) {
|
||||
return new DefaultCacheRealmProvider(cache, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,6 +28,6 @@ public class SimpleCacheModelProviderFactory implements CacheModelProviderFactor
|
|||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "simple";
|
||||
return "mem";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class MemoryCacheUserProviderFactory implements CacheUserProviderFactory {
|
||||
protected UserCache cache = new MemoryUserCache();
|
||||
|
||||
@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 "mem";
|
||||
}
|
||||
}
|
125
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
vendored
Executable file
125
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryRealmCache.java
vendored
Executable file
|
@ -0,0 +1,125 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
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 java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class MemoryRealmCache implements RealmCache {
|
||||
|
||||
protected ConcurrentHashMap<String, CachedRealm> realmCache = new ConcurrentHashMap<String, CachedRealm>();
|
||||
protected ConcurrentHashMap<String, CachedRealm> realmCacheByName = new ConcurrentHashMap<String, CachedRealm>();
|
||||
protected ConcurrentHashMap<String, CachedApplication> applicationCache = new ConcurrentHashMap<String, CachedApplication>();
|
||||
protected ConcurrentHashMap<String, CachedOAuthClient> clientCache = new ConcurrentHashMap<String, CachedOAuthClient>();
|
||||
protected ConcurrentHashMap<String, CachedRole> roleCache = new ConcurrentHashMap<String, CachedRole>();
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
143
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryUserCache.java
vendored
Executable file
143
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/MemoryUserCache.java
vendored
Executable file
|
@ -0,0 +1,143 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class MemoryUserCache implements UserCache {
|
||||
|
||||
protected int maxUserCacheSize = 10000;
|
||||
|
||||
|
||||
protected class RealmUsers {
|
||||
protected class LRUCache extends LinkedHashMap<String, CachedUser> {
|
||||
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<String, CachedUser> 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<String, CachedUser> usersById = Collections.synchronizedMap(new LRUCache());
|
||||
protected Map<String, CachedUser> usersByUsername = new ConcurrentHashMap<String, CachedUser>();
|
||||
protected Map<String, CachedUser> usersByEmail = new ConcurrentHashMap<String, CachedUser>();
|
||||
|
||||
}
|
||||
|
||||
protected ConcurrentHashMap<String, RealmUsers> realmUsers = new ConcurrentHashMap<String, RealmUsers>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,42 +1,34 @@
|
|||
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;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
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.UserSessionModel;
|
||||
import org.keycloak.models.UsernameLoginFailureModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class NoCacheModelProvider implements CacheModelProvider {
|
||||
public class NoCacheRealmProvider implements CacheRealmProvider {
|
||||
protected KeycloakSession session;
|
||||
protected ModelProvider delegate;
|
||||
protected RealmProvider delegate;
|
||||
// protected KeycloakTransaction transactionDelegate;
|
||||
// protected boolean transactionActive;
|
||||
// protected boolean setRollbackOnly;
|
||||
|
||||
public NoCacheModelProvider(KeycloakSession session) {
|
||||
public NoCacheRealmProvider(KeycloakSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelProvider getDelegate() {
|
||||
public RealmProvider getDelegate() {
|
||||
// if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
|
||||
if (delegate != null) return delegate;
|
||||
delegate = session.getProvider(ModelProvider.class);
|
||||
delegate = session.getProvider(RealmProvider.class);
|
||||
// transactionDelegate = delegate.getTransaction();
|
||||
// if (!transactionDelegate.isActive()) {
|
||||
// transactionDelegate.begin();
|
||||
|
@ -83,21 +75,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<RealmModel> getRealms() {
|
||||
// we don't cache this for now
|
||||
|
@ -114,36 +91,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<UserModel> getUsers(RealmModel realm) {
|
||||
return getDelegate().getUsers(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return getDelegate().searchForUser(search, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
|
||||
return getDelegate().searchForUserByAttributes(attributes, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> 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);
|
|
@ -7,10 +7,10 @@ import org.keycloak.models.KeycloakSession;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class NoCacheModelProviderFactory implements CacheModelProviderFactory {
|
||||
public class NoCacheRealmProviderFactory implements CacheRealmProviderFactory {
|
||||
@Override
|
||||
public CacheModelProvider create(KeycloakSession session) {
|
||||
return new NoCacheModelProvider(session);
|
||||
public CacheRealmProvider create(KeycloakSession session) {
|
||||
return new NoCacheRealmProvider(session);
|
||||
}
|
||||
|
||||
@Override
|
126
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java
vendored
Executable file
126
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProvider.java
vendored
Executable file
|
@ -0,0 +1,126 @@
|
|||
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class NoCacheUserProvider implements CacheUserProvider {
|
||||
protected KeycloakSession session;
|
||||
protected UserProvider delegate;
|
||||
|
||||
public NoCacheUserProvider(KeycloakSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserProvider getDelegate() {
|
||||
if (delegate != null) return delegate;
|
||||
delegate = session.getProvider(UserProvider.class);
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUserInvalidation(RealmModel realm, String id) {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@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 void close() {
|
||||
if (delegate != null) delegate.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) {
|
||||
return getDelegate().getUserBySocialLink(socialLink, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers(RealmModel realm) {
|
||||
return getDelegate().getUsers(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
return getDelegate().searchForUser(search, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
|
||||
return getDelegate().searchForUserByAttributes(attributes, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> 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) {
|
||||
getDelegate().preRemove(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RoleModel role) {
|
||||
getDelegate().preRemove(role);
|
||||
}
|
||||
}
|
30
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProviderFactory.java
vendored
Executable file
30
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/NoCacheUserProviderFactory.java
vendored
Executable file
|
@ -0,0 +1,30 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class NoCacheUserProviderFactory implements CacheUserProviderFactory {
|
||||
@Override
|
||||
public CacheUserProvider create(KeycloakSession session) {
|
||||
return new NoCacheUserProvider(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "none";
|
||||
}
|
||||
}
|
|
@ -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, CacheRealmProvider cacheSession, RealmCache cache) {
|
||||
super(cachedRealm, cached, cache, cacheSession);
|
||||
this.cached = cached;
|
||||
}
|
||||
|
|
|
@ -9,15 +9,11 @@ import org.keycloak.models.PasswordPolicy;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
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;
|
||||
|
@ -35,13 +31,13 @@ import java.util.Set;
|
|||
*/
|
||||
public class RealmAdapter implements RealmModel {
|
||||
protected CachedRealm cached;
|
||||
protected CacheModelProvider cacheSession;
|
||||
protected CacheRealmProvider cacheSession;
|
||||
protected RealmModel updated;
|
||||
protected KeycloakCache cache;
|
||||
protected RealmCache cache;
|
||||
protected volatile transient PublicKey publicKey;
|
||||
protected volatile transient PrivateKey privateKey;
|
||||
|
||||
public RealmAdapter(CachedRealm cached, CacheModelProvider cacheSession) {
|
||||
public RealmAdapter(CachedRealm cached, CacheRealmProvider cacheSession) {
|
||||
this.cached = cached;
|
||||
this.cacheSession = cacheSession;
|
||||
}
|
||||
|
@ -395,39 +391,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 +501,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<SocialLinkModel> 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 +525,6 @@ public class RealmAdapter implements RealmModel {
|
|||
updated.setUpdateProfileOnInitialSocialLogin(updateProfileOnInitialSocialLogin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers() {
|
||||
if (updated != null) return updated.getUsers();
|
||||
return cacheSession.getUsers(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search) {
|
||||
if (updated != null) return updated.searchForUser(search);
|
||||
return cacheSession.searchForUser(search, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
|
||||
if (updated != null) return updated.searchForUserByAttributes(attributes);
|
||||
return cacheSession.searchForUserByAttributes(attributes, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuthClientModel addOAuthClient(String name) {
|
||||
getDelegateForUpdate();
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface KeycloakCache {
|
||||
public interface RealmCache {
|
||||
void clear();
|
||||
|
||||
CachedRealm getCachedRealm(String id);
|
||||
|
@ -51,16 +49,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);
|
||||
}
|
|
@ -19,11 +19,11 @@ public class RoleAdapter implements RoleModel {
|
|||
|
||||
protected RoleModel updated;
|
||||
protected CachedRole cached;
|
||||
protected KeycloakCache cache;
|
||||
protected CacheModelProvider cacheSession;
|
||||
protected RealmCache cache;
|
||||
protected CacheRealmProvider cacheSession;
|
||||
protected RealmModel realm;
|
||||
|
||||
public RoleAdapter(CachedRole cached, KeycloakCache cache, CacheModelProvider session, RealmModel realm) {
|
||||
public RoleAdapter(CachedRole cached, RealmCache cache, CacheRealmProvider session, RealmModel realm) {
|
||||
this.cached = cached;
|
||||
this.cache = cache;
|
||||
this.cacheSession = session;
|
||||
|
|
|
@ -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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class SimpleCache implements KeycloakCache {
|
||||
|
||||
protected ConcurrentHashMap<String, CachedRealm> realmCache = new ConcurrentHashMap<String, CachedRealm>();
|
||||
protected ConcurrentHashMap<String, CachedRealm> realmCacheByName = new ConcurrentHashMap<String, CachedRealm>();
|
||||
protected ConcurrentHashMap<String, CachedApplication> applicationCache = new ConcurrentHashMap<String, CachedApplication>();
|
||||
protected ConcurrentHashMap<String, CachedOAuthClient> clientCache = new ConcurrentHashMap<String, CachedOAuthClient>();
|
||||
protected ConcurrentHashMap<String, CachedRole> roleCache = new ConcurrentHashMap<String, CachedRole>();
|
||||
|
||||
protected int maxUserCacheSize = 10000;
|
||||
protected boolean userCacheEnabled = true;
|
||||
|
||||
protected Map<String, CachedUser> usersById = Collections.synchronizedMap(new LRUCache());
|
||||
protected Map<String, CachedUser> usersByUsername = new ConcurrentHashMap<String, CachedUser>();
|
||||
protected Map<String, CachedUser> usersByEmail = new ConcurrentHashMap<String, CachedUser>();
|
||||
|
||||
protected class LRUCache extends LinkedHashMap<String, CachedUser> {
|
||||
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<String, CachedUser> 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.getId());
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package org.keycloak.models.cache;
|
|||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.AuthenticationLinkModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
|
@ -22,21 +23,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 +258,13 @@ public class UserAdapter implements UserModel {
|
|||
if (updated != null) return updated.getRoleMappings();
|
||||
Set<RoleModel> roles = new HashSet<RoleModel>();
|
||||
for (String id : cached.getRoleMappings()) {
|
||||
roles.add(cacheSession.getRoleById(id, realm));
|
||||
RoleModel roleById = keycloakSession.realms().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;
|
||||
|
|
25
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
vendored
Executable file
25
model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/UserCache.java
vendored
Executable file
|
@ -0,0 +1,25 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.models.cache.entities.CachedUser;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @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);
|
||||
}
|
|
@ -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.RealmProvider;
|
||||
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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -29,7 +23,7 @@ public class CachedApplication extends CachedClient {
|
|||
private boolean bearerOnly;
|
||||
private Map<String, String> roles = new HashMap<String, String>();
|
||||
|
||||
public CachedApplication(KeycloakCache cache, ModelProvider delegate, RealmModel realm, ApplicationModel model) {
|
||||
public CachedApplication(RealmCache cache, RealmProvider delegate, RealmModel realm, ApplicationModel model) {
|
||||
super(cache, delegate, realm, model);
|
||||
surrogateAuthRequired = model.isSurrogateAuthRequired();
|
||||
managementUrl = model.getManagementUrl();
|
||||
|
|
|
@ -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.RealmProvider;
|
||||
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<String> scope = new HashSet<String>();
|
||||
protected Set<String> webOrigins = new HashSet<String>();
|
||||
|
||||
public CachedClient(KeycloakCache cache, ModelProvider delegate, RealmModel realm, ClientModel model) {
|
||||
public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
|
||||
id = model.getId();
|
||||
secret = model.getSecret();
|
||||
name = model.getClientId();
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
package org.keycloak.models.cache.entities;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelProvider;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
import org.keycloak.models.OAuthClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.cache.KeycloakCache;
|
||||
import org.keycloak.models.cache.RealmCache;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CachedOAuthClient extends CachedClient {
|
||||
public CachedOAuthClient(KeycloakCache cache, ModelProvider delegate, RealmModel realm, OAuthClientModel model) {
|
||||
public CachedOAuthClient(RealmCache cache, RealmProvider delegate, RealmModel realm, OAuthClientModel model) {
|
||||
super(cache, delegate, realm, model);
|
||||
|
||||
}
|
||||
|
|
|
@ -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.RealmProvider;
|
||||
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, RealmProvider delegate, RealmModel model) {
|
||||
id = model.getId();
|
||||
name = model.getName();
|
||||
enabled = model.isEnabled();
|
||||
|
|
|
@ -2,9 +2,6 @@ package org.keycloak.models.cache.entities;
|
|||
|
||||
import org.keycloak.models.RoleModel;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
|
|
@ -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<UserCredentialValueModel> credentials = new LinkedList<UserCredentialValueModel>();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
org.keycloak.models.cache.SimpleCacheModelProviderFactory
|
||||
org.keycloak.models.cache.NoCacheModelProviderFactory
|
|
@ -0,0 +1,2 @@
|
|||
org.keycloak.models.cache.MemoryCacheRealmProviderFactory
|
||||
org.keycloak.models.cache.NoCacheRealmProviderFactory
|
|
@ -0,0 +1,2 @@
|
|||
org.keycloak.models.cache.MemoryCacheUserProviderFactory
|
||||
org.keycloak.models.cache.NoCacheUserProviderFactory
|
|
@ -1 +1,2 @@
|
|||
org.keycloak.models.cache.CacheModelProviderSpi
|
||||
org.keycloak.models.cache.CacheRealmProviderSpi
|
||||
org.keycloak.models.cache.CacheUserProviderSpi
|
|
@ -2,12 +2,13 @@ package org.keycloak.models.jpa;
|
|||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.jpa.entities.*;
|
||||
import org.keycloak.models.jpa.entities.ApplicationEntity;
|
||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||
import org.keycloak.models.jpa.entities.ScopeMappingEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -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);
|
||||
|
|
|
@ -1,278 +0,0 @@
|
|||
package org.keycloak.models.jpa;
|
||||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakTransaction;
|
||||
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.jpa.entities.ApplicationEntity;
|
||||
import org.keycloak.models.jpa.entities.OAuthClientEntity;
|
||||
import org.keycloak.models.jpa.entities.RealmEntity;
|
||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||
import org.keycloak.models.jpa.entities.SocialLinkEntity;
|
||||
import org.keycloak.models.jpa.entities.UserEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JpaModelProvider implements ModelProvider {
|
||||
private final KeycloakSession session;
|
||||
protected EntityManager em;
|
||||
|
||||
public JpaModelProvider(KeycloakSession session, EntityManager em) {
|
||||
this.session = session;
|
||||
this.em = em;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel createRealm(String name) {
|
||||
return createRealm(KeycloakModelUtils.generateId(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel createRealm(String id, String name) {
|
||||
RealmEntity realm = new RealmEntity();
|
||||
realm.setName(name);
|
||||
realm.setId(id);
|
||||
em.persist(realm);
|
||||
em.flush();
|
||||
return new RealmAdapter(session, em, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm(String id) {
|
||||
RealmEntity realm = em.find(RealmEntity.class, id);
|
||||
if (realm == null) return null;
|
||||
return new RealmAdapter(session, em, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RealmModel> getRealms() {
|
||||
TypedQuery<RealmEntity> query = em.createNamedQuery("getAllRealms", RealmEntity.class);
|
||||
List<RealmEntity> entities = query.getResultList();
|
||||
List<RealmModel> realms = new ArrayList<RealmModel>();
|
||||
for (RealmEntity entity : entities) {
|
||||
realms.add(new RealmAdapter(session, em, entity));
|
||||
}
|
||||
return realms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealmByName(String name) {
|
||||
TypedQuery<RealmEntity> query = em.createNamedQuery("getRealmByName", RealmEntity.class);
|
||||
query.setParameter("name", name);
|
||||
List<RealmEntity> entities = query.getResultList();
|
||||
if (entities.size() == 0) return null;
|
||||
if (entities.size() > 1) throw new IllegalStateException("Should not be more than one realm with same name");
|
||||
RealmEntity realm = query.getResultList().get(0);
|
||||
if (realm == null) return null;
|
||||
return new RealmAdapter(session, em, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserById(String id, RealmModel realmModel) {
|
||||
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserById", UserEntity.class);
|
||||
query.setParameter("id", id);
|
||||
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
|
||||
query.setParameter("realm", realm);
|
||||
List<UserEntity> 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<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
|
||||
query.setParameter("username", username);
|
||||
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
|
||||
query.setParameter("realm", realm);
|
||||
List<UserEntity> 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<UserEntity> query = em.createNamedQuery("getRealmUserByEmail", UserEntity.class);
|
||||
query.setParameter("email", email);
|
||||
RealmEntity realm = em.getReference(RealmEntity.class, realmModel.getId());
|
||||
query.setParameter("realm", realm);
|
||||
List<UserEntity> 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);
|
||||
if (realm == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RealmAdapter adapter = new RealmAdapter(session, em, realm);
|
||||
for (ApplicationEntity a : new LinkedList<ApplicationEntity>(realm.getApplications())) {
|
||||
adapter.removeApplication(a.getId());
|
||||
}
|
||||
|
||||
for (OAuthClientModel oauth : adapter.getOAuthClients()) {
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUserBySocialLink(SocialLinkModel socialLink, RealmModel realm) {
|
||||
TypedQuery<UserEntity> 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<UserEntity> 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<UserModel> getUsers(RealmModel realm) {
|
||||
TypedQuery<UserEntity> 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<UserEntity> results = query.getResultList();
|
||||
List<UserModel> users = new ArrayList<UserModel>();
|
||||
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||
TypedQuery<UserEntity> 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<UserEntity> results = query.getResultList();
|
||||
List<UserModel> users = new ArrayList<UserModel>();
|
||||
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm) {
|
||||
StringBuilder builder = new StringBuilder("select u from UserEntity u");
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, String> 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<UserEntity> query = em.createQuery(q, UserEntity.class);
|
||||
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
|
||||
query.setParameter("realm", realmEntity);
|
||||
List<UserEntity> results = query.getResultList();
|
||||
List<UserModel> users = new ArrayList<UserModel>();
|
||||
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
|
||||
return users;
|
||||
}
|
||||
|
||||
private SocialLinkEntity findSocialLink(UserModel user, String socialProvider) {
|
||||
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByUserAndProvider", SocialLinkEntity.class);
|
||||
UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
|
||||
query.setParameter("user", userEntity);
|
||||
query.setParameter("socialProvider", socialProvider);
|
||||
List<SocialLinkEntity> results = query.getResultList();
|
||||
return results.size() > 0 ? results.get(0) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<SocialLinkModel> getSocialLinks(UserModel user, RealmModel realm) {
|
||||
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByUser", SocialLinkEntity.class);
|
||||
UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
|
||||
query.setParameter("user", userEntity);
|
||||
List<SocialLinkEntity> results = query.getResultList();
|
||||
Set<SocialLinkModel> set = new HashSet<SocialLinkModel>();
|
||||
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);
|
||||
if (entity == null) return null;
|
||||
if (!realm.getId().equals(entity.getRealmId())) return null;
|
||||
return new RoleAdapter(realm, em, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationModel getApplicationById(String id, RealmModel realm) {
|
||||
ApplicationEntity app = em.find(ApplicationEntity.class, id);
|
||||
|
||||
// Check if application belongs to this realm
|
||||
if (app == null || !realm.getId().equals(app.getRealm().getId())) return null;
|
||||
return new ApplicationAdapter(realm, em, app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
|
||||
OAuthClientEntity client = em.find(OAuthClientEntity.class, id);
|
||||
|
||||
// Check if client belongs to this realm
|
||||
if (client == null || !realm.getId().equals(client.getRealm().getId())) return null;
|
||||
return new OAuthClientAdapter(realm, client, em);
|
||||
}
|
||||
|
||||
}
|
130
model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
Executable file
130
model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
Executable file
|
@ -0,0 +1,130 @@
|
|||
package org.keycloak.models.jpa;
|
||||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
import org.keycloak.models.OAuthClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.jpa.entities.ApplicationEntity;
|
||||
import org.keycloak.models.jpa.entities.OAuthClientEntity;
|
||||
import org.keycloak.models.jpa.entities.RealmEntity;
|
||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JpaRealmProvider implements RealmProvider {
|
||||
private final KeycloakSession session;
|
||||
protected EntityManager em;
|
||||
|
||||
public JpaRealmProvider(KeycloakSession session, EntityManager em) {
|
||||
this.session = session;
|
||||
this.em = em;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel createRealm(String name) {
|
||||
return createRealm(KeycloakModelUtils.generateId(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel createRealm(String id, String name) {
|
||||
RealmEntity realm = new RealmEntity();
|
||||
realm.setName(name);
|
||||
realm.setId(id);
|
||||
em.persist(realm);
|
||||
em.flush();
|
||||
return new RealmAdapter(session, em, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm(String id) {
|
||||
RealmEntity realm = em.find(RealmEntity.class, id);
|
||||
if (realm == null) return null;
|
||||
return new RealmAdapter(session, em, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RealmModel> getRealms() {
|
||||
TypedQuery<RealmEntity> query = em.createNamedQuery("getAllRealms", RealmEntity.class);
|
||||
List<RealmEntity> entities = query.getResultList();
|
||||
List<RealmModel> realms = new ArrayList<RealmModel>();
|
||||
for (RealmEntity entity : entities) {
|
||||
realms.add(new RealmAdapter(session, em, entity));
|
||||
}
|
||||
return realms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealmByName(String name) {
|
||||
TypedQuery<RealmEntity> query = em.createNamedQuery("getRealmByName", RealmEntity.class);
|
||||
query.setParameter("name", name);
|
||||
List<RealmEntity> entities = query.getResultList();
|
||||
if (entities.size() == 0) return null;
|
||||
if (entities.size() > 1) throw new IllegalStateException("Should not be more than one realm with same name");
|
||||
RealmEntity realm = query.getResultList().get(0);
|
||||
if (realm == null) return null;
|
||||
return new RealmAdapter(session, em, realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeRealm(String id) {
|
||||
RealmEntity realm = em.find(RealmEntity.class, id);
|
||||
if (realm == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RealmAdapter adapter = new RealmAdapter(session, em, realm);
|
||||
session.users().preRemove(adapter);
|
||||
for (ApplicationEntity a : new LinkedList<ApplicationEntity>(realm.getApplications())) {
|
||||
adapter.removeApplication(a.getId());
|
||||
}
|
||||
|
||||
for (OAuthClientModel oauth : adapter.getOAuthClients()) {
|
||||
adapter.removeOAuthClient(oauth.getId());
|
||||
}
|
||||
|
||||
em.remove(realm);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleModel getRoleById(String id, RealmModel realm) {
|
||||
RoleEntity entity = em.find(RoleEntity.class, id);
|
||||
if (entity == null) return null;
|
||||
if (!realm.getId().equals(entity.getRealmId())) return null;
|
||||
return new RoleAdapter(realm, em, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationModel getApplicationById(String id, RealmModel realm) {
|
||||
ApplicationEntity app = em.find(ApplicationEntity.class, id);
|
||||
|
||||
// Check if application belongs to this realm
|
||||
if (app == null || !realm.getId().equals(app.getRealm().getId())) return null;
|
||||
return new ApplicationAdapter(realm, em, session, app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuthClientModel getOAuthClientById(String id, RealmModel realm) {
|
||||
OAuthClientEntity client = em.find(OAuthClientEntity.class, id);
|
||||
|
||||
// Check if client belongs to this realm
|
||||
if (client == null || !realm.getId().equals(client.getRealm().getId())) return null;
|
||||
return new OAuthClientAdapter(realm, client, em);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,8 +3,8 @@ 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.RealmProvider;
|
||||
import org.keycloak.models.RealmProviderFactory;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
|
@ -12,7 +12,7 @@ import javax.persistence.EntityManager;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JpaModelProviderFactory implements ModelProviderFactory {
|
||||
public class JpaRealmProviderFactory implements RealmProviderFactory {
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
@ -24,9 +24,9 @@ public class JpaModelProviderFactory implements ModelProviderFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ModelProvider create(KeycloakSession session) {
|
||||
public RealmProvider create(KeycloakSession session) {
|
||||
EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||
return new JpaModelProvider(session, em);
|
||||
return new JpaRealmProvider(session, em);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -2,16 +2,11 @@ package org.keycloak.models.jpa;
|
|||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakTransaction;
|
||||
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.jpa.entities.ApplicationEntity;
|
||||
import org.keycloak.models.jpa.entities.OAuthClientEntity;
|
||||
import org.keycloak.models.jpa.entities.RealmEntity;
|
||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||
import org.keycloak.models.jpa.entities.SocialLinkEntity;
|
||||
|
@ -23,7 +18,6 @@ import javax.persistence.EntityManager;
|
|||
import javax.persistence.TypedQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -39,7 +33,6 @@ public class JpaUserProvider implements UserProvider {
|
|||
public JpaUserProvider(KeycloakSession session, EntityManager em) {
|
||||
this.session = session;
|
||||
this.em = em;
|
||||
this.em = PersistenceExceptionConverter.create(em);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -99,12 +92,38 @@ public class JpaUserProvider implements UserProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm) {
|
||||
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class);
|
||||
public void addSocialLink(RealmModel realm, UserModel user, SocialLinkModel socialLink) {
|
||||
SocialLinkEntity entity = new SocialLinkEntity();
|
||||
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
|
||||
query.setParameter("realm", realmEntity);
|
||||
for (UserEntity u : query.getResultList()) {
|
||||
em.remove(u);
|
||||
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) {
|
||||
RealmEntity realmEntity = em.getReference(RealmEntity.class, realm.getId());
|
||||
for (UserEntity u : em.createQuery("from UserEntity u where u.realm = :realm", UserEntity.class).setParameter("realm", realmEntity).getResultList()) {
|
||||
removeUser(realm, u.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,12 +133,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<UserEntity> query = em.createNamedQuery("getRealmUserById", UserEntity.class);
|
||||
|
@ -154,8 +167,6 @@ public class JpaUserProvider implements UserProvider {
|
|||
|
||||
@Override
|
||||
public void close() {
|
||||
if (em.getTransaction().isActive()) em.getTransaction().rollback();
|
||||
if (em.isOpen()) em.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
36
model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java
Executable file
36
model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProviderFactory.java
Executable file
|
@ -0,0 +1,36 @@
|
|||
package org.keycloak.models.jpa;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.connections.jpa.JpaConnectionProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserProvider;
|
||||
import org.keycloak.models.UserProviderFactory;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @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() {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
package org.keycloak.models.jpa;
|
||||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.OAuthClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.jpa.entities.OAuthClientEntity;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
|
3
model/jpa/src/main/java/org/keycloak/models/jpa/PersistenceExceptionConverter.java
Normal file → Executable file
3
model/jpa/src/main/java/org/keycloak/models/jpa/PersistenceExceptionConverter.java
Normal file → Executable file
|
@ -1,12 +1,11 @@
|
|||
package org.keycloak.models.jpa;
|
||||
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.ModelException;
|
||||
|
||||
import javax.persistence.EntityExistsException;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
|
|
@ -10,11 +10,9 @@ import org.keycloak.models.PasswordPolicy;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.SocialLinkModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserCredentialValueModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UsernameLoginFailureModel;
|
||||
import org.keycloak.models.jpa.entities.ApplicationEntity;
|
||||
import org.keycloak.models.jpa.entities.AuthenticationProviderEntity;
|
||||
import org.keycloak.models.jpa.entities.OAuthClientEntity;
|
||||
|
@ -22,9 +20,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 +406,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<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
|
||||
query.setParameter("username", name);
|
||||
query.setParameter("realm", realm);
|
||||
List<UserEntity> 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<String> getDefaultRoles() {
|
||||
Collection<RoleEntity> entities = realm.getDefaultRoles();
|
||||
|
@ -567,7 +493,7 @@ public class RealmAdapter implements RealmModel {
|
|||
List<ApplicationModel> list = new ArrayList<ApplicationModel>();
|
||||
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 +513,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;
|
||||
}
|
||||
|
@ -628,7 +554,7 @@ public class RealmAdapter implements RealmModel {
|
|||
|
||||
@Override
|
||||
public ApplicationModel getApplicationById(String id) {
|
||||
return session.model().getApplicationById(id, this);
|
||||
return session.realms().getApplicationById(id, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -636,57 +562,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<SocialLinkModel> 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<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByUserAndProvider", SocialLinkEntity.class);
|
||||
UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
|
||||
query.setParameter("user", userEntity);
|
||||
query.setParameter("socialProvider", socialProvider);
|
||||
List<SocialLinkEntity> 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 +584,6 @@ public class RealmAdapter implements RealmModel {
|
|||
em.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> getUsers() {
|
||||
return session.model().getUsers(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUser(String search) {
|
||||
return session.model().searchForUser(search, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
|
||||
return session.model().searchForUserByAttributes(attributes, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuthClientModel addOAuthClient(String name) {
|
||||
return this.addOAuthClient(KeycloakModelUtils.generateId(), name);
|
||||
|
@ -764,7 +624,7 @@ public class RealmAdapter implements RealmModel {
|
|||
|
||||
@Override
|
||||
public OAuthClientModel getOAuthClientById(String id) {
|
||||
return session.model().getOAuthClientById(id, this);
|
||||
return session.realms().getOAuthClientById(id, this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -899,13 +759,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);
|
||||
|
@ -926,7 +785,7 @@ public class RealmAdapter implements RealmModel {
|
|||
|
||||
@Override
|
||||
public RoleModel getRoleById(String id) {
|
||||
return session.model().getRoleById(id, this);
|
||||
return session.realms().getRoleById(id, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1060,7 +919,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
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.keycloak.models.jpa;
|
|||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.AuthenticationLinkModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public class AbstractRoleMappingEntity {
|
||||
@Id
|
||||
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
|
||||
@GeneratedValue(generator = "keycloak_generator")
|
||||
protected String id;
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
protected UserEntity user;
|
||||
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name="roleId")
|
||||
protected RoleEntity role;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UserEntity getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserEntity user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public RoleEntity getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(RoleEntity role) {
|
||||
this.role = role;
|
||||
}
|
||||
}
|
|
@ -1,25 +1,12 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
|
8
model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationLinkEntity.java
Normal file → Executable file
8
model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationLinkEntity.java
Normal file → Executable file
|
@ -1,14 +1,10 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
|
5
model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationProviderEntity.java
Normal file → Executable file
5
model/jpa/src/main/java/org/keycloak/models/jpa/entities/AuthenticationProviderEntity.java
Normal file → Executable file
|
@ -1,6 +1,6 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import java.util.Map;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
|
@ -11,8 +11,7 @@ import javax.persistence.Id;
|
|||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import java.util.HashSet;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
|
@ -8,8 +10,6 @@ import javax.persistence.ManyToOne;
|
|||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
@ -33,6 +33,9 @@ public class CredentialEntity {
|
|||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
protected UserEntity user;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
protected RealmEntity realm;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
|
|
@ -3,10 +3,7 @@ package org.keycloak.models.jpa.entities;
|
|||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
|
@ -18,8 +15,6 @@ import javax.persistence.UniqueConstraint;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
|
@ -8,8 +10,6 @@ import javax.persistence.ManyToOne;
|
|||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
|
@ -10,7 +9,6 @@ import javax.persistence.Column;
|
|||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
@ -21,7 +19,6 @@ import javax.persistence.OneToMany;
|
|||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
package org.keycloak.models.jpa.entities;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
|
||||
|
@ -14,6 +21,40 @@ import javax.persistence.NamedQuery;
|
|||
@NamedQuery(name="userRoleMappingIds", query="select m.role.id from UserRoleMappingEntity m where m.user = :user")
|
||||
})
|
||||
@Entity
|
||||
public class UserRoleMappingEntity extends AbstractRoleMappingEntity {
|
||||
public class UserRoleMappingEntity {
|
||||
@Id
|
||||
@GenericGenerator(name="keycloak_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
|
||||
@GeneratedValue(generator = "keycloak_generator")
|
||||
protected String id;
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
protected UserEntity user;
|
||||
|
||||
@ManyToOne(fetch= FetchType.LAZY)
|
||||
@JoinColumn(name="roleId")
|
||||
protected RoleEntity role;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public UserEntity getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserEntity user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public RoleEntity getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(RoleEntity role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
4
model/jpa/src/main/java/org/keycloak/models/jpa/utils/JpaIdGenerator.java
Normal file → Executable file
4
model/jpa/src/main/java/org/keycloak/models/jpa/utils/JpaIdGenerator.java
Normal file → Executable file
|
@ -1,12 +1,12 @@
|
|||
package org.keycloak.models.jpa.utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
org.keycloak.models.jpa.JpaModelProviderFactory
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.models.jpa.JpaRealmProviderFactory
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.models.jpa.JpaUserProviderFactory
|
|
@ -2,12 +2,12 @@ package org.keycloak.models.mongo.keycloak.adapters;
|
|||
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.QueryBuilder;
|
||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
|
||||
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
|
||||
import org.keycloak.models.mongo.utils.MongoModelUtils;
|
||||
|
@ -141,6 +141,7 @@ public class ApplicationAdapter extends ClientAdapter<MongoApplicationEntity> im
|
|||
|
||||
@Override
|
||||
public boolean removeRole(RoleModel role) {
|
||||
session.users().preRemove(role);
|
||||
return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue