/* * Copyright 2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.keycloak.models.jpa; import org.jboss.logging.Logger; import org.keycloak.common.enums.SslRequired; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.component.ComponentFactory; import org.keycloak.component.ComponentModel; import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.AuthenticatorConfigModel; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientTemplateModel; import org.keycloak.models.GroupModel; import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelException; import org.keycloak.models.OTPPolicy; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredActionProviderModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; import org.keycloak.models.jpa.entities.AuthenticationExecutionEntity; import org.keycloak.models.jpa.entities.AuthenticationFlowEntity; import org.keycloak.models.jpa.entities.AuthenticatorConfigEntity; import org.keycloak.models.jpa.entities.ClientEntity; import org.keycloak.models.jpa.entities.ClientTemplateEntity; import org.keycloak.models.jpa.entities.ComponentConfigEntity; import org.keycloak.models.jpa.entities.ComponentEntity; import org.keycloak.models.jpa.entities.GroupEntity; import org.keycloak.models.jpa.entities.IdentityProviderEntity; import org.keycloak.models.jpa.entities.IdentityProviderMapperEntity; import org.keycloak.models.jpa.entities.RealmAttributeEntity; import org.keycloak.models.jpa.entities.RealmAttributes; import org.keycloak.models.jpa.entities.RealmEntity; import org.keycloak.models.jpa.entities.RequiredActionProviderEntity; import org.keycloak.models.jpa.entities.RequiredCredentialEntity; import org.keycloak.models.jpa.entities.RoleEntity; import org.keycloak.models.utils.ComponentUtil; import org.keycloak.models.utils.KeycloakModelUtils; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; 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 RealmAdapter implements RealmModel, JpaModel<RealmEntity> { protected static final Logger logger = Logger.getLogger(RealmAdapter.class); protected RealmEntity realm; protected EntityManager em; protected KeycloakSession session; private PasswordPolicy passwordPolicy; private OTPPolicy otpPolicy; public RealmAdapter(KeycloakSession session, EntityManager em, RealmEntity realm) { this.session = session; this.em = em; this.realm = realm; } public RealmEntity getEntity() { return realm; } @Override public String getId() { return realm.getId(); } @Override public String getName() { return realm.getName(); } @Override public void setName(String name) { realm.setName(name); em.flush(); } @Override public String getDisplayName() { return getAttribute(RealmAttributes.DISPLAY_NAME); } @Override public void setDisplayName(String displayName) { setAttribute(RealmAttributes.DISPLAY_NAME, displayName); } @Override public String getDisplayNameHtml() { return getAttribute(RealmAttributes.DISPLAY_NAME_HTML); } @Override public void setDisplayNameHtml(String displayNameHtml) { setAttribute(RealmAttributes.DISPLAY_NAME_HTML, displayNameHtml); } @Override public boolean isEnabled() { return realm.isEnabled(); } @Override public void setEnabled(boolean enabled) { realm.setEnabled(enabled); em.flush(); } @Override public SslRequired getSslRequired() { return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null; } @Override public void setSslRequired(SslRequired sslRequired) { realm.setSslRequired(sslRequired.name()); em.flush(); } @Override public boolean isRegistrationAllowed() { return realm.isRegistrationAllowed(); } @Override public void setRegistrationAllowed(boolean registrationAllowed) { realm.setRegistrationAllowed(registrationAllowed); em.flush(); } @Override public boolean isRegistrationEmailAsUsername() { return realm.isRegistrationEmailAsUsername(); } @Override public void setRegistrationEmailAsUsername(boolean registrationEmailAsUsername) { realm.setRegistrationEmailAsUsername(registrationEmailAsUsername); if (registrationEmailAsUsername) realm.setDuplicateEmailsAllowed(false); em.flush(); } @Override public boolean isRememberMe() { return realm.isRememberMe(); } @Override public void setRememberMe(boolean rememberMe) { realm.setRememberMe(rememberMe); em.flush(); } @Override public void setAttribute(String name, String value) { for (RealmAttributeEntity attr : realm.getAttributes()) { if (attr.getName().equals(name)) { attr.setValue(value); return; } } RealmAttributeEntity attr = new RealmAttributeEntity(); attr.setName(name); attr.setValue(value); attr.setRealm(realm); em.persist(attr); realm.getAttributes().add(attr); } @Override public void setAttribute(String name, Boolean value) { setAttribute(name, value.toString()); } @Override public void setAttribute(String name, Integer value) { setAttribute(name, value.toString()); } @Override public void setAttribute(String name, Long value) { setAttribute(name, value.toString()); } @Override public void removeAttribute(String name) { Iterator<RealmAttributeEntity> it = realm.getAttributes().iterator(); while (it.hasNext()) { RealmAttributeEntity attr = it.next(); if (attr.getName().equals(name)) { it.remove(); em.remove(attr); } } } @Override public String getAttribute(String name) { for (RealmAttributeEntity attr : realm.getAttributes()) { if (attr.getName().equals(name)) { return attr.getValue(); } } return null; } @Override public Integer getAttribute(String name, Integer defaultValue) { String v = getAttribute(name); return v != null ? Integer.parseInt(v) : defaultValue; } @Override public Long getAttribute(String name, Long defaultValue) { String v = getAttribute(name); return v != null ? Long.parseLong(v) : defaultValue; } @Override public Boolean getAttribute(String name, Boolean defaultValue) { String v = getAttribute(name); return v != null ? Boolean.parseBoolean(v) : defaultValue; } @Override public Map<String, String> getAttributes() { // should always return a copy Map<String, String> result = new HashMap<String, String>(); for (RealmAttributeEntity attr : realm.getAttributes()) { result.put(attr.getName(), attr.getValue()); } return result; } @Override public boolean isBruteForceProtected() { return getAttribute("bruteForceProtected", false); } @Override public void setBruteForceProtected(boolean value) { setAttribute("bruteForceProtected", value); } @Override public boolean isPermanentLockout() { return getAttribute("permanentLockout", false); } @Override public void setPermanentLockout(final boolean val) { setAttribute("permanentLockout", val); } @Override public int getMaxFailureWaitSeconds() { return getAttribute("maxFailureWaitSeconds", 0); } @Override public void setMaxFailureWaitSeconds(int val) { setAttribute("maxFailureWaitSeconds", val); } @Override public int getWaitIncrementSeconds() { return getAttribute("waitIncrementSeconds", 0); } @Override public void setWaitIncrementSeconds(int val) { setAttribute("waitIncrementSeconds", val); } @Override public long getQuickLoginCheckMilliSeconds() { return getAttribute("quickLoginCheckMilliSeconds", 0L); } @Override public void setQuickLoginCheckMilliSeconds(long val) { setAttribute("quickLoginCheckMilliSeconds", val); } @Override public int getMinimumQuickLoginWaitSeconds() { return getAttribute("minimumQuickLoginWaitSeconds", 0); } @Override public void setMinimumQuickLoginWaitSeconds(int val) { setAttribute("minimumQuickLoginWaitSeconds", val); } @Override public int getMaxDeltaTimeSeconds() { return getAttribute("maxDeltaTimeSeconds", 0); } @Override public void setMaxDeltaTimeSeconds(int val) { setAttribute("maxDeltaTimeSeconds", val); } @Override public int getFailureFactor() { return getAttribute("failureFactor", 0); } @Override public void setFailureFactor(int failureFactor) { setAttribute("failureFactor", failureFactor); } @Override public boolean isVerifyEmail() { return realm.isVerifyEmail(); } @Override public void setVerifyEmail(boolean verifyEmail) { realm.setVerifyEmail(verifyEmail); em.flush(); } @Override public boolean isLoginWithEmailAllowed() { return realm.isLoginWithEmailAllowed(); } @Override public void setLoginWithEmailAllowed(boolean loginWithEmailAllowed) { realm.setLoginWithEmailAllowed(loginWithEmailAllowed); if (loginWithEmailAllowed) realm.setDuplicateEmailsAllowed(false); em.flush(); } @Override public boolean isDuplicateEmailsAllowed() { return realm.isDuplicateEmailsAllowed(); } @Override public void setDuplicateEmailsAllowed(boolean duplicateEmailsAllowed) { realm.setDuplicateEmailsAllowed(duplicateEmailsAllowed); if (duplicateEmailsAllowed) { realm.setLoginWithEmailAllowed(false); realm.setRegistrationEmailAsUsername(false); } em.flush(); } @Override public boolean isResetPasswordAllowed() { return realm.isResetPasswordAllowed(); } @Override public void setResetPasswordAllowed(boolean resetPasswordAllowed) { realm.setResetPasswordAllowed(resetPasswordAllowed); em.flush(); } @Override public boolean isEditUsernameAllowed() { return realm.isEditUsernameAllowed(); } @Override public void setEditUsernameAllowed(boolean editUsernameAllowed) { realm.setEditUsernameAllowed(editUsernameAllowed); em.flush(); } @Override public int getNotBefore() { return realm.getNotBefore(); } @Override public void setNotBefore(int notBefore) { realm.setNotBefore(notBefore); } @Override public boolean isRevokeRefreshToken() { return realm.isRevokeRefreshToken(); } @Override public void setRevokeRefreshToken(boolean revokeRefreshToken) { realm.setRevokeRefreshToken(revokeRefreshToken); } @Override public int getAccessTokenLifespan() { return realm.getAccessTokenLifespan(); } @Override public void setAccessTokenLifespan(int tokenLifespan) { realm.setAccessTokenLifespan(tokenLifespan); em.flush(); } @Override public int getAccessTokenLifespanForImplicitFlow() { return realm.getAccessTokenLifespanForImplicitFlow(); } @Override public void setAccessTokenLifespanForImplicitFlow(int seconds) { realm.setAccessTokenLifespanForImplicitFlow(seconds); } @Override public int getSsoSessionIdleTimeout() { return realm.getSsoSessionIdleTimeout(); } @Override public void setSsoSessionIdleTimeout(int seconds) { realm.setSsoSessionIdleTimeout(seconds); } @Override public int getSsoSessionMaxLifespan() { return realm.getSsoSessionMaxLifespan(); } @Override public void setSsoSessionMaxLifespan(int seconds) { realm.setSsoSessionMaxLifespan(seconds); } @Override public int getOfflineSessionIdleTimeout() { return realm.getOfflineSessionIdleTimeout(); } @Override public void setOfflineSessionIdleTimeout(int seconds) { realm.setOfflineSessionIdleTimeout(seconds); } @Override public int getAccessCodeLifespan() { return realm.getAccessCodeLifespan(); } @Override public void setAccessCodeLifespan(int accessCodeLifespan) { realm.setAccessCodeLifespan(accessCodeLifespan); em.flush(); } @Override public int getAccessCodeLifespanUserAction() { return realm.getAccessCodeLifespanUserAction(); } @Override public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) { realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction); em.flush(); } @Override public int getAccessCodeLifespanLogin() { return realm.getAccessCodeLifespanLogin(); } @Override public void setAccessCodeLifespanLogin(int accessCodeLifespanLogin) { realm.setAccessCodeLifespanLogin(accessCodeLifespanLogin); em.flush(); } @Override public int getActionTokenGeneratedByAdminLifespan() { return getAttribute(RealmAttributes.ACTION_TOKEN_GENERATED_BY_ADMIN_LIFESPAN, 12 * 60 * 60); } @Override public void setActionTokenGeneratedByAdminLifespan(int actionTokenGeneratedByAdminLifespan) { setAttribute(RealmAttributes.ACTION_TOKEN_GENERATED_BY_ADMIN_LIFESPAN, actionTokenGeneratedByAdminLifespan); } @Override public int getActionTokenGeneratedByUserLifespan() { return getAttribute(RealmAttributes.ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN, getAccessCodeLifespanUserAction()); } @Override public void setActionTokenGeneratedByUserLifespan(int actionTokenGeneratedByUserLifespan) { setAttribute(RealmAttributes.ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN, actionTokenGeneratedByUserLifespan); } protected RequiredCredentialModel initRequiredCredentialModel(String type) { RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type); if (model == null) { throw new RuntimeException("Unknown credential type " + type); } return model; } @Override public void addRequiredCredential(String type) { RequiredCredentialModel model = initRequiredCredentialModel(type); addRequiredCredential(model); em.flush(); } public void addRequiredCredential(RequiredCredentialModel model) { RequiredCredentialEntity entity = new RequiredCredentialEntity(); entity.setRealm(realm); entity.setInput(model.isInput()); entity.setSecret(model.isSecret()); entity.setType(model.getType()); entity.setFormLabel(model.getFormLabel()); em.persist(entity); realm.getRequiredCredentials().add(entity); em.flush(); } @Override public void updateRequiredCredentials(Set<String> creds) { Collection<RequiredCredentialEntity> relationships = realm.getRequiredCredentials(); if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>(); Set<String> already = new HashSet<String>(); List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>(); for (RequiredCredentialEntity rel : relationships) { if (!creds.contains(rel.getType())) { remove.add(rel); } else { already.add(rel.getType()); } } for (RequiredCredentialEntity entity : remove) { relationships.remove(entity); em.remove(entity); } for (String cred : creds) { if (!already.contains(cred)) { addRequiredCredential(cred); } } em.flush(); } @Override public List<RequiredCredentialModel> getRequiredCredentials() { Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials(); if (entities == null) return Collections.EMPTY_LIST; List<RequiredCredentialModel> requiredCredentialModels = new LinkedList<>(); for (RequiredCredentialEntity entity : entities) { RequiredCredentialModel model = new RequiredCredentialModel(); model.setFormLabel(entity.getFormLabel()); model.setType(entity.getType()); model.setSecret(entity.isSecret()); model.setInput(entity.isInput()); requiredCredentialModels.add(model); } return Collections.unmodifiableList(requiredCredentialModels); } @Override public List<String> getDefaultRoles() { Collection<RoleEntity> entities = realm.getDefaultRoles(); if (entities == null || entities.isEmpty()) return Collections.emptyList(); List<String> roles = new LinkedList<>(); for (RoleEntity entity : entities) { roles.add(entity.getName()); } return Collections.unmodifiableList(roles); } @Override public void addDefaultRole(String name) { RoleModel role = getRole(name); if (role == null) { role = addRole(name); } Collection<RoleEntity> entities = realm.getDefaultRoles(); for (RoleEntity entity : entities) { if (entity.getId().equals(role.getId())) { return; } } RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em); entities.add(roleEntity); em.flush(); } public static boolean contains(String str, String[] array) { for (String s : array) { if (str.equals(s)) return true; } return false; } @Override public void updateDefaultRoles(String[] defaultRoles) { Collection<RoleEntity> entities = realm.getDefaultRoles(); Set<String> already = new HashSet<String>(); List<RoleEntity> remove = new ArrayList<RoleEntity>(); for (RoleEntity rel : entities) { if (!contains(rel.getName(), defaultRoles)) { remove.add(rel); } else { already.add(rel.getName()); } } for (RoleEntity entity : remove) { entities.remove(entity); } em.flush(); for (String roleName : defaultRoles) { if (!already.contains(roleName)) { addDefaultRole(roleName); } } em.flush(); } @Override public void removeDefaultRoles(String... defaultRoles) { Collection<RoleEntity> entities = realm.getDefaultRoles(); List<RoleEntity> remove = new ArrayList<RoleEntity>(); for (RoleEntity rel : entities) { if (contains(rel.getName(), defaultRoles)) { remove.add(rel); } } for (RoleEntity entity : remove) { entities.remove(entity); } em.flush(); } @Override public List<GroupModel> getDefaultGroups() { Collection<GroupEntity> entities = realm.getDefaultGroups(); if (entities == null || entities.isEmpty()) return Collections.EMPTY_LIST; List<GroupModel> defaultGroups = new LinkedList<>(); for (GroupEntity entity : entities) { defaultGroups.add(session.realms().getGroupById(entity.getId(), this)); } return Collections.unmodifiableList(defaultGroups); } @Override public void addDefaultGroup(GroupModel group) { Collection<GroupEntity> entities = realm.getDefaultGroups(); for (GroupEntity entity : entities) { if (entity.getId().equals(group.getId())) return; } GroupEntity groupEntity = GroupAdapter.toEntity(group, em); realm.getDefaultGroups().add(groupEntity); em.flush(); } @Override public void removeDefaultGroup(GroupModel group) { GroupEntity found = null; for (GroupEntity defaultGroup : realm.getDefaultGroups()) { if (defaultGroup.getId().equals(group.getId())) { found = defaultGroup; break; } } if (found != null) { realm.getDefaultGroups().remove(found); em.flush(); } } @Override public List<ClientModel> getClients() { return session.realms().getClients(this); } @Override public ClientModel addClient(String name) { return session.realms().addClient(this, name); } @Override public ClientModel addClient(String id, String clientId) { return session.realms().addClient(this, id, clientId); } @Override public boolean removeClient(String id) { if (id == null) return false; ClientModel client = getClientById(id); if (client == null) return false; return session.realms().removeClient(id, this); } @Override public ClientModel getClientById(String id) { return session.realms().getClientById(id, this); } @Override public ClientModel getClientByClientId(String clientId) { return session.realms().getClientByClientId(clientId, this); } private static final String BROWSER_HEADER_PREFIX = "_browser_header."; @Override public Map<String, String> getBrowserSecurityHeaders() { Map<String, String> attributes = getAttributes(); if (attributes.isEmpty()) return Collections.EMPTY_MAP; Map<String, String> headers = new HashMap<String, String>(); for (Map.Entry<String, String> entry : attributes.entrySet()) { if (entry.getKey().startsWith(BROWSER_HEADER_PREFIX)) { headers.put(entry.getKey().substring(BROWSER_HEADER_PREFIX.length()), entry.getValue()); } } return Collections.unmodifiableMap(headers); } @Override public void setBrowserSecurityHeaders(Map<String, String> headers) { for (Map.Entry<String, String> entry : headers.entrySet()) { setAttribute(BROWSER_HEADER_PREFIX + entry.getKey(), entry.getValue()); } } @Override public Map<String, String> getSmtpConfig() { Map<String, String> config = new HashMap<String, String>(); config.putAll(realm.getSmtpConfig()); return Collections.unmodifiableMap(config); } @Override public void setSmtpConfig(Map<String, String> smtpConfig) { realm.setSmtpConfig(smtpConfig); em.flush(); } @Override public RoleModel getRole(String name) { return session.realms().getRealmRole(this, name); } @Override public RoleModel addRole(String name) { return session.realms().addRealmRole(this, name); } @Override public RoleModel addRole(String id, String name) { return session.realms().addRealmRole(this, id, name); } @Override public boolean removeRole(RoleModel role) { return session.realms().removeRole(this, role); } @Override public Set<RoleModel> getRoles() { return session.realms().getRealmRoles(this); } @Override public RoleModel getRoleById(String id) { return session.realms().getRoleById(id, this); } @Override public PasswordPolicy getPasswordPolicy() { if (passwordPolicy == null) { passwordPolicy = PasswordPolicy.parse(session, realm.getPasswordPolicy()); } return passwordPolicy; } @Override public void setPasswordPolicy(PasswordPolicy policy) { this.passwordPolicy = policy; realm.setPasswordPolicy(policy.toString()); em.flush(); } @Override public OTPPolicy getOTPPolicy() { if (otpPolicy == null) { otpPolicy = new OTPPolicy(); otpPolicy.setDigits(realm.getOtpPolicyDigits()); otpPolicy.setAlgorithm(realm.getOtpPolicyAlgorithm()); otpPolicy.setInitialCounter(realm.getOtpPolicyInitialCounter()); otpPolicy.setLookAheadWindow(realm.getOtpPolicyLookAheadWindow()); otpPolicy.setType(realm.getOtpPolicyType()); otpPolicy.setPeriod(realm.getOtpPolicyPeriod()); } return otpPolicy; } @Override public void setOTPPolicy(OTPPolicy policy) { realm.setOtpPolicyAlgorithm(policy.getAlgorithm()); realm.setOtpPolicyDigits(policy.getDigits()); realm.setOtpPolicyInitialCounter(policy.getInitialCounter()); realm.setOtpPolicyLookAheadWindow(policy.getLookAheadWindow()); realm.setOtpPolicyType(policy.getType()); realm.setOtpPolicyPeriod(policy.getPeriod()); em.flush(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || !(o instanceof RealmModel)) return false; RealmModel that = (RealmModel) o; return that.getId().equals(getId()); } @Override public int hashCode() { return getId().hashCode(); } @Override public String getLoginTheme() { return realm.getLoginTheme(); } @Override public void setLoginTheme(String name) { realm.setLoginTheme(name); em.flush(); } @Override public String getAccountTheme() { return realm.getAccountTheme(); } @Override public void setAccountTheme(String name) { realm.setAccountTheme(name); em.flush(); } @Override public String getAdminTheme() { return realm.getAdminTheme(); } @Override public void setAdminTheme(String name) { realm.setAdminTheme(name); em.flush(); } @Override public String getEmailTheme() { return realm.getEmailTheme(); } @Override public void setEmailTheme(String name) { realm.setEmailTheme(name); em.flush(); } @Override public boolean isEventsEnabled() { return realm.isEventsEnabled(); } @Override public void setEventsEnabled(boolean enabled) { realm.setEventsEnabled(enabled); em.flush(); } @Override public long getEventsExpiration() { return realm.getEventsExpiration(); } @Override public void setEventsExpiration(long expiration) { realm.setEventsExpiration(expiration); em.flush(); } @Override public Set<String> getEventsListeners() { Set<String> eventsListeners = realm.getEventsListeners(); if (eventsListeners.isEmpty()) return Collections.EMPTY_SET; Set<String> copy = new HashSet<>(); copy.addAll(eventsListeners); return Collections.unmodifiableSet(copy); } @Override public void setEventsListeners(Set<String> listeners) { realm.setEventsListeners(listeners); em.flush(); } @Override public Set<String> getEnabledEventTypes() { Set<String> enabledEventTypes = realm.getEnabledEventTypes(); if (enabledEventTypes.isEmpty()) return Collections.EMPTY_SET; Set<String> copy = new HashSet<>(); copy.addAll(enabledEventTypes); return Collections.unmodifiableSet(copy); } @Override public void setEnabledEventTypes(Set<String> enabledEventTypes) { realm.setEnabledEventTypes(enabledEventTypes); em.flush(); } @Override public boolean isAdminEventsEnabled() { return realm.isAdminEventsEnabled(); } @Override public void setAdminEventsEnabled(boolean enabled) { realm.setAdminEventsEnabled(enabled); em.flush(); } @Override public boolean isAdminEventsDetailsEnabled() { return realm.isAdminEventsDetailsEnabled(); } @Override public void setAdminEventsDetailsEnabled(boolean enabled) { realm.setAdminEventsDetailsEnabled(enabled); em.flush(); } @Override public ClientModel getMasterAdminClient() { ClientEntity masterAdminClient = realm.getMasterAdminClient(); if (masterAdminClient == null) { return null; } RealmModel masterRealm = null; String masterAdminClientRealmId = masterAdminClient.getRealm().getId(); if (masterAdminClientRealmId.equals(getId())) { masterRealm = this; } else { masterRealm = session.realms().getRealm(masterAdminClientRealmId); } return session.realms().getClientById(masterAdminClient.getId(), masterRealm); } @Override public void setMasterAdminClient(ClientModel client) { ClientEntity appEntity = client !=null ? em.getReference(ClientEntity.class, client.getId()) : null; realm.setMasterAdminClient(appEntity); em.flush(); } @Override public List<IdentityProviderModel> getIdentityProviders() { List<IdentityProviderEntity> entities = realm.getIdentityProviders(); if (entities.isEmpty()) return Collections.EMPTY_LIST; List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>(); for (IdentityProviderEntity entity: entities) { IdentityProviderModel identityProviderModel = entityToModel(entity); identityProviders.add(identityProviderModel); } return Collections.unmodifiableList(identityProviders); } private IdentityProviderModel entityToModel(IdentityProviderEntity entity) { IdentityProviderModel identityProviderModel = new IdentityProviderModel(); identityProviderModel.setProviderId(entity.getProviderId()); identityProviderModel.setAlias(entity.getAlias()); identityProviderModel.setDisplayName(entity.getDisplayName()); identityProviderModel.setInternalId(entity.getInternalId()); Map<String, String> config = entity.getConfig(); Map<String, String> copy = new HashMap<>(); copy.putAll(config); identityProviderModel.setConfig(copy); identityProviderModel.setEnabled(entity.isEnabled()); identityProviderModel.setLinkOnly(entity.isLinkOnly()); identityProviderModel.setTrustEmail(entity.isTrustEmail()); identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault()); identityProviderModel.setFirstBrokerLoginFlowId(entity.getFirstBrokerLoginFlowId()); identityProviderModel.setPostBrokerLoginFlowId(entity.getPostBrokerLoginFlowId()); identityProviderModel.setStoreToken(entity.isStoreToken()); identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate()); return identityProviderModel; } @Override public IdentityProviderModel getIdentityProviderByAlias(String alias) { for (IdentityProviderModel identityProviderModel : getIdentityProviders()) { if (identityProviderModel.getAlias().equals(alias)) { return identityProviderModel; } } return null; } @Override public void addIdentityProvider(IdentityProviderModel identityProvider) { IdentityProviderEntity entity = new IdentityProviderEntity(); entity.setInternalId(KeycloakModelUtils.generateId()); entity.setAlias(identityProvider.getAlias()); entity.setDisplayName(identityProvider.getDisplayName()); entity.setProviderId(identityProvider.getProviderId()); entity.setEnabled(identityProvider.isEnabled()); entity.setStoreToken(identityProvider.isStoreToken()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setTrustEmail(identityProvider.isTrustEmail()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId()); entity.setPostBrokerLoginFlowId(identityProvider.getPostBrokerLoginFlowId()); entity.setConfig(identityProvider.getConfig()); entity.setLinkOnly(identityProvider.isLinkOnly()); realm.addIdentityProvider(entity); identityProvider.setInternalId(entity.getInternalId()); em.persist(entity); em.flush(); } @Override public void removeIdentityProviderByAlias(String alias) { for (IdentityProviderEntity entity : realm.getIdentityProviders()) { if (entity.getAlias().equals(alias)) { IdentityProviderModel model = entityToModel(entity); em.remove(entity); em.flush(); session.getKeycloakSessionFactory().publish(new RealmModel.IdentityProviderRemovedEvent() { @Override public RealmModel getRealm() { return RealmAdapter.this; } @Override public IdentityProviderModel getRemovedIdentityProvider() { return model; } @Override public KeycloakSession getKeycloakSession() { return session; } }); } } } @Override public void updateIdentityProvider(IdentityProviderModel identityProvider) { for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) { if (entity.getInternalId().equals(identityProvider.getInternalId())) { entity.setAlias(identityProvider.getAlias()); entity.setDisplayName(identityProvider.getDisplayName()); entity.setEnabled(identityProvider.isEnabled()); entity.setTrustEmail(identityProvider.isTrustEmail()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId()); entity.setPostBrokerLoginFlowId(identityProvider.getPostBrokerLoginFlowId()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setStoreToken(identityProvider.isStoreToken()); entity.setConfig(identityProvider.getConfig()); entity.setLinkOnly(identityProvider.isLinkOnly()); } } em.flush(); session.getKeycloakSessionFactory().publish(new RealmModel.IdentityProviderUpdatedEvent() { @Override public RealmModel getRealm() { return RealmAdapter.this; } @Override public IdentityProviderModel getUpdatedIdentityProvider() { return identityProvider; } @Override public KeycloakSession getKeycloakSession() { return session; } }); } @Override public boolean isIdentityFederationEnabled() { return !this.realm.getIdentityProviders().isEmpty(); } @Override public boolean isInternationalizationEnabled() { return realm.isInternationalizationEnabled(); } @Override public void setInternationalizationEnabled(boolean enabled) { realm.setInternationalizationEnabled(enabled); em.flush(); } @Override public Set<String> getSupportedLocales() { Set<String> supportedLocales = realm.getSupportedLocales(); if (supportedLocales == null || supportedLocales.isEmpty()) return Collections.EMPTY_SET; Set<String> copy = new HashSet<>(); copy.addAll(supportedLocales); return Collections.unmodifiableSet(copy); } @Override public void setSupportedLocales(Set<String> locales) { realm.setSupportedLocales(locales); em.flush(); } @Override public String getDefaultLocale() { return realm.getDefaultLocale(); } @Override public void setDefaultLocale(String locale) { realm.setDefaultLocale(locale); em.flush(); } @Override public Set<IdentityProviderMapperModel> getIdentityProviderMappers() { Collection<IdentityProviderMapperEntity> entities = this.realm.getIdentityProviderMappers(); if (entities.isEmpty()) return Collections.EMPTY_SET; Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>(); for (IdentityProviderMapperEntity entity : entities) { IdentityProviderMapperModel mapping = entityToModel(entity); mappings.add(mapping); } return Collections.unmodifiableSet(mappings); } @Override public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) { Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>(); for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { if (!entity.getIdentityProviderAlias().equals(brokerAlias)) { continue; } IdentityProviderMapperModel mapping = entityToModel(entity); mappings.add(mapping); } return mappings; } @Override public IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model) { if (getIdentityProviderMapperByName(model.getIdentityProviderAlias(), model.getName()) != null) { throw new RuntimeException("identity provider mapper name must be unique per identity provider"); } String id = KeycloakModelUtils.generateId(); IdentityProviderMapperEntity entity = new IdentityProviderMapperEntity(); entity.setId(id); entity.setName(model.getName()); entity.setIdentityProviderAlias(model.getIdentityProviderAlias()); entity.setIdentityProviderMapper(model.getIdentityProviderMapper()); entity.setRealm(this.realm); entity.setConfig(model.getConfig()); em.persist(entity); this.realm.getIdentityProviderMappers().add(entity); return entityToModel(entity); } protected IdentityProviderMapperEntity getIdentityProviderMapperEntity(String id) { for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { if (entity.getId().equals(id)) { return entity; } } return null; } protected IdentityProviderMapperEntity getIdentityProviderMapperEntityByName(String alias, String name) { for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) { if (entity.getIdentityProviderAlias().equals(alias) && entity.getName().equals(name)) { return entity; } } return null; } @Override public void removeIdentityProviderMapper(IdentityProviderMapperModel mapping) { IdentityProviderMapperEntity toDelete = getIdentityProviderMapperEntity(mapping.getId()); if (toDelete != null) { this.realm.getIdentityProviderMappers().remove(toDelete); em.remove(toDelete); } } @Override public void updateIdentityProviderMapper(IdentityProviderMapperModel mapping) { IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(mapping.getId()); entity.setIdentityProviderAlias(mapping.getIdentityProviderAlias()); entity.setIdentityProviderMapper(mapping.getIdentityProviderMapper()); if (entity.getConfig() == null) { entity.setConfig(mapping.getConfig()); } else { entity.getConfig().clear(); entity.getConfig().putAll(mapping.getConfig()); } em.flush(); } @Override public IdentityProviderMapperModel getIdentityProviderMapperById(String id) { IdentityProviderMapperEntity entity = getIdentityProviderMapperEntity(id); if (entity == null) return null; return entityToModel(entity); } @Override public IdentityProviderMapperModel getIdentityProviderMapperByName(String alias, String name) { IdentityProviderMapperEntity entity = getIdentityProviderMapperEntityByName(alias, name); if (entity == null) return null; return entityToModel(entity); } protected IdentityProviderMapperModel entityToModel(IdentityProviderMapperEntity entity) { IdentityProviderMapperModel mapping = new IdentityProviderMapperModel(); mapping.setId(entity.getId()); mapping.setName(entity.getName()); mapping.setIdentityProviderAlias(entity.getIdentityProviderAlias()); mapping.setIdentityProviderMapper(entity.getIdentityProviderMapper()); Map<String, String> config = new HashMap<String, String>(); if (entity.getConfig() != null) config.putAll(entity.getConfig()); mapping.setConfig(config); return mapping; } @Override public AuthenticationFlowModel getBrowserFlow() { String flowId = realm.getBrowserFlow(); if (flowId == null) return null; return getAuthenticationFlowById(flowId); } @Override public void setBrowserFlow(AuthenticationFlowModel flow) { realm.setBrowserFlow(flow.getId()); } @Override public AuthenticationFlowModel getRegistrationFlow() { String flowId = realm.getRegistrationFlow(); if (flowId == null) return null; return getAuthenticationFlowById(flowId); } @Override public void setRegistrationFlow(AuthenticationFlowModel flow) { realm.setRegistrationFlow(flow.getId()); } @Override public AuthenticationFlowModel getDirectGrantFlow() { String flowId = realm.getDirectGrantFlow(); if (flowId == null) return null; return getAuthenticationFlowById(flowId); } @Override public void setDirectGrantFlow(AuthenticationFlowModel flow) { realm.setDirectGrantFlow(flow.getId()); } @Override public AuthenticationFlowModel getResetCredentialsFlow() { String flowId = realm.getResetCredentialsFlow(); if (flowId == null) return null; return getAuthenticationFlowById(flowId); } @Override public void setResetCredentialsFlow(AuthenticationFlowModel flow) { realm.setResetCredentialsFlow(flow.getId()); } public AuthenticationFlowModel getClientAuthenticationFlow() { String flowId = realm.getClientAuthenticationFlow(); if (flowId == null) return null; return getAuthenticationFlowById(flowId); } public void setClientAuthenticationFlow(AuthenticationFlowModel flow) { realm.setClientAuthenticationFlow(flow.getId()); } @Override public List<AuthenticationFlowModel> getAuthenticationFlows() { TypedQuery<AuthenticationFlowEntity> query = em.createNamedQuery("getAuthenticationFlowsByRealm", AuthenticationFlowEntity.class); query.setParameter("realm", realm); List<AuthenticationFlowEntity> flows = query.getResultList(); if (flows.isEmpty()) return Collections.EMPTY_LIST; List<AuthenticationFlowModel> models = new LinkedList<>(); for (AuthenticationFlowEntity entity : flows) { AuthenticationFlowModel model = entityToModel(entity); models.add(model); } return Collections.unmodifiableList(models); } @Override public AuthenticationFlowModel getFlowByAlias(String alias) { for (AuthenticationFlowModel flow : getAuthenticationFlows()) { if (flow.getAlias().equals(alias)) { return flow; } } return null; } @Override public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) { for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) { if (config.getAlias().equals(alias)) { return config; } } return null; } protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) { AuthenticationFlowModel model = new AuthenticationFlowModel(); model.setId(entity.getId()); model.setAlias(entity.getAlias()); model.setProviderId(entity.getProviderId()); model.setDescription(entity.getDescription()); model.setBuiltIn(entity.isBuiltIn()); model.setTopLevel(entity.isTopLevel()); return model; } @Override public AuthenticationFlowModel getAuthenticationFlowById(String id) { AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, id); if (entity == null) return null; return entityToModel(entity); } @Override public void removeAuthenticationFlow(AuthenticationFlowModel model) { if (KeycloakModelUtils.isFlowUsed(this, model)) { throw new ModelException("Cannot remove authentication flow, it is currently in use"); } AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId()); em.remove(entity); em.flush(); } @Override public void updateAuthenticationFlow(AuthenticationFlowModel model) { AuthenticationFlowEntity entity = em.find(AuthenticationFlowEntity.class, model.getId()); if (entity == null) return; entity.setAlias(model.getAlias()); entity.setDescription(model.getDescription()); entity.setProviderId(model.getProviderId()); entity.setBuiltIn(model.isBuiltIn()); entity.setTopLevel(model.isTopLevel()); } @Override public AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model) { AuthenticationFlowEntity entity = new AuthenticationFlowEntity(); String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); entity.setId(id); entity.setAlias(model.getAlias()); entity.setDescription(model.getDescription()); entity.setProviderId(model.getProviderId()); entity.setBuiltIn(model.isBuiltIn()); entity.setTopLevel(model.isTopLevel()); entity.setRealm(realm); realm.getAuthenticationFlows().add(entity); em.persist(entity); em.flush(); model.setId(entity.getId()); return model; } @Override public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) { TypedQuery<AuthenticationExecutionEntity> query = em.createNamedQuery("getAuthenticationExecutionsByFlow", AuthenticationExecutionEntity.class); AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId); query.setParameter("realm", realm); query.setParameter("parentFlow", flow); List<AuthenticationExecutionEntity> queryResult = query.getResultList(); if (queryResult.isEmpty()) return Collections.EMPTY_LIST; List<AuthenticationExecutionModel> executions = new LinkedList<>(); for (AuthenticationExecutionEntity entity : queryResult) { AuthenticationExecutionModel model = entityToModel(entity); executions.add(model); } Collections.sort(executions, AuthenticationExecutionModel.ExecutionComparator.SINGLETON); return Collections.unmodifiableList(executions); } public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) { AuthenticationExecutionModel model = new AuthenticationExecutionModel(); model.setId(entity.getId()); model.setRequirement(entity.getRequirement()); model.setPriority(entity.getPriority()); model.setAuthenticator(entity.getAuthenticator()); model.setFlowId(entity.getFlowId()); model.setParentFlow(entity.getParentFlow().getId()); model.setAuthenticatorFlow(entity.isAutheticatorFlow()); model.setAuthenticatorConfig(entity.getAuthenticatorConfig()); return model; } @Override public AuthenticationExecutionModel getAuthenticationExecutionById(String id) { AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, id); if (entity == null) return null; return entityToModel(entity); } @Override public AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model) { AuthenticationExecutionEntity entity = new AuthenticationExecutionEntity(); String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); entity.setId(id); entity.setAuthenticator(model.getAuthenticator()); entity.setPriority(model.getPriority()); entity.setFlowId(model.getFlowId()); entity.setRequirement(model.getRequirement()); entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); AuthenticationFlowEntity flow = em.find(AuthenticationFlowEntity.class, model.getParentFlow()); entity.setParentFlow(flow); flow.getExecutions().add(entity); entity.setRealm(realm); entity.setAutheticatorFlow(model.isAuthenticatorFlow()); em.persist(entity); em.flush(); model.setId(entity.getId()); return model; } @Override public void updateAuthenticatorExecution(AuthenticationExecutionModel model) { AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId()); if (entity == null) return; entity.setAutheticatorFlow(model.isAuthenticatorFlow()); entity.setAuthenticator(model.getAuthenticator()); entity.setPriority(model.getPriority()); entity.setRequirement(model.getRequirement()); entity.setAuthenticatorConfig(model.getAuthenticatorConfig()); entity.setFlowId(model.getFlowId()); em.flush(); } @Override public void removeAuthenticatorExecution(AuthenticationExecutionModel model) { AuthenticationExecutionEntity entity = em.find(AuthenticationExecutionEntity.class, model.getId()); if (entity == null) return; em.remove(entity); em.flush(); } @Override public AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model) { AuthenticatorConfigEntity auth = new AuthenticatorConfigEntity(); String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); auth.setId(id); auth.setAlias(model.getAlias()); auth.setRealm(realm); auth.setConfig(model.getConfig()); realm.getAuthenticatorConfigs().add(auth); em.persist(auth); em.flush(); model.setId(auth.getId()); return model; } @Override public void removeAuthenticatorConfig(AuthenticatorConfigModel model) { AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId()); if (entity == null) return; em.remove(entity); em.flush(); } @Override public AuthenticatorConfigModel getAuthenticatorConfigById(String id) { AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, id); if (entity == null) return null; return entityToModel(entity); } public AuthenticatorConfigModel entityToModel(AuthenticatorConfigEntity entity) { AuthenticatorConfigModel model = new AuthenticatorConfigModel(); model.setId(entity.getId()); model.setAlias(entity.getAlias()); Map<String, String> config = new HashMap<>(); if (entity.getConfig() != null) config.putAll(entity.getConfig()); model.setConfig(config); return model; } @Override public void updateAuthenticatorConfig(AuthenticatorConfigModel model) { AuthenticatorConfigEntity entity = em.find(AuthenticatorConfigEntity.class, model.getId()); if (entity == null) return; entity.setAlias(model.getAlias()); if (entity.getConfig() == null) { entity.setConfig(model.getConfig()); } else { entity.getConfig().clear(); entity.getConfig().putAll(model.getConfig()); } em.flush(); } @Override public List<AuthenticatorConfigModel> getAuthenticatorConfigs() { Collection<AuthenticatorConfigEntity> entities = realm.getAuthenticatorConfigs(); if (entities.isEmpty()) return Collections.EMPTY_LIST; List<AuthenticatorConfigModel> authenticators = new LinkedList<>(); for (AuthenticatorConfigEntity entity : entities) { authenticators.add(entityToModel(entity)); } return Collections.unmodifiableList(authenticators); } @Override public RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model) { RequiredActionProviderEntity auth = new RequiredActionProviderEntity(); String id = (model.getId() == null) ? KeycloakModelUtils.generateId(): model.getId(); auth.setId(id); auth.setAlias(model.getAlias()); auth.setName(model.getName()); auth.setRealm(realm); auth.setProviderId(model.getProviderId()); auth.setConfig(model.getConfig()); auth.setEnabled(model.isEnabled()); auth.setDefaultAction(model.isDefaultAction()); realm.getRequiredActionProviders().add(auth); em.persist(auth); em.flush(); model.setId(auth.getId()); return model; } @Override public void removeRequiredActionProvider(RequiredActionProviderModel model) { RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId()); if (entity == null) return; em.remove(entity); em.flush(); } @Override public RequiredActionProviderModel getRequiredActionProviderById(String id) { RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, id); if (entity == null) return null; return entityToModel(entity); } public RequiredActionProviderModel entityToModel(RequiredActionProviderEntity entity) { RequiredActionProviderModel model = new RequiredActionProviderModel(); model.setId(entity.getId()); model.setProviderId(entity.getProviderId()); model.setAlias(entity.getAlias()); model.setEnabled(entity.isEnabled()); model.setDefaultAction(entity.isDefaultAction()); model.setName(entity.getName()); Map<String, String> config = new HashMap<>(); if (entity.getConfig() != null) config.putAll(entity.getConfig()); model.setConfig(config); return model; } @Override public void updateRequiredActionProvider(RequiredActionProviderModel model) { RequiredActionProviderEntity entity = em.find(RequiredActionProviderEntity.class, model.getId()); if (entity == null) return; entity.setAlias(model.getAlias()); entity.setProviderId(model.getProviderId()); entity.setEnabled(model.isEnabled()); entity.setDefaultAction(model.isDefaultAction()); entity.setName(model.getName()); if (entity.getConfig() == null) { entity.setConfig(model.getConfig()); } else { entity.getConfig().clear(); entity.getConfig().putAll(model.getConfig()); } em.flush(); } @Override public List<RequiredActionProviderModel> getRequiredActionProviders() { Collection<RequiredActionProviderEntity> entities = realm.getRequiredActionProviders(); if (entities.isEmpty()) return Collections.EMPTY_LIST; List<RequiredActionProviderModel> actions = new LinkedList<>(); for (RequiredActionProviderEntity entity : entities) { actions.add(entityToModel(entity)); } return Collections.unmodifiableList(actions); } @Override public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) { for (RequiredActionProviderModel action : getRequiredActionProviders()) { if (action.getAlias().equals(alias)) return action; } return null; } @Override public GroupModel createGroup(String name) { return session.realms().createGroup(this, name); } @Override public GroupModel createGroup(String id, String name) { return session.realms().createGroup(this, id, name); } @Override public void moveGroup(GroupModel group, GroupModel toParent) { session.realms().moveGroup(this, group, toParent); } @Override public GroupModel getGroupById(String id) { return session.realms().getGroupById(id, this); } @Override public List<GroupModel> getGroups() { return session.realms().getGroups(this); } @Override public List<GroupModel> getTopLevelGroups() { return session.realms().getTopLevelGroups(this); } @Override public boolean removeGroup(GroupModel group) { return session.realms().removeGroup(this, group); } @Override public List<ClientTemplateModel> getClientTemplates() { Collection<ClientTemplateEntity> entities = realm.getClientTemplates(); if (entities == null || entities.isEmpty()) return Collections.EMPTY_LIST; List<ClientTemplateModel> list = new LinkedList<>(); for (ClientTemplateEntity entity : entities) { list.add(session.realms().getClientTemplateById(entity.getId(), this)); } return Collections.unmodifiableList(list); } @Override public ClientTemplateModel addClientTemplate(String name) { return this.addClientTemplate(KeycloakModelUtils.generateId(), name); } @Override public ClientTemplateModel addClientTemplate(String id, String name) { ClientTemplateEntity entity = new ClientTemplateEntity(); entity.setId(id); entity.setName(name); entity.setRealm(realm); realm.getClientTemplates().add(entity); em.persist(entity); em.flush(); final ClientTemplateModel resource = new ClientTemplateAdapter(this, em, session, entity); em.flush(); return resource; } @Override public boolean removeClientTemplate(String id) { if (id == null) return false; ClientTemplateModel client = getClientTemplateById(id); if (client == null) return false; if (KeycloakModelUtils.isClientTemplateUsed(this, client)) { throw new ModelException("Cannot remove client template, it is currently in use"); } ClientTemplateEntity clientEntity = null; Iterator<ClientTemplateEntity> it = realm.getClientTemplates().iterator(); while (it.hasNext()) { ClientTemplateEntity ae = it.next(); if (ae.getId().equals(id)) { clientEntity = ae; it.remove(); break; } } if (client == null) { return false; } em.createNamedQuery("deleteTemplateScopeMappingByClient").setParameter("template", clientEntity).executeUpdate(); em.flush(); em.remove(clientEntity); em.flush(); return true; } @Override public ClientTemplateModel getClientTemplateById(String id) { return session.realms().getClientTemplateById(id, this); } @Override public ComponentModel addComponentModel(ComponentModel model) { model = importComponentModel(model); ComponentUtil.notifyCreated(session, this, model); return model; } /** * This just exists for testing purposes * */ public static final String COMPONENT_PROVIDER_EXISTS_DISABLED = "component.provider.exists.disabled"; @Override public ComponentModel importComponentModel(ComponentModel model) { ComponentFactory componentFactory = null; try { componentFactory = ComponentUtil.getComponentFactory(session, model); if (componentFactory == null && System.getProperty(COMPONENT_PROVIDER_EXISTS_DISABLED) == null) { throw new IllegalArgumentException("Invalid component type"); } componentFactory.validateConfiguration(session, this, model); } catch (Exception e) { if (System.getProperty(COMPONENT_PROVIDER_EXISTS_DISABLED) == null) { throw e; } } ComponentEntity c = new ComponentEntity(); if (model.getId() == null) { c.setId(KeycloakModelUtils.generateId()); } else { c.setId(model.getId()); } c.setName(model.getName()); c.setParentId(model.getParentId()); if (model.getParentId() == null) { c.setParentId(this.getId()); model.setParentId(this.getId()); } c.setProviderType(model.getProviderType()); c.setProviderId(model.getProviderId()); c.setSubType(model.getSubType()); c.setRealm(realm); em.persist(c); setConfig(model, c); model.setId(c.getId()); return model; } protected void setConfig(ComponentModel model, ComponentEntity c) { for (String key : model.getConfig().keySet()) { List<String> vals = model.getConfig().get(key); if (vals == null) { continue; } for (String val : vals) { ComponentConfigEntity config = new ComponentConfigEntity(); config.setId(KeycloakModelUtils.generateId()); config.setName(key); config.setValue(val); config.setComponent(c); em.persist(config); } } } @Override public void updateComponent(ComponentModel component) { ComponentUtil.getComponentFactory(session, component).validateConfiguration(session, this, component); ComponentEntity c = em.find(ComponentEntity.class, component.getId()); if (c == null) return; ComponentModel old = entityToModel(c); c.setName(component.getName()); c.setProviderId(component.getProviderId()); c.setProviderType(component.getProviderType()); c.setParentId(component.getParentId()); c.setSubType(component.getSubType()); em.createNamedQuery("deleteComponentConfigByComponent").setParameter("component", c).executeUpdate(); em.flush(); setConfig(component, c); ComponentUtil.notifyUpdated(session, this, old, component); } @Override public void removeComponent(ComponentModel component) { ComponentEntity c = em.find(ComponentEntity.class, component.getId()); if (c == null) return; session.users().preRemove(this, component); removeComponents(component.getId()); em.createNamedQuery("deleteComponentConfigByComponent").setParameter("component", c).executeUpdate(); em.remove(c); } @Override public void removeComponents(String parentId) { TypedQuery<String> query = em.createNamedQuery("getComponentIdsByParent", String.class) .setParameter("realm", realm) .setParameter("parentId", parentId); List<String> results = query.getResultList(); if (results.isEmpty()) return; for (String id : results) { session.users().preRemove(this, getComponent(id)); } em.createNamedQuery("deleteComponentConfigByParent").setParameter("parentId", parentId).executeUpdate(); em.createNamedQuery("deleteComponentByParent").setParameter("parentId", parentId).executeUpdate(); } @Override public List<ComponentModel> getComponents(String parentId, String providerType) { if (parentId == null) parentId = getId(); TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponentsByParentAndType", ComponentEntity.class) .setParameter("realm", realm) .setParameter("parentId", parentId) .setParameter("providerType", providerType); List<ComponentEntity> results = query.getResultList(); List<ComponentModel> rtn = new LinkedList<>(); for (ComponentEntity c : results) { ComponentModel model = entityToModel(c); rtn.add(model); } return rtn; } @Override public List<ComponentModel> getComponents(String parentId) { TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponentsByParent", ComponentEntity.class) .setParameter("realm", realm) .setParameter("parentId", parentId); List<ComponentEntity> results = query.getResultList(); List<ComponentModel> rtn = new LinkedList<>(); for (ComponentEntity c : results) { ComponentModel model = entityToModel(c); rtn.add(model); } return rtn; } protected ComponentModel entityToModel(ComponentEntity c) { ComponentModel model = new ComponentModel(); model.setId(c.getId()); model.setName(c.getName()); model.setProviderType(c.getProviderType()); model.setProviderId(c.getProviderId()); model.setSubType(c.getSubType()); model.setParentId(c.getParentId()); MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>(); TypedQuery<ComponentConfigEntity> configQuery = em.createNamedQuery("getComponentConfig", ComponentConfigEntity.class) .setParameter("component", c); List<ComponentConfigEntity> configResults = configQuery.getResultList(); for (ComponentConfigEntity configEntity : configResults) { config.add(configEntity.getName(), configEntity.getValue()); } model.setConfig(config); return model; } @Override public List<ComponentModel> getComponents() { TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponents", ComponentEntity.class) .setParameter("realm", realm); List<ComponentEntity> results = query.getResultList(); List<ComponentModel> rtn = new LinkedList<>(); for (ComponentEntity c : results) { ComponentModel model = entityToModel(c); rtn.add(model); } return rtn; } @Override public ComponentModel getComponent(String id) { ComponentEntity c = em.find(ComponentEntity.class, id); if (c == null) return null; return entityToModel(c); } }