/*
* 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.*;
import org.keycloak.models.jpa.entities.*;
import org.keycloak.models.utils.ComponentUtil;
import org.keycloak.models.utils.KeycloakModelUtils;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static java.util.Objects.nonNull;
/**
* @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 isUserManagedAccessAllowed() {
return realm.isAllowUserManagedAccess();
}
@Override
public void setUserManagedAccessAllowed(boolean userManagedAccessAllowed) {
realm.setAllowUserManagedAccess(userManagedAccessAllowed);
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 String getDefaultSignatureAlgorithm() {
return getAttribute("defaultSignatureAlgorithm");
}
@Override
public void setDefaultSignatureAlgorithm(String defaultSignatureAlgorithm) {
setAttribute("defaultSignatureAlgorithm", defaultSignatureAlgorithm);
}
@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 getRefreshTokenMaxReuse() {
return realm.getRefreshTokenMaxReuse();
}
@Override
public void setRefreshTokenMaxReuse(int revokeRefreshTokenReuseCount) {
realm.setRefreshTokenMaxReuse(revokeRefreshTokenReuseCount);
}
@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 getSsoSessionIdleTimeoutRememberMe() {
return realm.getSsoSessionIdleTimeoutRememberMe();
}
@Override
public void setSsoSessionIdleTimeoutRememberMe(int seconds){
realm.setSsoSessionIdleTimeoutRememberMe(seconds);
}
@Override
public int getSsoSessionMaxLifespanRememberMe() {
return realm.getSsoSessionMaxLifespanRememberMe();
}
@Override
public void setSsoSessionMaxLifespanRememberMe(int seconds) {
realm.setSsoSessionMaxLifespanRememberMe(seconds);
}
@Override
public int getOfflineSessionIdleTimeout() {
return realm.getOfflineSessionIdleTimeout();
}
@Override
public void setOfflineSessionIdleTimeout(int seconds) {
realm.setOfflineSessionIdleTimeout(seconds);
}
// KEYCLOAK-7688 Offline Session Max for Offline Token
@Override
public boolean isOfflineSessionMaxLifespanEnabled() {
return getAttribute(RealmAttributes.OFFLINE_SESSION_MAX_LIFESPAN_ENABLED, false);
}
@Override
public void setOfflineSessionMaxLifespanEnabled(boolean offlineSessionMaxLifespanEnabled) {
setAttribute(RealmAttributes.OFFLINE_SESSION_MAX_LIFESPAN_ENABLED, offlineSessionMaxLifespanEnabled);
}
@Override
public int getOfflineSessionMaxLifespan() {
return getAttribute(RealmAttributes.OFFLINE_SESSION_MAX_LIFESPAN, Constants.DEFAULT_OFFLINE_SESSION_MAX_LIFESPAN);
}
@Override
public void setOfflineSessionMaxLifespan(int seconds) {
setAttribute(RealmAttributes.OFFLINE_SESSION_MAX_LIFESPAN, 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 Map<String, Integer> getUserActionTokenLifespans() {
Map<String, Integer> userActionTokens = new HashMap<>();
getAttributes().entrySet().stream()
.filter(Objects::nonNull)
.filter(entry -> nonNull(entry.getValue()))
.filter(entry -> entry.getKey().startsWith(RealmAttributes.ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN + "."))
.forEach(entry -> userActionTokens.put(entry.getKey().substring(RealmAttributes.ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN.length() + 1), Integer.valueOf(entry.getValue())));
return Collections.unmodifiableMap(userActionTokens);
}
@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);
}
@Override
public int getActionTokenGeneratedByUserLifespan(String actionTokenId) {
return getAttribute(RealmAttributes.ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN + "." + actionTokenId, getAccessCodeLifespanUserAction());
}
@Override
public void setActionTokenGeneratedByUserLifespan(String actionTokenId, Integer actionTokenGeneratedByUserLifespan) {
if (actionTokenGeneratedByUserLifespan != null)
setAttribute(RealmAttributes.ACTION_TOKEN_GENERATED_BY_USER_LIFESPAN + "." + actionTokenId, 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();
if (identityProvider.getInternalId() == null) {
entity.setInternalId(KeycloakModelUtils.generateId());
} else {
entity.setInternalId(identityProvider.getInternalId());
}
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 AuthenticationFlowModel getDockerAuthenticationFlow() {
String flowId = realm.getDockerAuthenticationFlow();
if (flowId == null) return null;
return getAuthenticationFlowById(flowId);
}
@Override
public void setDockerAuthenticationFlow(AuthenticationFlowModel flow) {
realm.setDockerAuthenticationFlow(flow.getId());
}
@Override
public List<AuthenticationFlowModel> getAuthenticationFlows() {
return realm.getAuthenticationFlows().stream()
.map(this::entityToModel)
.collect(Collectors.collectingAndThen(
Collectors.toList(), Collections::unmodifiableList));
}
@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);
model.setId(entity.getId());
return model;
}
@Override
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId);
return flow.getExecutions().stream()
.filter(e -> getId().equals(e.getRealm().getId()))
.map(this::entityToModel)
.sorted(AuthenticationExecutionModel.ExecutionComparator.SINGLETON)
.collect(Collectors.collectingAndThen(
Collectors.toList(), Collections::unmodifiableList));
}
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);
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);
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());
auth.setPriority(model.getPriority());
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.setPriority(entity.getPriority());
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.setPriority(model.getPriority());
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));
}
Collections.sort(actions, RequiredActionProviderModel.RequiredActionComparator.SINGLETON);
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 Long getGroupsCount(Boolean onlyTopGroups) {
return session.realms().getGroupsCount(this, onlyTopGroups);
}
@Override
public Long getGroupsCountByNameContaining(String search) {
return session.realms().getGroupsCountByNameContaining(this, search);
}
@Override
public List<GroupModel> getTopLevelGroups() {
return session.realms().getTopLevelGroups(this);
}
@Override
public List<GroupModel> getTopLevelGroups(Integer first, Integer max) {
return session.realms().getTopLevelGroups(this, first, max);
}
@Override
public List<GroupModel> searchForGroupByName(String search, Integer first, Integer max) {
return session.realms().searchForGroupByName(this, search, first, max);
}
@Override
public boolean removeGroup(GroupModel group) {
return session.realms().removeGroup(this, group);
}
@Override
public List<ClientScopeModel> getClientScopes() {
Collection<ClientScopeEntity> entities = realm.getClientScopes();
if (entities == null || entities.isEmpty()) return Collections.EMPTY_LIST;
List<ClientScopeModel> list = new LinkedList<>();
for (ClientScopeEntity entity : entities) {
list.add(session.realms().getClientScopeById(entity.getId(), this));
}
return Collections.unmodifiableList(list);
}
@Override
public ClientScopeModel addClientScope(String name) {
return this.addClientScope(KeycloakModelUtils.generateId(), name);
}
@Override
public ClientScopeModel addClientScope(String id, String name) {
ClientScopeEntity entity = new ClientScopeEntity();
entity.setId(id);
name = KeycloakModelUtils.convertClientScopeName(name);
entity.setName(name);
entity.setRealm(realm);
realm.getClientScopes().add(entity);
em.persist(entity);
em.flush();
final ClientScopeModel resource = new ClientScopeAdapter(this, em, session, entity);
em.flush();
return resource;
}
@Override
public boolean removeClientScope(String id) {
if (id == null) return false;
ClientScopeModel clientScope = getClientScopeById(id);
if (clientScope == null) return false;
if (KeycloakModelUtils.isClientScopeUsed(this, clientScope)) {
throw new ModelException("Cannot remove client scope, it is currently in use");
}
ClientScopeEntity clientScopeEntity = null;
Iterator<ClientScopeEntity> it = realm.getClientScopes().iterator();
while (it.hasNext()) {
ClientScopeEntity ae = it.next();
if (ae.getId().equals(id)) {
clientScopeEntity = ae;
it.remove();
break;
}
}
if (clientScope == null) {
return false;
}
session.users().preRemove(clientScope);
em.createNamedQuery("deleteClientScopeRoleMappingByClientScope").setParameter("clientScope", clientScopeEntity).executeUpdate();
em.flush();
em.remove(clientScopeEntity);
em.flush();
return true;
}
@Override
public ClientScopeModel getClientScopeById(String id) {
return session.realms().getClientScopeById(id, this);
}
@Override
public void addDefaultClientScope(ClientScopeModel clientScope, boolean defaultScope) {
DefaultClientScopeRealmMappingEntity entity = new DefaultClientScopeRealmMappingEntity();
entity.setClientScope(ClientScopeAdapter.toClientScopeEntity(clientScope, em));
entity.setRealm(getEntity());
entity.setDefaultScope(defaultScope);
em.persist(entity);
em.flush();
em.detach(entity);
}
@Override
public void removeDefaultClientScope(ClientScopeModel clientScope) {
int numRemoved = em.createNamedQuery("deleteDefaultClientScopeRealmMapping")
.setParameter("clientScope", ClientScopeAdapter.toClientScopeEntity(clientScope, em))
.setParameter("realm", getEntity())
.executeUpdate();
em.flush();
}
@Override
public List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope) {
TypedQuery<String> query = em.createNamedQuery("defaultClientScopeRealmMappingIdsByRealm", String.class);
query.setParameter("realm", getEntity());
query.setParameter("defaultScope", defaultScope);
List<String> ids = query.getResultList();
List<ClientScopeModel> clientScopes = new LinkedList<>();
for (String clientScopeId : ids) {
ClientScopeModel clientScope = getClientScopeById(clientScopeId);
if (clientScope == null) continue;
clientScopes.add(clientScope);
}
return clientScopes;
}
@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);
realm.getComponents().add(c);
setConfig(model, c);
model.setId(c.getId());
return model;
}
protected void setConfig(ComponentModel model, ComponentEntity c) {
c.getComponentConfigs().clear();
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);
c.getComponentConfigs().add(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());
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);
ComponentUtil.notifyPreRemove(session, this, component);
removeComponents(component.getId());
getEntity().getComponents().remove(c);
}
@Override
public void removeComponents(String parentId) {
Predicate<ComponentEntity> sameParent = c -> Objects.equals(parentId, c.getParentId());
getEntity().getComponents().stream()
.filter(sameParent)
.map(this::entityToModel)
.forEach((ComponentModel c) -> {
session.users().preRemove(this, c);
ComponentUtil.notifyPreRemove(session, this, c);
});
getEntity().getComponents().removeIf(sameParent);
}
@Override
public List<ComponentModel> getComponents(String parentId, final String providerType) {
if (parentId == null) parentId = getId();
final String parent = parentId;
return realm.getComponents().stream()
.filter(c -> parent.equals(c.getParentId())
&& providerType.equals(c.getProviderType()))
.map(this::entityToModel)
.collect(Collectors.toList());
}
@Override
public List<ComponentModel> getComponents(final String parentId) {
return realm.getComponents().stream()
.filter(c -> parentId.equals(c.getParentId()))
.map(this::entityToModel)
.collect(Collectors.toList());
}
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<>();
for (ComponentConfigEntity configEntity : c.getComponentConfigs()) {
config.add(configEntity.getName(), configEntity.getValue());
}
model.setConfig(config);
return model;
}
@Override
public List<ComponentModel> getComponents() {
return realm.getComponents().stream().map(this::entityToModel).collect(Collectors.toList());
}
@Override
public ComponentModel getComponent(String id) {
ComponentEntity c = em.find(ComponentEntity.class, id);
if (c == null) return null;
return entityToModel(c);
}
}