RealmAdapter.java

1272 lines | 35.298 kB Blame History Raw Download
package org.keycloak.models.jpa;

import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
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;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

import org.keycloak.enums.SslRequired;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
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.UserFederationProviderModel;
import org.keycloak.models.jpa.entities.ApplicationEntity;
import org.keycloak.models.jpa.entities.IdentityProviderEntity;
import org.keycloak.models.jpa.entities.OAuthClientEntity;
import org.keycloak.models.jpa.entities.RealmAttributeEntity;
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.UserFederationProviderEntity;
import org.keycloak.models.utils.KeycloakModelUtils;

/**
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 * @version $Revision: 1 $
 */
public class RealmAdapter implements RealmModel {
	protected RealmEntity realm;
	protected EntityManager em;
	protected volatile transient PublicKey publicKey;
	protected volatile transient PrivateKey privateKey;
	protected volatile transient X509Certificate certificate;
	protected volatile transient Key codeSecretKey;
	protected KeycloakSession session;
	private PasswordPolicy passwordPolicy;

	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 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 isPasswordCredentialGrantAllowed() {
		return realm.isPasswordCredentialGrantAllowed();
	}

	@Override
	public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
		realm.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
		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);
		em.flush();
	}

	@Override
	public boolean isRememberMe() {
		return realm.isRememberMe();
	}

	@Override
	public void setRememberMe(boolean rememberMe) {
		realm.setRememberMe(rememberMe);
		em.flush();
	}

	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);
	}

	public void setAttribute(String name, Boolean value) {
		setAttribute(name, value.toString());
	}

	public void setAttribute(String name, Integer value) {
		setAttribute(name, value.toString());
	}

	public void setAttribute(String name, Long value) {
		setAttribute(name, value.toString());
	}

	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);
			}
		}
	}

	public String getAttribute(String name) {
		for (RealmAttributeEntity attr : realm.getAttributes()) {
			if (attr.getName().equals(name)) {
				return attr.getValue();
			}
		}
		return null;
	}

	public Integer getAttribute(String name, Integer defaultValue) {
		String v = getAttribute(name);
		return v != null ? Integer.parseInt(v) : defaultValue;

	}

	public Long getAttribute(String name, Long defaultValue) {
		String v = getAttribute(name);
		return v != null ? Long.parseLong(v) : defaultValue;

	}

	public Boolean getAttribute(String name, Boolean defaultValue) {
		String v = getAttribute(name);
		return v != null ? Boolean.parseBoolean(v) : defaultValue;

	}

	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 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 isResetPasswordAllowed() {
		return realm.isResetPasswordAllowed();
	}

	@Override
	public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
		realm.setResetPasswordAllowed(resetPasswordAllowed);
		em.flush();
	}

	@Override
	public int getNotBefore() {
		return realm.getNotBefore();
	}

	@Override
	public void setNotBefore(int notBefore) {
		realm.setNotBefore(notBefore);
	}

	@Override
	public int getAccessTokenLifespan() {
		return realm.getAccessTokenLifespan();
	}

	@Override
	public void setAccessTokenLifespan(int tokenLifespan) {
		realm.setAccessTokenLifespan(tokenLifespan);
		em.flush();
	}

	@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 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 String getPublicKeyPem() {
		return realm.getPublicKeyPem();
	}

	@Override
	public void setPublicKeyPem(String publicKeyPem) {
		realm.setPublicKeyPem(publicKeyPem);
		em.flush();
	}

	@Override
	public X509Certificate getCertificate() {
		if (certificate != null)
			return certificate;
		certificate = KeycloakModelUtils.getCertificate(getCertificatePem());
		return certificate;
	}

	@Override
	public void setCertificate(X509Certificate certificate) {
		this.certificate = certificate;
		String certificatePem = KeycloakModelUtils.getPemFromCertificate(certificate);
		setCertificatePem(certificatePem);

	}

	@Override
	public String getCertificatePem() {
		return realm.getCertificatePem();
	}

	@Override
	public void setCertificatePem(String certificate) {
		realm.setCertificatePem(certificate);

	}

	@Override
	public String getPrivateKeyPem() {
		return realm.getPrivateKeyPem();
	}

	@Override
	public void setPrivateKeyPem(String privateKeyPem) {
		realm.setPrivateKeyPem(privateKeyPem);
		em.flush();
	}

	@Override
	public PublicKey getPublicKey() {
		if (publicKey != null)
			return publicKey;
		publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
		return publicKey;
	}

	@Override
	public void setPublicKey(PublicKey publicKey) {
		this.publicKey = publicKey;
		String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
		setPublicKeyPem(publicKeyPem);
	}

	@Override
	public PrivateKey getPrivateKey() {
		if (privateKey != null)
			return privateKey;
		privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
		return privateKey;
	}

	@Override
	public void setPrivateKey(PrivateKey privateKey) {
		this.privateKey = privateKey;
		String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
		setPrivateKeyPem(privateKeyPem);
	}

	@Override
	public String getCodeSecret() {
		return realm.getCodeSecret();
	}

	@Override
	public Key getCodeSecretKey() {
		if (codeSecretKey == null) {
			codeSecretKey = KeycloakModelUtils.getSecretKey(getCodeSecret());
		}
		return codeSecretKey;
	}

	@Override
	public void setCodeSecret(String codeSecret) {
		realm.setCodeSecret(codeSecret);
	}

	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() {
		List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
		Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
		if (entities == null)
			return requiredCredentialModels;
		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 requiredCredentialModels; // To change body of implemented methods use File | Settings | File Templates.
	}

	@Override
	public List<String> getDefaultRoles() {
		Collection<RoleEntity> entities = realm.getDefaultRoles();
		List<String> roles = new ArrayList<String>();
		if (entities == null)
			return roles;
		for (RoleEntity entity : entities) {
			roles.add(entity.getName());
		}
		return 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 ClientModel findClient(String clientId) {
		ClientModel model = getApplicationByName(clientId);
		if (model != null)
			return model;
		return getOAuthClient(clientId);
	}

	@Override
	public ClientModel findClientById(String id) {
		ClientModel model = getApplicationById(id);
		if (model != null)
			return model;
		return getOAuthClientById(id);
	}

	@Override
	public Map<String, ApplicationModel> getApplicationNameMap() {
		Map<String, ApplicationModel> map = new HashMap<String, ApplicationModel>();
		for (ApplicationModel app : getApplications()) {
			map.put(app.getName(), app);
		}
		return map; // To change body of implemented methods use File | Settings | File Templates.
	}

	@Override
	public List<ApplicationModel> getApplications() {
		List<ApplicationModel> list = new ArrayList<ApplicationModel>();
		if (realm.getApplications() == null)
			return list;
		for (ApplicationEntity entity : realm.getApplications()) {
			list.add(new ApplicationAdapter(this, em, session, entity));
		}
		return list;
	}

	@Override
	public ApplicationModel addApplication(String name) {
		return this.addApplication(KeycloakModelUtils.generateId(), name);
	}

	@Override
	public ApplicationModel addApplication(String id, String name) {
		ApplicationEntity applicationData = new ApplicationEntity();
		applicationData.setId(id);
		applicationData.setName(name);
		applicationData.setEnabled(true);
		applicationData.setRealm(realm);
		realm.getApplications().add(applicationData);
		em.persist(applicationData);
		em.flush();
		final ApplicationModel resource = new ApplicationAdapter(this, em, session, applicationData);
		em.flush();
		session.getKeycloakSessionFactory().publish(new ApplicationCreationEvent() {
			@Override
			public ApplicationModel getCreatedApplication() {
				return resource;
			}

			@Override
			public ClientModel getCreatedClient() {
				return resource;
			}
		});
		return resource;
	}

	@Override
	public boolean removeApplication(String id) {
		if (id == null)
			return false;
		ApplicationModel application = getApplicationById(id);
		if (application == null)
			return false;

		for (RoleModel role : application.getRoles()) {
			application.removeRole(role);
		}

		ApplicationEntity applicationEntity = null;
		Iterator<ApplicationEntity> it = realm.getApplications().iterator();
		while (it.hasNext()) {
			ApplicationEntity ae = it.next();
			if (ae.getId().equals(id)) {
				applicationEntity = ae;
				it.remove();
				break;
			}
		}
		for (ApplicationEntity a : realm.getApplications()) {
			if (a.getId().equals(id)) {
				applicationEntity = a;
			}
		}
		if (application == null) {
			return false;
		}
		em.remove(applicationEntity);
		em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", applicationEntity).executeUpdate();
		em.flush();

		return true;
	}

	@Override
	public ApplicationModel getApplicationById(String id) {
		return session.realms().getApplicationById(id, this);
	}

	@Override
	public ApplicationModel getApplicationByName(String name) {
		return getApplicationNameMap().get(name);
	}

	@Override
	public OAuthClientModel addOAuthClient(String name) {
		return this.addOAuthClient(KeycloakModelUtils.generateId(), name);
	}

	@Override
	public OAuthClientModel addOAuthClient(String id, String name) {
		OAuthClientEntity data = new OAuthClientEntity();
		data.setId(id);
		data.setEnabled(true);
		data.setName(name);
		data.setRealm(realm);
		em.persist(data);
		em.flush();
		final OAuthClientModel model = new OAuthClientAdapter(this, data, em);
		em.flush();
		session.getKeycloakSessionFactory().publish(new OAuthClientCreationEvent() {
			@Override
			public OAuthClientModel getCreatedOAuthClient() {
				return model;
			}

			@Override
			public ClientModel getCreatedClient() {
				return model;
			}
		});
		return model;
	}

	@Override
	public boolean removeOAuthClient(String id) {
		OAuthClientModel oauth = getOAuthClientById(id);
		if (oauth == null)
			return false;
		OAuthClientEntity client = em.getReference(OAuthClientEntity.class, oauth.getId());
		em.createNamedQuery("deleteScopeMappingByClient").setParameter("client", client).executeUpdate();
		em.remove(client);
		return true;
	}

	@Override
	public OAuthClientModel getOAuthClient(String name) {
		TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByName", OAuthClientEntity.class);
		query.setParameter("name", name);
		query.setParameter("realm", realm);
		List<OAuthClientEntity> entities = query.getResultList();
		if (entities.size() == 0)
			return null;
		return new OAuthClientAdapter(this, entities.get(0), em);
	}

	@Override
	public OAuthClientModel getOAuthClientById(String id) {
		return session.realms().getOAuthClientById(id, this);
	}

	@Override
	public List<OAuthClientModel> getOAuthClients() {
		TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByRealm", OAuthClientEntity.class);
		query.setParameter("realm", realm);
		List<OAuthClientEntity> entities = query.getResultList();
		List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
		for (OAuthClientEntity entity : entities)
			list.add(new OAuthClientAdapter(this, entity, em));
		return list;
	}

	private static final String BROWSER_HEADER_PREFIX = "_browser_header.";

	@Override
	public Map<String, String> getBrowserSecurityHeaders() {
		Map<String, String> attributes = getAttributes();
		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 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() {
		return realm.getSmtpConfig();
	}

	@Override
	public void setSmtpConfig(Map<String, String> smtpConfig) {
		realm.setSmtpConfig(smtpConfig);
		em.flush();
	}

	@Override
	public List<UserFederationProviderModel> getUserFederationProviders() {
		List<UserFederationProviderEntity> entities = realm.getUserFederationProviders();
		List<UserFederationProviderEntity> copy = new ArrayList<UserFederationProviderEntity>();
		for (UserFederationProviderEntity entity : entities) {
			copy.add(entity);

		}
		Collections.sort(copy, new Comparator<UserFederationProviderEntity>() {

			@Override
			public int compare(UserFederationProviderEntity o1, UserFederationProviderEntity o2) {
				return o1.getPriority() - o2.getPriority();
			}

		});
		List<UserFederationProviderModel> result = new ArrayList<UserFederationProviderModel>();
		for (UserFederationProviderEntity entity : copy) {
			result.add(new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity
					.getPriority(), entity.getDisplayName(), entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(), entity
					.getLastSync()));
		}

		return result;
	}

	@Override
	public UserFederationProviderModel addUserFederationProvider(String providerName, Map<String, String> config,
			int priority, String displayName, int fullSyncPeriod, int changedSyncPeriod, int lastSync) {
		String id = KeycloakModelUtils.generateId();
		UserFederationProviderEntity entity = new UserFederationProviderEntity();
		entity.setId(id);
		entity.setRealm(realm);
		entity.setProviderName(providerName);
		entity.setConfig(config);
		entity.setPriority(priority);
		if (displayName == null) {
			displayName = id;
		}
		entity.setDisplayName(displayName);
		entity.setFullSyncPeriod(fullSyncPeriod);
		entity.setChangedSyncPeriod(changedSyncPeriod);
		entity.setLastSync(lastSync);
		em.persist(entity);
		realm.getUserFederationProviders().add(entity);
		em.flush();
		return new UserFederationProviderModel(entity.getId(), providerName, config, priority, displayName, fullSyncPeriod,
				changedSyncPeriod, lastSync);
	}

	@Override
	public void removeUserFederationProvider(UserFederationProviderModel provider) {
		Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
		while (it.hasNext()) {
			UserFederationProviderEntity entity = it.next();
			if (entity.getId().equals(provider.getId())) {
				session.users().preRemove(this, provider);
				it.remove();
				em.remove(entity);
				return;
			}
		}
	}

	@Override
	public void updateUserFederationProvider(UserFederationProviderModel model) {
		Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
		while (it.hasNext()) {
			UserFederationProviderEntity entity = it.next();
			if (entity.getId().equals(model.getId())) {
				String displayName = model.getDisplayName();
				if (displayName != null) {
					entity.setDisplayName(model.getDisplayName());
				}
				entity.setConfig(model.getConfig());
				entity.setPriority(model.getPriority());
				entity.setProviderName(model.getProviderName());
				entity.setPriority(model.getPriority());
				entity.setFullSyncPeriod(model.getFullSyncPeriod());
				entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
				entity.setLastSync(model.getLastSync());
				break;
			}
		}
	}

	@Override
	public void setUserFederationProviders(List<UserFederationProviderModel> providers) {

		Iterator<UserFederationProviderEntity> it = realm.getUserFederationProviders().iterator();
		while (it.hasNext()) {
			UserFederationProviderEntity entity = it.next();
			boolean found = false;
			for (UserFederationProviderModel model : providers) {
				if (entity.getId().equals(model.getId())) {
					entity.setConfig(model.getConfig());
					entity.setPriority(model.getPriority());
					entity.setProviderName(model.getProviderName());
					entity.setPriority(model.getPriority());
					String displayName = model.getDisplayName();
					if (displayName != null) {
						entity.setDisplayName(model.getDisplayName());
					}
					entity.setFullSyncPeriod(model.getFullSyncPeriod());
					entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
					entity.setLastSync(model.getLastSync());
					found = true;
					break;
				}

			}
			if (found)
				continue;
			session.users().preRemove(
					this,
					new UserFederationProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity
							.getPriority(), entity.getDisplayName(), entity.getFullSyncPeriod(), entity.getChangedSyncPeriod(),
							entity.getLastSync()));
			it.remove();
			em.remove(entity);
		}

		List<UserFederationProviderModel> add = new LinkedList<UserFederationProviderModel>();
		for (UserFederationProviderModel model : providers) {
			boolean found = false;
			for (UserFederationProviderEntity entity : realm.getUserFederationProviders()) {
				if (entity.getId().equals(model.getId())) {
					found = true;
					break;
				}
			}
			if (!found)
				add.add(model);
		}

		for (UserFederationProviderModel model : add) {
			UserFederationProviderEntity entity = new UserFederationProviderEntity();
			if (model.getId() != null)
				entity.setId(model.getId());
			else
				entity.setId(KeycloakModelUtils.generateId());
			entity.setConfig(model.getConfig());
			entity.setPriority(model.getPriority());
			entity.setProviderName(model.getProviderName());
			entity.setPriority(model.getPriority());
			String displayName = model.getDisplayName();
			if (displayName == null) {
				displayName = entity.getId();
			}
			entity.setDisplayName(displayName);
			entity.setFullSyncPeriod(model.getFullSyncPeriod());
			entity.setChangedSyncPeriod(model.getChangedSyncPeriod());
			entity.setLastSync(model.getLastSync());
			em.persist(entity);
			realm.getUserFederationProviders().add(entity);

		}
	}

	@Override
	public RoleModel getRole(String name) {
		TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoleByName", RoleEntity.class);
		query.setParameter("name", name);
		query.setParameter("realm", realm);
		List<RoleEntity> roles = query.getResultList();
		if (roles.size() == 0)
			return null;
		return new RoleAdapter(this, em, roles.get(0));
	}

	@Override
	public RoleModel addRole(String name) {
		return this.addRole(KeycloakModelUtils.generateId(), name);
	}

	@Override
	public RoleModel addRole(String id, String name) {
		RoleEntity entity = new RoleEntity();
		entity.setId(id);
		entity.setName(name);
		entity.setRealm(realm);
		entity.setRealmId(realm.getId());
		realm.getRoles().add(entity);
		em.persist(entity);
		em.flush();
		return new RoleAdapter(this, em, entity);
	}

	@Override
	public boolean removeRole(RoleModel role) {
		if (role == null) {
			return false;
		}
		if (!role.getContainer().equals(this))
			return false;
		session.users().preRemove(this, role);
		RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
		realm.getRoles().remove(role);
		realm.getDefaultRoles().remove(role);

		em.createNativeQuery("delete from COMPOSITE_ROLE where CHILD_ROLE = :role").setParameter("role", roleEntity)
				.executeUpdate();
		em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();

		em.remove(roleEntity);

		return true;
	}

	@Override
	public Set<RoleModel> getRoles() {
		Set<RoleModel> list = new HashSet<RoleModel>();
		Collection<RoleEntity> roles = realm.getRoles();
		if (roles == null)
			return list;
		for (RoleEntity entity : roles) {
			list.add(new RoleAdapter(this, em, entity));
		}
		return list;
	}

	@Override
	public RoleModel getRoleById(String id) {
		return session.realms().getRoleById(id, this);
	}

	@Override
	public boolean removeRoleById(String id) {
		RoleModel role = getRoleById(id);
		if (role == null)
			return false;
		return role.getContainer().removeRole(role);
	}

	@Override
	public PasswordPolicy getPasswordPolicy() {
		if (passwordPolicy == null) {
			passwordPolicy = new PasswordPolicy(realm.getPasswordPolicy());
		}
		return passwordPolicy;
	}

	@Override
	public void setPasswordPolicy(PasswordPolicy policy) {
		this.passwordPolicy = policy;
		realm.setPasswordPolicy(policy.toString());
		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() {
		return realm.getEventsListeners();
	}

	@Override
	public void setEventsListeners(Set<String> listeners) {
		realm.setEventsListeners(listeners);
		em.flush();
	}

	@Override
	public ApplicationModel getMasterAdminApp() {
		return new ApplicationAdapter(this, em, session, realm.getMasterAdminApp());
	}

	@Override
	public void setMasterAdminApp(ApplicationModel app) {
		ApplicationEntity appEntity = app != null ? em.getReference(ApplicationEntity.class, app.getId()) : null;
		realm.setMasterAdminApp(appEntity);
		em.flush();
	}

	@Override
	public List<IdentityProviderModel> getIdentityProviders() {
		List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();

		for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
			IdentityProviderModel identityProviderModel = new IdentityProviderModel();

			identityProviderModel.setProviderId(entity.getProviderId());
			identityProviderModel.setId(entity.getId());
			identityProviderModel.setInternalId(entity.getInternalId());
			identityProviderModel.setName(entity.getName());
			identityProviderModel.setConfig(entity.getConfig());
			identityProviderModel.setEnabled(entity.isEnabled());
			identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
			identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
			identityProviderModel.setStoreToken(entity.isStoreToken());

			identityProviders.add(identityProviderModel);
		}

		return identityProviders;
	}

	@Override
	public IdentityProviderModel getIdentityProviderById(String identityProviderId) {
		for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
			if (identityProviderModel.getId().equals(identityProviderId)) {
				return identityProviderModel;
			}
		}

		return null;
	}

	@Override
	public void addIdentityProvider(IdentityProviderModel identityProvider) {
		IdentityProviderEntity entity = new IdentityProviderEntity();

		entity.setInternalId(KeycloakModelUtils.generateId());
		entity.setId(identityProvider.getId());
		entity.setProviderId(identityProvider.getProviderId());
		entity.setName(identityProvider.getName());
		entity.setEnabled(identityProvider.isEnabled());
		entity.setStoreToken(identityProvider.isStoreToken());
		entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
		entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
		entity.setConfig(identityProvider.getConfig());

		realm.addIdentityProvider(entity);

		em.persist(entity);
		em.flush();
	}

	@Override
	public void removeIdentityProviderById(String providerId) {
		for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
			if (entity.getId().equals(providerId)) {
				em.remove(entity);
				em.flush();
			}
		}
	}

	@Override
	public void updateIdentityProvider(IdentityProviderModel identityProvider) {
		for (IdentityProviderEntity entity : this.realm.getIdentityProviders()) {
			if (entity.getInternalId().equals(identityProvider.getInternalId())) {
				entity.setId(identityProvider.getId());
				entity.setName(identityProvider.getName());
				entity.setEnabled(identityProvider.isEnabled());
				entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
				entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
				entity.setStoreToken(identityProvider.isStoreToken());
				entity.setConfig(identityProvider.getConfig());
			}
		}

		em.flush();
	}

	@Override
	public boolean isIdentityFederationEnabled() {
		return !this.realm.getIdentityProviders().isEmpty();
	}

}