role cached queries

This commit is contained in:
Bill Burke 2016-02-22 17:16:35 -05:00
parent daa09f9a41
commit 4dcdaf4985
21 changed files with 631 additions and 266 deletions

View file

@ -463,11 +463,18 @@ public class ClientAdapter implements ClientModel {
} }
@Override @Override
public void updateDefaultRoles(String[] defaultRoles) { public void updateDefaultRoles(String... defaultRoles) {
getDelegateForUpdate(); getDelegateForUpdate();
updated.updateDefaultRoles(defaultRoles); updated.updateDefaultRoles(defaultRoles);
} }
@Override
public void removeDefaultRoles(String... defaultRoles) {
getDelegateForUpdate();
updated.removeDefaultRoles(defaultRoles);
}
@Override @Override
public boolean isBearerOnly() { public boolean isBearerOnly() {
if (updated != null) return updated.isBearerOnly(); if (updated != null) return updated.isBearerOnly();
@ -542,12 +549,10 @@ public class ClientAdapter implements ClientModel {
@Override @Override
public RoleModel getRole(String name) { public RoleModel getRole(String name) {
if (updated != null) return updated.getRole(name); for (RoleModel role : getRoles()) {
String id = cached.getRoles().get(name); if (role.getName().equals(name)) return role;
if (id == null) {
return null;
} }
return cacheSession.getRoleById(id, cachedRealm); return null;
} }
@Override @Override
@ -575,15 +580,7 @@ public class ClientAdapter implements ClientModel {
@Override @Override
public Set<RoleModel> getRoles() { public Set<RoleModel> getRoles() {
if (updated != null) return updated.getRoles(); return cacheSession.getClientRoles(cachedRealm, this);
Set<RoleModel> roles = new HashSet<RoleModel>();
for (String id : cached.getRoles().values()) {
RoleModel roleById = cacheSession.getRoleById(id, cachedRealm);
if (roleById == null) continue;
roles.add(roleById);
}
return roles;
} }
@Override @Override

View file

@ -581,11 +581,18 @@ public class RealmAdapter implements RealmModel {
} }
@Override @Override
public void updateDefaultRoles(String[] defaultRoles) { public void updateDefaultRoles(String... defaultRoles) {
getDelegateForUpdate(); getDelegateForUpdate();
updated.updateDefaultRoles(defaultRoles); updated.updateDefaultRoles(defaultRoles);
} }
@Override
public void removeDefaultRoles(String... defaultRoles) {
getDelegateForUpdate();
updated.removeDefaultRoles(defaultRoles);
}
@Override @Override
public List<ClientModel> getClients() { public List<ClientModel> getClients() {
return cacheSession.getClients(this); return cacheSession.getClients(this);
@ -870,12 +877,18 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public RoleModel getRole(String name) { public RoleModel getRole(String name) {
if (updated != null) return updated.getRole(name); for (RoleModel role : getRoles()) {
String id = cached.getRealmRoles().get(name); if (role.getName().equals(name)) return role;
if (id == null) return null; }
return cacheSession.getRoleById(id, this); return null;
} }
@Override
public Set<RoleModel> getRoles() {
return cacheSession.getRealmRoles(this);
}
@Override @Override
public RoleModel addRole(String name) { public RoleModel addRole(String name) {
getDelegateForUpdate(); getDelegateForUpdate();
@ -899,18 +912,6 @@ public class RealmAdapter implements RealmModel {
return updated.removeRole(role); return updated.removeRole(role);
} }
@Override
public Set<RoleModel> getRoles() {
if (updated != null) return updated.getRoles();
Set<RoleModel> roles = new HashSet<RoleModel>();
for (String id : cached.getRealmRoles().values()) {
RoleModel roleById = cacheSession.getRoleById(id, this);
if (roleById == null) continue;
roles.add(roleById);
}
return Collections.unmodifiableSet(roles);
}
@Override @Override
public boolean isIdentityFederationEnabled() { public boolean isIdentityFederationEnabled() {

View file

@ -37,7 +37,8 @@ import org.keycloak.models.cache.infinispan.entities.CachedRealmRole;
import org.keycloak.models.cache.infinispan.entities.CachedRole; import org.keycloak.models.cache.infinispan.entities.CachedRole;
import org.keycloak.models.cache.infinispan.entities.ClientListQuery; import org.keycloak.models.cache.infinispan.entities.ClientListQuery;
import org.keycloak.models.cache.infinispan.entities.RealmListQuery; import org.keycloak.models.cache.infinispan.entities.RealmListQuery;
import org.keycloak.models.cache.infinispan.entities.Revisioned; import org.keycloak.models.cache.infinispan.entities.RoleListQuery;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -77,7 +78,7 @@ import java.util.Set;
* - realm client lists need to be invalidated and evited whenever a client is added or removed from a realm. RealmProvider * - realm client lists need to be invalidated and evited whenever a client is added or removed from a realm. RealmProvider
* now has addClient/removeClient at its top level. All adapaters should use these methods so that the appropriate invalidations * now has addClient/removeClient at its top level. All adapaters should use these methods so that the appropriate invalidations
* can be registered. * can be registered.
* - whenever a client is added/removed the realm of the client is added to a clientListInvalidations set * - whenever a client is added/removed the realm of the client is added to a listInvalidations set
* this set must be checked before sending back or caching a cached query. This check is required to * this set must be checked before sending back or caching a cached query. This check is required to
* avoid caching an uncommitted removal/add in a query cache. * avoid caching an uncommitted removal/add in a query cache.
* - when a client is removed, any queries that contain that client must also be removed. * - when a client is removed, any queries that contain that client must also be removed.
@ -104,6 +105,8 @@ import java.util.Set;
public class StreamCacheRealmProvider implements CacheRealmProvider { public class StreamCacheRealmProvider implements CacheRealmProvider {
protected static final Logger logger = Logger.getLogger(StreamCacheRealmProvider.class); protected static final Logger logger = Logger.getLogger(StreamCacheRealmProvider.class);
public static final String REALM_CLIENTS_QUERY_SUFFIX = ".realm.clients"; public static final String REALM_CLIENTS_QUERY_SUFFIX = ".realm.clients";
public static final String ROLES_QUERY_SUFFIX = ".roles";
public static final String ROLE_BY_NAME_QUERY_SUFFIX = ".role.by-name";
protected StreamRealmCache cache; protected StreamRealmCache cache;
protected KeycloakSession session; protected KeycloakSession session;
protected RealmProvider delegate; protected RealmProvider delegate;
@ -115,7 +118,7 @@ public class StreamCacheRealmProvider implements CacheRealmProvider {
protected Map<String, ClientTemplateModel> managedClientTemplates = new HashMap<>(); protected Map<String, ClientTemplateModel> managedClientTemplates = new HashMap<>();
protected Map<String, RoleModel> managedRoles = new HashMap<>(); protected Map<String, RoleModel> managedRoles = new HashMap<>();
protected Map<String, GroupModel> managedGroups = new HashMap<>(); protected Map<String, GroupModel> managedGroups = new HashMap<>();
protected Set<String> clientListInvalidations = new HashSet<>(); protected Set<String> listInvalidations = new HashSet<>();
protected Set<String> invalidations = new HashSet<>(); protected Set<String> invalidations = new HashSet<>();
protected boolean clearAll; protected boolean clearAll;
@ -386,7 +389,7 @@ public class StreamCacheRealmProvider implements CacheRealmProvider {
invalidations.add(client.getId()); invalidations.add(client.getId());
cache.clientAdded(realm.getId(), client.getId(), invalidations); cache.clientAdded(realm.getId(), client.getId(), invalidations);
// this is needed so that a new client that hasn't been committed isn't cached in a query // this is needed so that a new client that hasn't been committed isn't cached in a query
clientListInvalidations.add(realm.getId()); listInvalidations.add(realm.getId());
return client; return client;
} }
@ -394,10 +397,17 @@ public class StreamCacheRealmProvider implements CacheRealmProvider {
return realm + REALM_CLIENTS_QUERY_SUFFIX; return realm + REALM_CLIENTS_QUERY_SUFFIX;
} }
private String getRolesCacheKey(String container) {
return container + ROLES_QUERY_SUFFIX;
}
private String getRoleByNameCacheKey(String container, String name) {
return container + "." + name + ROLES_QUERY_SUFFIX;
}
@Override @Override
public List<ClientModel> getClients(RealmModel realm) { public List<ClientModel> getClients(RealmModel realm) {
String cacheKey = getRealmClientsQueryCacheKey(realm.getId()); String cacheKey = getRealmClientsQueryCacheKey(realm.getId());
boolean queryDB = invalidations.contains(cacheKey) || clientListInvalidations.contains(realm.getId()); boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
if (queryDB) { if (queryDB) {
return getDelegate().getClients(realm); return getDelegate().getClients(realm);
} }
@ -430,6 +440,7 @@ public class StreamCacheRealmProvider implements CacheRealmProvider {
return list; return list;
} }
@Override @Override
public boolean removeClient(String id, RealmModel realm) { public boolean removeClient(String id, RealmModel realm) {
ClientModel client = getClientById(id, realm); ClientModel client = getClientById(id, realm);
@ -437,7 +448,7 @@ public class StreamCacheRealmProvider implements CacheRealmProvider {
// need to invalidate realm client query cache every time client list is changed // need to invalidate realm client query cache every time client list is changed
invalidations.add(getRealmClientsQueryCacheKey(realm.getId())); invalidations.add(getRealmClientsQueryCacheKey(realm.getId()));
invalidations.add(getClientByClientIdCacheKey(client.getClientId(), realm)); invalidations.add(getClientByClientIdCacheKey(client.getClientId(), realm));
clientListInvalidations.add(realm.getId()); listInvalidations.add(realm.getId());
registerClientInvalidation(id); registerClientInvalidation(id);
cache.clientRemoval(realm.getId(), id, invalidations); cache.clientRemoval(realm.getId(), id, invalidations);
for (RoleModel role : client.getRoles()) { for (RoleModel role : client.getRoles()) {
@ -451,6 +462,177 @@ public class StreamCacheRealmProvider implements CacheRealmProvider {
if (delegate != null) delegate.close(); if (delegate != null) delegate.close();
} }
@Override
public RoleModel addRealmRole(RealmModel realm, String name) {
return addRealmRole(realm, KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addRealmRole(RealmModel realm, String id, String name) {
invalidations.add(getRolesCacheKey(realm.getId()));
// this is needed so that a new role that hasn't been committed isn't cached in a query
listInvalidations.add(realm.getId());
RoleModel role = getDelegate().addRealmRole(realm, name);
invalidations.add(role.getId());
return role;
}
@Override
public Set<RoleModel> getRealmRoles(RealmModel realm) {
String cacheKey = getRolesCacheKey(realm.getId());
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
if (queryDB) {
return getDelegate().getRealmRoles(realm);
}
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
if (query != null) {
logger.tracev("getRealmRoles cache hit: {0}", realm.getName());
}
if (query == null) {
Long loaded = cache.getCurrentRevision(cacheKey);
Set<RoleModel> model = getDelegate().getRealmRoles(realm);
if (model == null) return null;
Set<String> ids = new HashSet<>();
for (RoleModel role : model) ids.add(role.getId());
query = new RoleListQuery(loaded, cacheKey, realm, ids);
logger.tracev("adding realm roles cache miss: realm {0} key {1}", realm.getName(), cacheKey);
cache.addRevisioned(query);
return model;
}
Set<RoleModel> list = new HashSet<>();
for (String id : query.getRoles()) {
RoleModel role = session.realms().getRoleById(id, realm);
if (role == null) {
invalidations.add(cacheKey);
return getDelegate().getRealmRoles(realm);
}
list.add(role);
}
return list;
}
@Override
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client) {
String cacheKey = getRolesCacheKey(client.getId());
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(client.getId());
if (queryDB) {
return getDelegate().getClientRoles(realm, client);
}
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
if (query != null) {
logger.tracev("getClientRoles cache hit: {0}", client.getClientId());
}
if (query == null) {
Long loaded = cache.getCurrentRevision(cacheKey);
Set<RoleModel> model = getDelegate().getClientRoles(realm, client);
if (model == null) return null;
Set<String> ids = new HashSet<>();
for (RoleModel role : model) ids.add(role.getId());
query = new RoleListQuery(loaded, cacheKey, realm, ids, client.getClientId());
logger.tracev("adding client roles cache miss: client {0} key {1}", client.getClientId(), cacheKey);
cache.addRevisioned(query);
return model;
}
Set<RoleModel> list = new HashSet<>();
for (String id : query.getRoles()) {
RoleModel role = session.realms().getRoleById(id, realm);
if (role == null) {
invalidations.add(cacheKey);
return getDelegate().getClientRoles(realm, client);
}
list.add(role);
}
return list;
}
@Override
public RoleModel addClientRole(RealmModel realm, ClientModel client, String name) {
return addClientRole(realm, client, KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addClientRole(RealmModel realm, ClientModel client, String id, String name) {
invalidations.add(getRolesCacheKey(client.getId()));
// this is needed so that a new role that hasn't been committed isn't cached in a query
listInvalidations.add(client.getId());
RoleModel role = getDelegate().addClientRole(realm, client, id, name);
invalidations.add(role.getId());
return role;
}
@Override
public RoleModel getRealmRole(RealmModel realm, String name) {
String cacheKey = getRoleByNameCacheKey(realm.getId(), name);
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
if (queryDB) {
return getDelegate().getRealmRole(realm, name);
}
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
if (query != null) {
logger.tracev("getRealmRole cache hit: {0}.{1}", realm.getName(), name);
}
if (query == null) {
Long loaded = cache.getCurrentRevision(cacheKey);
RoleModel model = getDelegate().getRealmRole(realm, name);
if (model == null) return null;
query = new RoleListQuery(loaded, cacheKey, realm, model.getId());
logger.tracev("adding realm role cache miss: client {0} key {1}", realm.getName(), cacheKey);
cache.addRevisioned(query);
return model;
}
RoleModel role = getRoleById(query.getRoles().iterator().next(), realm);
if (role == null) {
invalidations.add(cacheKey);
return getDelegate().getRealmRole(realm, name);
}
return role;
}
@Override
public RoleModel getClientRole(RealmModel realm, ClientModel client, String name) {
String cacheKey = getRoleByNameCacheKey(client.getId(), name);
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(client.getId());
if (queryDB) {
return getDelegate().getClientRole(realm, client, name);
}
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
if (query != null) {
logger.tracev("getClientRole cache hit: {0}.{1}", client.getClientId(), name);
}
if (query == null) {
Long loaded = cache.getCurrentRevision(cacheKey);
RoleModel model = getDelegate().getClientRole(realm, client, name);
if (model == null) return null;
query = new RoleListQuery(loaded, cacheKey, realm, model.getId(), client.getClientId());
logger.tracev("adding client role cache miss: client {0} key {1}", client.getClientId(), cacheKey);
cache.addRevisioned(query);
return model;
}
RoleModel role = getRoleById(query.getRoles().iterator().next(), realm);
if (role == null) {
invalidations.add(cacheKey);
return getDelegate().getClientRole(realm, client, name);
}
return role;
}
@Override
public boolean removeRole(RealmModel realm, RoleModel role) {
invalidations.add(getRolesCacheKey(role.getContainer().getId()));
invalidations.add(getRoleByNameCacheKey(role.getContainer().getId(), role.getName()));
listInvalidations.add(role.getContainer().getId());
invalidations.add(role.getId());
return getDelegate().removeRole(realm, role);
}
@Override @Override
public RoleModel getRoleById(String id, RealmModel realm) { public RoleModel getRoleById(String id, RealmModel realm) {
CachedRole cached = cache.get(id, CachedRole.class); CachedRole cached = cache.get(id, CachedRole.class);

View file

@ -37,6 +37,7 @@ import org.keycloak.models.cache.infinispan.stream.HasRolePredicate;
import org.keycloak.models.cache.infinispan.stream.InClientPredicate; import org.keycloak.models.cache.infinispan.stream.InClientPredicate;
import org.keycloak.models.cache.infinispan.stream.InRealmPredicate; import org.keycloak.models.cache.infinispan.stream.InRealmPredicate;
import org.keycloak.models.cache.infinispan.stream.RealmQueryPredicate; import org.keycloak.models.cache.infinispan.stream.RealmQueryPredicate;
import org.keycloak.models.cache.infinispan.stream.RoleQueryPredicate;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -287,9 +288,6 @@ public class StreamRealmCache {
} else if (object instanceof CachedClient) { } else if (object instanceof CachedClient) {
CachedClient cached = (CachedClient)object; CachedClient cached = (CachedClient)object;
Predicate<Map.Entry<String, Revisioned>> predicate = getClientRemovalPredicate(cached.getRealm(), cached.getId()); Predicate<Map.Entry<String, Revisioned>> predicate = getClientRemovalPredicate(cached.getRealm(), cached.getId());
for (String roleId : cached.getRoles().values()) {
predicate.or(getRoleRemovalPredicate(roleId));
}
return predicate; return predicate;
} else if (object instanceof CachedRole) { } else if (object instanceof CachedRole) {
CachedRole cached = (CachedRole)object; CachedRole cached = (CachedRole)object;

View file

@ -67,7 +67,6 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
protected boolean implicitFlowEnabled; protected boolean implicitFlowEnabled;
protected boolean directAccessGrantsEnabled; protected boolean directAccessGrantsEnabled;
protected boolean serviceAccountsEnabled; protected boolean serviceAccountsEnabled;
protected Map<String, String> roles = new HashMap<String, String>();
protected int nodeReRegistrationTimeout; protected int nodeReRegistrationTimeout;
protected Map<String, Integer> registeredNodes; protected Map<String, Integer> registeredNodes;
protected String clientTemplate; protected String clientTemplate;
@ -110,7 +109,6 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
implicitFlowEnabled = model.isImplicitFlowEnabled(); implicitFlowEnabled = model.isImplicitFlowEnabled();
directAccessGrantsEnabled = model.isDirectAccessGrantsEnabled(); directAccessGrantsEnabled = model.isDirectAccessGrantsEnabled();
serviceAccountsEnabled = model.isServiceAccountsEnabled(); serviceAccountsEnabled = model.isServiceAccountsEnabled();
cacheRoles(model);
nodeReRegistrationTimeout = model.getNodeReRegistrationTimeout(); nodeReRegistrationTimeout = model.getNodeReRegistrationTimeout();
registeredNodes = new TreeMap<>(model.getRegisteredNodes()); registeredNodes = new TreeMap<>(model.getRegisteredNodes());
@ -122,12 +120,6 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
useTemplateScope = model.useTemplateScope(); useTemplateScope = model.useTemplateScope();
} }
protected void cacheRoles(ClientModel model) {
for (RoleModel role : model.getRoles()) {
roles.put(role.getName(), role.getId());
}
}
public String getClientId() { public String getClientId() {
return clientId; return clientId;
} }
@ -244,10 +236,6 @@ public class CachedClient extends AbstractRevisioned implements InRealm {
return serviceAccountsEnabled; return serviceAccountsEnabled;
} }
public Map<String, String> getRoles() {
return roles;
}
public int getNodeReRegistrationTimeout() { public int getNodeReRegistrationTimeout() {
return nodeReRegistrationTimeout; return nodeReRegistrationTimeout;
} }

View file

@ -145,8 +145,6 @@ public class CachedRealm extends AbstractRevisioned {
protected List<String> defaultGroups = new LinkedList<String>(); protected List<String> defaultGroups = new LinkedList<String>();
protected Set<String> groups = new HashSet<String>(); protected Set<String> groups = new HashSet<String>();
protected Map<String, String> realmRoles = new HashMap<String, String>();
protected List<String> clients = new LinkedList<>();
protected List<String> clientTemplates= new LinkedList<>(); protected List<String> clientTemplates= new LinkedList<>();
protected boolean internationalizationEnabled; protected boolean internationalizationEnabled;
protected Set<String> supportedLocales; protected Set<String> supportedLocales;
@ -240,10 +238,6 @@ public class CachedRealm extends AbstractRevisioned {
ClientModel masterAdminClient = model.getMasterAdminClient(); ClientModel masterAdminClient = model.getMasterAdminClient();
this.masterAdminClient = (masterAdminClient != null) ? masterAdminClient.getId() : null; this.masterAdminClient = (masterAdminClient != null) ? masterAdminClient.getId() : null;
cacheRealmRoles(model);
cacheClients(model);
cacheClientTemplates(model); cacheClientTemplates(model);
internationalizationEnabled = model.isInternationalizationEnabled(); internationalizationEnabled = model.isInternationalizationEnabled();
@ -288,19 +282,6 @@ public class CachedRealm extends AbstractRevisioned {
} }
} }
protected void cacheClients(RealmModel model) {
for (ClientModel client : model.getClients()) {
clients.add(client.getId());
}
}
protected void cacheRealmRoles(RealmModel model) {
for (RoleModel role : model.getRoles()) {
realmRoles.put(role.getName(), role.getId());
}
}
public String getMasterAdminClient() { public String getMasterAdminClient() {
return masterAdminClient; return masterAdminClient;
} }
@ -321,14 +302,6 @@ public class CachedRealm extends AbstractRevisioned {
return defaultRoles; return defaultRoles;
} }
public Map<String, String> getRealmRoles() {
return realmRoles;
}
public List<String> getClients() {
return clients;
}
public boolean isEnabled() { public boolean isEnabled() {
return enabled; return enabled;
} }

View file

@ -0,0 +1,68 @@
package org.keycloak.models.cache.infinispan.entities;
import org.keycloak.models.RealmModel;
import org.keycloak.models.cache.infinispan.entities.AbstractRevisioned;
import org.keycloak.models.cache.infinispan.entities.ClientQuery;
import org.keycloak.models.cache.infinispan.entities.RoleQuery;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RoleListQuery extends AbstractRevisioned implements RoleQuery, InClient {
private final Set<String> roles;
private final String realm;
private final String realmName;
private String client;
public RoleListQuery(Long revisioned, String id, RealmModel realm, Set<String> roles) {
super(revisioned, id);
this.realm = realm.getId();
this.realmName = realm.getName();
this.roles = roles;
}
public RoleListQuery(Long revisioned, String id, RealmModel realm, String role) {
super(revisioned, id);
this.realm = realm.getId();
this.realmName = realm.getName();
this.roles = new HashSet<>();
this.roles.add(role);
}
public RoleListQuery(Long revision, String id, RealmModel realm, Set<String> roles, String client) {
this(revision, id, realm, roles);
this.client = client;
}
public RoleListQuery(Long revision, String id, RealmModel realm, String role, String client) {
this(revision, id, realm, role);
this.client = client;
}
@Override
public Set<String> getRoles() {
return roles;
}
@Override
public String getRealm() {
return realm;
}
@Override
public String getClientId() {
return client;
}
@Override
public String toString() {
return "RoleListQuery{" +
"id='" + getId() + "'" +
"realmName='" + realmName + '\'' +
'}';
}
}

View file

@ -3,6 +3,7 @@ package org.keycloak.models.cache.infinispan.stream;
import org.keycloak.models.cache.infinispan.entities.CachedGroup; import org.keycloak.models.cache.infinispan.entities.CachedGroup;
import org.keycloak.models.cache.infinispan.entities.CachedRole; import org.keycloak.models.cache.infinispan.entities.CachedRole;
import org.keycloak.models.cache.infinispan.entities.Revisioned; import org.keycloak.models.cache.infinispan.entities.Revisioned;
import org.keycloak.models.cache.infinispan.entities.RoleQuery;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map; import java.util.Map;
@ -36,6 +37,10 @@ public class HasRolePredicate implements Predicate<Map.Entry<String, Revisioned>
CachedGroup cachedRole = (CachedGroup)value; CachedGroup cachedRole = (CachedGroup)value;
if (cachedRole.getRoleMappings().contains(role)) return true; if (cachedRole.getRoleMappings().contains(role)) return true;
} }
if (value instanceof RoleQuery) {
RoleQuery roleQuery = (RoleQuery)value;
if (roleQuery.getRoles().contains(role)) return true;
}
return false; return false;
} }
} }

View file

@ -612,31 +612,17 @@ public class ClientAdapter implements ClientModel {
@Override @Override
public RoleModel getRole(String name) { public RoleModel getRole(String name) {
TypedQuery<String> query = em.createNamedQuery("getClientRoleIdByName", String.class); return session.realms().getClientRole(realm, this, name);
query.setParameter("name", name);
query.setParameter("client", entity.getId());
List<String> roles = query.getResultList();
if (roles.size() == 0) return null;
return session.realms().getRoleById(roles.get(0), realm);
} }
@Override @Override
public RoleModel addRole(String name) { public RoleModel addRole(String name) {
return this.addRole(KeycloakModelUtils.generateId(), name); return session.realms().addClientRole(realm, this, name);
} }
@Override @Override
public RoleModel addRole(String id, String name) { public RoleModel addRole(String id, String name) {
RoleEntity roleEntity = new RoleEntity(); return session.realms().addClientRole(realm, this, id, name);
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setClient(entity);
roleEntity.setClientRole(true);
roleEntity.setRealmId(realm.getId());
entity.getRoles().add(roleEntity);
em.persist(roleEntity);
em.flush();
return new RoleAdapter(session, realm, em, roleEntity);
} }
@Override @Override
@ -650,7 +636,6 @@ public class ClientAdapter implements ClientModel {
RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em); RoleEntity role = RoleAdapter.toRoleEntity(roleModel, em);
if (!role.isClientRole()) return false; if (!role.isClientRole()) return false;
entity.getRoles().remove(role);
entity.getDefaultRoles().remove(role); entity.getDefaultRoles().remove(role);
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em); String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", role).executeUpdate(); em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", role).executeUpdate();
@ -666,24 +651,7 @@ public class ClientAdapter implements ClientModel {
@Override @Override
public Set<RoleModel> getRoles() { public Set<RoleModel> getRoles() {
Set<RoleModel> list = new HashSet<RoleModel>(); return session.realms().getClientRoles(realm, this);
TypedQuery<RoleEntity> query = em.createNamedQuery("getClientRoles", RoleEntity.class);
query.setParameter("client", entity);
List<RoleEntity> roles = query.getResultList();
for (RoleEntity roleEntity : roles) {
list.add(new RoleAdapter(session, realm, em, roleEntity));
}
/*
TypedQuery<String> query = em.createNamedQuery("getClientRoleIds", String.class);
query.setParameter("client", entity.getId());
List<String> roles = query.getResultList();
for (String id : roles) {
list.add(session.realms().getRoleById(id, realm));
}
*/
return list;
} }
@Override @Override
@ -733,10 +701,10 @@ public class ClientAdapter implements ClientModel {
} }
@Override @Override
public void updateDefaultRoles(String[] defaultRoles) { public void updateDefaultRoles(String... defaultRoles) {
Collection<RoleEntity> entities = entity.getDefaultRoles(); Collection<RoleEntity> entities = entity.getDefaultRoles();
Set<String> already = new HashSet<String>(); Set<String> already = new HashSet<String>();
List<RoleEntity> remove = new ArrayList<RoleEntity>(); List<RoleEntity> remove = new ArrayList<>();
for (RoleEntity rel : entities) { for (RoleEntity rel : entities) {
if (!contains(rel.getName(), defaultRoles)) { if (!contains(rel.getName(), defaultRoles)) {
remove.add(rel); remove.add(rel);
@ -756,6 +724,24 @@ public class ClientAdapter implements ClientModel {
em.flush(); em.flush();
} }
@Override
public void removeDefaultRoles(String... defaultRoles) {
Collection<RoleEntity> entities = entity.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 @Override
public int getNodeReRegistrationTimeout() { public int getNodeReRegistrationTimeout() {
return entity.getNodeReRegistrationTimeout(); return entity.getNodeReRegistrationTimeout();

View file

@ -18,6 +18,7 @@
package org.keycloak.models.jpa; package org.keycloak.models.jpa;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.connections.jpa.util.JpaUtils;
import org.keycloak.migration.MigrationModel; import org.keycloak.migration.MigrationModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel; import org.keycloak.models.ClientTemplateModel;
@ -25,6 +26,7 @@ import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RealmProvider; import org.keycloak.models.RealmProvider;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.jpa.entities.ClientEntity; import org.keycloak.models.jpa.entities.ClientEntity;
import org.keycloak.models.jpa.entities.ClientTemplateEntity; import org.keycloak.models.jpa.entities.ClientTemplateEntity;
@ -37,8 +39,10 @@ import javax.persistence.EntityManager;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -135,15 +139,15 @@ public class JpaRealmProvider implements RealmProvider {
for (String client : clients) { for (String client : clients) {
session.realms().removeClient(client, adapter); session.realms().removeClient(client, adapter);
} }
/*
for (ClientEntity a : new LinkedList<>(realm.getClients())) {
adapter.removeClient(a.getId());
}
*/
for (ClientTemplateEntity a : new LinkedList<>(realm.getClientTemplates())) { for (ClientTemplateEntity a : new LinkedList<>(realm.getClientTemplates())) {
adapter.removeClientTemplate(a.getId()); adapter.removeClientTemplate(a.getId());
} }
for (RoleModel role : adapter.getRoles()) {
session.realms().removeRole(adapter, role);
}
em.remove(realm); em.remove(realm);
em.flush(); em.flush();
@ -155,6 +159,112 @@ public class JpaRealmProvider implements RealmProvider {
public void close() { public void close() {
} }
@Override
public RoleModel addRealmRole(RealmModel realm, String name) {
return addRealmRole(realm, KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addRealmRole(RealmModel realm, String id, String name) {
RoleEntity entity = new RoleEntity();
entity.setId(id);
entity.setName(name);
RealmEntity ref = em.getReference(RealmEntity.class, realm.getId());
entity.setRealm(ref);
entity.setRealmId(realm.getId());
em.persist(entity);
em.flush();
return new RoleAdapter(session, realm, em, entity);
}
@Override
public RoleModel getRealmRole(RealmModel realm, String name) {
TypedQuery<String> query = em.createNamedQuery("getRealmRoleIdByName", String.class);
query.setParameter("name", name);
query.setParameter("realm", realm.getId());
List<String> roles = query.getResultList();
if (roles.size() == 0) return null;
return session.realms().getRoleById(roles.get(0), realm);
}
@Override
public RoleModel addClientRole(RealmModel realm, ClientModel client, String name) {
return addClientRole(realm, client, KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addClientRole(RealmModel realm, ClientModel client, String id, String name) {
ClientEntity clientEntity = em.getReference(ClientEntity.class, client.getId());
RoleEntity roleEntity = new RoleEntity();
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setClient(clientEntity);
roleEntity.setClientRole(true);
roleEntity.setRealmId(realm.getId());
em.persist(roleEntity);
em.flush();
return new RoleAdapter(session, realm, em, roleEntity);
}
@Override
public Set<RoleModel> getRealmRoles(RealmModel realm) {
TypedQuery<String> query = em.createNamedQuery("getRealmRoleIds", String.class);
query.setParameter("realm", realm.getId());
List<String> roles = query.getResultList();
if (roles.isEmpty()) return Collections.EMPTY_SET;
Set<RoleModel> list = new HashSet<RoleModel>();
for (String id : roles) {
list.add(session.realms().getRoleById(id, realm));
}
return Collections.unmodifiableSet(list);
}
@Override
public RoleModel getClientRole(RealmModel realm, ClientModel client, String name) {
TypedQuery<String> query = em.createNamedQuery("getClientRoleIdByName", String.class);
query.setParameter("name", name);
query.setParameter("client", client.getId());
List<String> roles = query.getResultList();
if (roles.size() == 0) return null;
return session.realms().getRoleById(roles.get(0), realm);
}
@Override
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client) {
Set<RoleModel> list = new HashSet<RoleModel>();
TypedQuery<String> query = em.createNamedQuery("getClientRoleIds", String.class);
query.setParameter("client", client.getId());
List<String> roles = query.getResultList();
for (String id : roles) {
list.add(session.realms().getRoleById(id, realm));
}
return list;
}
@Override
public boolean removeRole(RealmModel realm, RoleModel role) {
session.users().preRemove(realm, role);
RoleEntity roleEntity = em.getReference(RoleEntity.class, role.getId());
RoleContainerModel container = role.getContainer();
if (container.getDefaultRoles().contains(role.getName())) {
container.removeDefaultRoles(role.getName());
}
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
em.createNamedQuery("deleteTemplateScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
em.remove(roleEntity);
em.flush();
return true;
}
@Override @Override
public RoleModel getRoleById(String id, RealmModel realm) { public RoleModel getRoleById(String id, RealmModel realm) {
RoleEntity entity = em.find(RoleEntity.class, id); RoleEntity entity = em.find(RoleEntity.class, id);

View file

@ -682,6 +682,21 @@ public class RealmAdapter implements RealmModel {
em.flush(); 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 @Override
public List<GroupModel> getDefaultGroups() { public List<GroupModel> getDefaultGroups() {
Collection<GroupEntity> entities = realm.getDefaultGroups(); Collection<GroupEntity> entities = realm.getDefaultGroups();
@ -980,66 +995,27 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public RoleModel getRole(String name) { public RoleModel getRole(String name) {
TypedQuery<String> query = em.createNamedQuery("getRealmRoleIdByName", String.class); return session.realms().getRealmRole(this, name);
query.setParameter("name", name);
query.setParameter("realm", realm.getId());
List<String> roles = query.getResultList();
if (roles.size() == 0) return null;
return session.realms().getRoleById(roles.get(0), this);
} }
@Override @Override
public RoleModel addRole(String name) { public RoleModel addRole(String name) {
return this.addRole(KeycloakModelUtils.generateId(), name); return session.realms().addRealmRole(this, name);
} }
@Override @Override
public RoleModel addRole(String id, String name) { public RoleModel addRole(String id, String name) {
RoleEntity entity = new RoleEntity(); return session.realms().addRealmRole(this, id, name);
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(session, this, em, entity);
} }
@Override @Override
public boolean removeRole(RoleModel role) { public boolean removeRole(RoleModel role) {
if (role == null) { return session.realms().removeRole(this, role);
return false;
}
if (!role.getContainer().equals(this)) return false;
session.users().preRemove(this, role);
RoleEntity roleEntity = RoleAdapter.toRoleEntity(role, em);
realm.getRoles().remove(roleEntity);
realm.getDefaultRoles().remove(roleEntity);
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
em.createNamedQuery("deleteScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
em.createNamedQuery("deleteTemplateScopeMappingByRole").setParameter("role", roleEntity).executeUpdate();
em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
em.remove(roleEntity);
em.flush();
return true;
} }
@Override @Override
public Set<RoleModel> getRoles() { public Set<RoleModel> getRoles() {
Collection<RoleEntity> roles = realm.getRoles(); return session.realms().getRealmRoles(this);
if (roles == null) return Collections.EMPTY_SET;
Set<RoleModel> list = new HashSet<RoleModel>();
for (RoleEntity entity : roles) {
list.add(new RoleAdapter(session, this, em, entity));
// can't get it from cache cuz of stack overflow
// list.add(session.realms().getRoleById(entity.getId(), this));
}
return Collections.unmodifiableSet(list);
} }
@Override @Override

View file

@ -157,9 +157,6 @@ public class ClientEntity {
@Column(name="NODE_REREG_TIMEOUT") @Column(name="NODE_REREG_TIMEOUT")
private int nodeReRegistrationTimeout; private int nodeReRegistrationTimeout;
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, mappedBy = "client")
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true) @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="CLIENT_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")}) @JoinTable(name="CLIENT_DEFAULT_ROLES", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="ROLE_ID")})
Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>(); Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
@ -354,14 +351,6 @@ public class ClientEntity {
this.managementUrl = managementUrl; this.managementUrl = managementUrl;
} }
public Collection<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Collection<RoleEntity> roles) {
this.roles = roles;
}
public Collection<RoleEntity> getDefaultRoles() { public Collection<RoleEntity> getDefaultRoles() {
return defaultRoles; return defaultRoles;
} }

View file

@ -150,9 +150,6 @@ public class RealmEntity {
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm") @OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
Collection<ClientTemplateEntity> clientTemplates = new ArrayList<>(); Collection<ClientTemplateEntity> clientTemplates = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, mappedBy = "realm")
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
@ElementCollection @ElementCollection
@MapKeyColumn(name="NAME") @MapKeyColumn(name="NAME")
@Column(name="VALUE") @Column(name="VALUE")
@ -418,21 +415,6 @@ public class RealmEntity {
public void setRequiredCredentials(Collection<RequiredCredentialEntity> requiredCredentials) { public void setRequiredCredentials(Collection<RequiredCredentialEntity> requiredCredentials) {
this.requiredCredentials = requiredCredentials; this.requiredCredentials = requiredCredentials;
} }
public Collection<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Collection<RoleEntity> roles) {
this.roles = roles;
}
public void addRole(RoleEntity role) {
if (roles == null) {
roles = new ArrayList<RoleEntity>();
}
roles.add(role);
}
public Map<String, String> getSmtpConfig() { public Map<String, String> getSmtpConfig() {
return smtpConfig; return smtpConfig;
} }

View file

@ -52,6 +52,8 @@ import java.util.Collection;
@NamedQuery(name="getClientRoleIds", query="select role.id from RoleEntity role where role.client.id = :client"), @NamedQuery(name="getClientRoleIds", query="select role.id from RoleEntity role where role.client.id = :client"),
@NamedQuery(name="getClientRoleByName", query="select role from RoleEntity role where role.name = :name and role.client = :client"), @NamedQuery(name="getClientRoleByName", query="select role from RoleEntity role where role.name = :name and role.client = :client"),
@NamedQuery(name="getClientRoleIdByName", query="select role.id from RoleEntity role where role.name = :name and role.client.id = :client"), @NamedQuery(name="getClientRoleIdByName", query="select role.id from RoleEntity role where role.name = :name and role.client.id = :client"),
@NamedQuery(name="getRealmRoles", query="select role from RoleEntity role where role.clientRole = false and role.realm = :realm"),
@NamedQuery(name="getRealmRoleIds", query="select role.id from RoleEntity role where role.clientRole = false and role.realm.id = :realm"),
@NamedQuery(name="getRealmRoleByName", query="select role from RoleEntity role where role.clientRole = false and role.name = :name and role.realm = :realm"), @NamedQuery(name="getRealmRoleByName", query="select role from RoleEntity role where role.clientRole = false and role.name = :name and role.realm = :realm"),
@NamedQuery(name="getRealmRoleIdByName", query="select role.id from RoleEntity role where role.clientRole = false and role.name = :name and role.realm.id = :realm") @NamedQuery(name="getRealmRoleIdByName", query="select role.id from RoleEntity role where role.clientRole = false and role.name = :name and role.realm.id = :realm")
}) })
@ -108,6 +110,8 @@ public class RoleEntity {
this.realmId = realmId; this.realmId = realmId;
} }
public String getName() { public String getName() {
return name; return name;
} }

View file

@ -567,34 +567,18 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
} }
@Override @Override
public RoleAdapter getRole(String name) { public RoleModel getRole(String name) {
DBObject query = new QueryBuilder() return session.realms().getClientRole(realm, this, name);
.and("name").is(name)
.and("clientId").is(getId())
.get();
MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
if (role == null) {
return null;
} else {
return new RoleAdapter(session, getRealm(), role, invocationContext);
}
} }
@Override @Override
public RoleAdapter addRole(String name) { public RoleModel addRole(String name) {
return this.addRole(null, name); return session.realms().addClientRole(realm, this, name);
} }
@Override @Override
public RoleAdapter addRole(String id, String name) { public RoleModel addRole(String id, String name) {
MongoRoleEntity roleEntity = new MongoRoleEntity(); return session.realms().addClientRole(realm, this, id, name);
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setClientId(getId());
getMongoStore().insertEntity(roleEntity, invocationContext);
return new RoleAdapter(session, getRealm(), roleEntity, this, invocationContext);
} }
@Override @Override
@ -605,17 +589,7 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
@Override @Override
public Set<RoleModel> getRoles() { public Set<RoleModel> getRoles() {
DBObject query = new QueryBuilder() return session.realms().getClientRoles(realm, this);
.and("clientId").is(getId())
.get();
List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
Set<RoleModel> result = new HashSet<RoleModel>();
for (MongoRoleEntity role : roles) {
result.add(new RoleAdapter(session, getRealm(), role, this, invocationContext));
}
return result;
} }
@Override @Override
@ -653,7 +627,7 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
} }
@Override @Override
public void updateDefaultRoles(String[] defaultRoles) { public void updateDefaultRoles(String... defaultRoles) {
List<String> roleNames = new ArrayList<String>(); List<String> roleNames = new ArrayList<String>();
for (String roleName : defaultRoles) { for (String roleName : defaultRoles) {
RoleModel role = getRole(roleName); RoleModel role = getRole(roleName);
@ -668,6 +642,17 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
updateMongoEntity(); updateMongoEntity();
} }
@Override
public void removeDefaultRoles(String... defaultRoles) {
List<String> roleNames = new ArrayList<String>();
for (String role : getMongoEntity().getDefaultRoles()) {
if (!RealmAdapter.contains(role, defaultRoles)) roleNames.add(role);
}
getMongoEntity().setDefaultRoles(roleNames);
updateMongoEntity();
}
@Override @Override
public int getNodeReRegistrationTimeout() { public int getNodeReRegistrationTimeout() {
return getMongoEntity().getNodeReRegistrationTimeout(); return getMongoEntity().getNodeReRegistrationTimeout();

View file

@ -40,7 +40,9 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -209,6 +211,107 @@ public class MongoRealmProvider implements RealmProvider {
return Collections.unmodifiableList(result); return Collections.unmodifiableList(result);
} }
@Override
public RoleModel addRealmRole(RealmModel realm, String name) {
return addRealmRole(realm, KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addRealmRole(RealmModel realm, String id, String name) {
MongoRoleEntity roleEntity = new MongoRoleEntity();
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setRealmId(realm.getId());
getMongoStore().insertEntity(roleEntity, invocationContext);
return new RoleAdapter(session, realm, roleEntity, realm, invocationContext);
}
@Override
public Set<RoleModel> getRealmRoles(RealmModel realm) {
DBObject query = new QueryBuilder()
.and("realmId").is(realm.getId())
.get();
List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
if (roles == null) return Collections.EMPTY_SET;
Set<RoleModel> result = new HashSet<RoleModel>();
for (MongoRoleEntity role : roles) {
result.add(session.realms().getRoleById(role.getId(), realm));
}
return Collections.unmodifiableSet(result);
}
@Override
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client) {
DBObject query = new QueryBuilder()
.and("clientId").is(client.getId())
.get();
List<MongoRoleEntity> roles = getMongoStore().loadEntities(MongoRoleEntity.class, query, invocationContext);
Set<RoleModel> result = new HashSet<RoleModel>();
for (MongoRoleEntity role : roles) {
result.add(session.realms().getRoleById(role.getId(), realm));
}
return result;
}
@Override
public RoleModel getRealmRole(RealmModel realm, String name) {
DBObject query = new QueryBuilder()
.and("name").is(name)
.and("realmId").is(realm.getId())
.get();
MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
if (role == null) {
return null;
} else {
return session.realms().getRoleById(role.getId(), realm);
}
}
@Override
public RoleModel getClientRole(RealmModel realm, ClientModel client, String name) {
DBObject query = new QueryBuilder()
.and("name").is(name)
.and("clientId").is(client.getId())
.get();
MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
if (role == null) {
return null;
} else {
return session.realms().getRoleById(role.getId(), realm);
}
}
@Override
public RoleModel addClientRole(RealmModel realm, ClientModel client, String name) {
return addClientRole(realm, client, KeycloakModelUtils.generateId(), name);
}
@Override
public RoleModel addClientRole(RealmModel realm, ClientModel client, String id, String name) {
MongoRoleEntity roleEntity = new MongoRoleEntity();
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setClientId(client.getId());
getMongoStore().insertEntity(roleEntity, invocationContext);
return new RoleAdapter(session, realm, roleEntity, client, invocationContext);
}
@Override
public boolean removeRole(RealmModel realm, RoleModel role) {
session.users().preRemove(realm, role);
return getMongoStore().removeEntity(MongoRoleEntity.class, role.getId(), invocationContext);
}
@Override @Override
public boolean removeClient(String id, RealmModel realm) { public boolean removeClient(String id, RealmModel realm) {
if (id == null) return false; if (id == null) return false;

View file

@ -595,47 +595,30 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
} }
@Override @Override
public RoleAdapter getRole(String name) { public RoleModel getRole(String name) {
DBObject query = new QueryBuilder() return session.realms().getRealmRole(this, name);
.and("name").is(name)
.and("realmId").is(getId())
.get();
MongoRoleEntity role = getMongoStore().loadSingleEntity(MongoRoleEntity.class, query, invocationContext);
if (role == null) {
return null;
} else {
return new RoleAdapter(session, this, role, this, invocationContext);
}
} }
@Override @Override
public RoleModel addRole(String name) { public RoleModel addRole(String name) {
return this.addRole(null, name); return session.realms().addRealmRole(this, name);
} }
@Override @Override
public RoleModel addRole(String id, String name) { public RoleModel addRole(String id, String name) {
MongoRoleEntity roleEntity = new MongoRoleEntity(); return session.realms().addRealmRole(this, id, name);
roleEntity.setId(id);
roleEntity.setName(name);
roleEntity.setRealmId(getId());
getMongoStore().insertEntity(roleEntity, invocationContext);
return new RoleAdapter(session, this, roleEntity, this, invocationContext);
} }
@Override @Override
public boolean removeRole(RoleModel role) { public boolean removeRole(RoleModel role) {
return removeRoleById(role.getId()); return session.realms().removeRole(this, role);
} }
@Override @Override
public boolean removeRoleById(String id) { public boolean removeRoleById(String id) {
RoleModel role = getRoleById(id); RoleModel role = getRoleById(id);
if (role == null) return false; if (role == null) return false;
session.users().preRemove(this, role); return removeRole(role);
return getMongoStore().removeEntity(MongoRoleEntity.class, id, invocationContext);
} }
@Override @Override
@ -657,7 +640,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
@Override @Override
public RoleModel getRoleById(String id) { public RoleModel getRoleById(String id) {
return model.getRoleById(id, this); return session.realms().getRoleById(id, this);
} }
@Override @Override
@ -780,6 +763,24 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
updateRealm(); updateRealm();
} }
public static boolean contains(String str, String[] array) {
for (String s : array) {
if (str.equals(s)) return true;
}
return false;
}
@Override
public void removeDefaultRoles(String... defaultRoles) {
List<String> roleNames = new ArrayList<String>();
for (String role : realm.getDefaultRoles()) {
if (!contains(role, defaultRoles)) roleNames.add(role);
}
realm.setDefaultRoles(roleNames);
updateRealm();
}
@Override @Override
public List<GroupModel> getDefaultGroups() { public List<GroupModel> getDefaultGroups() {
List<String> entities = realm.getDefaultGroups(); List<String> entities = realm.getDefaultGroups();

View file

@ -85,12 +85,6 @@ public interface ClientModel extends RoleContainerModel, ProtocolMapperContaine
void setBaseUrl(String url); void setBaseUrl(String url);
List<String> getDefaultRoles();
void addDefaultRole(String name);
void updateDefaultRoles(String[] defaultRoles);
boolean isBearerOnly(); boolean isBearerOnly();
void setBearerOnly(boolean only); void setBearerOnly(boolean only);

View file

@ -181,12 +181,6 @@ public interface RealmModel extends RoleContainerModel {
RoleModel getRoleById(String id); RoleModel getRoleById(String id);
List<String> getDefaultRoles();
void addDefaultRole(String name);
void updateDefaultRoles(String[] defaultRoles);
List<GroupModel> getDefaultGroups(); List<GroupModel> getDefaultGroups();
void addDefaultGroup(GroupModel group); void addDefaultGroup(GroupModel group);

View file

@ -21,6 +21,7 @@ import org.keycloak.migration.MigrationModel;
import org.keycloak.provider.Provider; import org.keycloak.provider.Provider;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -45,6 +46,24 @@ public interface RealmProvider extends Provider {
ClientModel getClientByClientId(String clientId, RealmModel realm); ClientModel getClientByClientId(String clientId, RealmModel realm);
RoleModel addRealmRole(RealmModel realm, String name);
RoleModel addRealmRole(RealmModel realm, String id, String name);
RoleModel getRealmRole(RealmModel realm, String name);
RoleModel addClientRole(RealmModel realm, ClientModel client, String name);
RoleModel addClientRole(RealmModel realm, ClientModel client, String id, String name);
Set<RoleModel> getRealmRoles(RealmModel realm);
RoleModel getClientRole(RealmModel realm, ClientModel client, String name);
Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client);
boolean removeRole(RealmModel realm, RoleModel role);
RoleModel getRoleById(String id, RealmModel realm); RoleModel getRoleById(String id, RealmModel realm);
boolean removeClient(String id, RealmModel realm); boolean removeClient(String id, RealmModel realm);

View file

@ -17,6 +17,7 @@
package org.keycloak.models; package org.keycloak.models;
import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
@ -24,6 +25,8 @@ import java.util.Set;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public interface RoleContainerModel { public interface RoleContainerModel {
String getId();
RoleModel getRole(String name); RoleModel getRole(String name);
RoleModel addRole(String name); RoleModel addRole(String name);
@ -34,4 +37,11 @@ public interface RoleContainerModel {
Set<RoleModel> getRoles(); Set<RoleModel> getRoles();
List<String> getDefaultRoles();
void addDefaultRole(String name);
void updateDefaultRoles(String... defaultRoles);
void removeDefaultRoles(String... defaultRoles);
} }