KEYCLOAK-14972 Add independent GroupProvider interface
This commit is contained in:
parent
fdcfa6e13e
commit
ae39760a62
22 changed files with 545 additions and 96 deletions
|
@ -123,7 +123,7 @@ public class SSSDFederationProvider implements UserStorageProvider,
|
|||
for (String s : sssd.getGroups()) {
|
||||
GroupModel group = KeycloakModelUtils.findGroupByPath(realm, "/" + s);
|
||||
if (group == null) {
|
||||
group = session.realms().createGroup(realm, s);
|
||||
group = session.groups().createGroup(realm, s);
|
||||
}
|
||||
user.joinGroup(group);
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ public class GroupAdapter implements GroupModel {
|
|||
protected boolean isUpdated() {
|
||||
if (updated != null) return true;
|
||||
if (!invalidated) return false;
|
||||
updated = cacheSession.getRealmDelegate().getGroupById(cached.getId(), realm);
|
||||
updated = cacheSession.getGroupDelegate().getGroupById(realm, cached.getId());
|
||||
if (updated == null) throw new IllegalStateException("Not found in database");
|
||||
return true;
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ public class GroupAdapter implements GroupModel {
|
|||
public GroupModel getParent() {
|
||||
if (isUpdated()) return updated.getParent();
|
||||
if (cached.getParentId() == null) return null;
|
||||
return keycloakSession.realms().getGroupById(cached.getParentId(), realm);
|
||||
return keycloakSession.groups().getGroupById(realm, cached.getParentId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -238,7 +238,7 @@ public class GroupAdapter implements GroupModel {
|
|||
if (isUpdated()) return updated.getSubGroups();
|
||||
Set<GroupModel> subGroups = new HashSet<>();
|
||||
for (String id : cached.getSubGroups(modelSupplier)) {
|
||||
GroupModel subGroup = keycloakSession.realms().getGroupById(id, realm);
|
||||
GroupModel subGroup = keycloakSession.groups().getGroupById(realm, id);
|
||||
if (subGroup == null) {
|
||||
// chance that role was removed, so just delegate to persistence and get user invalidated
|
||||
getDelegateForUpdate();
|
||||
|
@ -273,6 +273,6 @@ public class GroupAdapter implements GroupModel {
|
|||
}
|
||||
|
||||
private GroupModel getGroupModel() {
|
||||
return cacheSession.getRealmDelegate().getGroupById(cached.getId(), realm);
|
||||
return cacheSession.getGroupDelegate().getGroupById(realm, cached.getId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -710,7 +710,7 @@ public class RealmAdapter implements CachedRealmModel {
|
|||
|
||||
List<GroupModel> defaultGroups = new LinkedList<>();
|
||||
for (String id : cached.getDefaultGroups()) {
|
||||
defaultGroups.add(cacheSession.getGroupById(id, this));
|
||||
defaultGroups.add(cacheSession.getGroupById(this, id));
|
||||
}
|
||||
return Collections.unmodifiableList(defaultGroups);
|
||||
|
||||
|
@ -1416,7 +1416,7 @@ public class RealmAdapter implements CachedRealmModel {
|
|||
|
||||
@Override
|
||||
public GroupModel getGroupById(String id) {
|
||||
return cacheSession.getGroupById(id, this);
|
||||
return cacheSession.getGroupById(this, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -101,6 +101,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
protected KeycloakSession session;
|
||||
protected RealmProvider realmDelegate;
|
||||
protected ClientProvider clientDelegate;
|
||||
protected GroupProvider groupDelegate;
|
||||
protected RoleProvider roleDelegate;
|
||||
protected boolean transactionActive;
|
||||
protected boolean setRollbackOnly;
|
||||
|
@ -163,8 +164,12 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
roleDelegate = session.roleStorageManager();
|
||||
return roleDelegate;
|
||||
}
|
||||
|
||||
|
||||
public GroupProvider getGroupDelegate() {
|
||||
if (!transactionActive) throw new IllegalStateException("Cannot access delegate without a transaction");
|
||||
if (groupDelegate != null) return groupDelegate;
|
||||
groupDelegate = session.groupLocalStorage();
|
||||
return groupDelegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -826,7 +831,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public GroupModel getGroupById(String id, RealmModel realm) {
|
||||
public GroupModel getGroupById(RealmModel realm, String id) {
|
||||
CachedGroup cached = cache.get(id, CachedGroup.class);
|
||||
if (cached != null && !cached.getRealm().equals(realm.getId())) {
|
||||
cached = null;
|
||||
|
@ -834,14 +839,14 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
if (cached == null) {
|
||||
Long loaded = cache.getCurrentRevision(id);
|
||||
GroupModel model = getRealmDelegate().getGroupById(id, realm);
|
||||
GroupModel model = getGroupDelegate().getGroupById(realm, id);
|
||||
if (model == null) return null;
|
||||
if (invalidations.contains(id)) return model;
|
||||
cached = new CachedGroup(loaded, realm, model);
|
||||
cache.addRevisioned(cached, startupRevision);
|
||||
|
||||
} else if (invalidations.contains(id)) {
|
||||
return getRealmDelegate().getGroupById(id, realm);
|
||||
return getGroupDelegate().getGroupById(realm, id);
|
||||
} else if (managedGroups.containsKey(id)) {
|
||||
return managedGroups.get(id);
|
||||
}
|
||||
|
@ -857,7 +862,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
listInvalidations.add(realm.getId());
|
||||
|
||||
invalidationEvents.add(GroupMovedEvent.create(group, toParent, realm.getId()));
|
||||
getRealmDelegate().moveGroup(realm, group, toParent);
|
||||
getGroupDelegate().moveGroup(realm, group, toParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -865,7 +870,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
String cacheKey = getGroupsQueryCacheKey(realm.getId());
|
||||
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
|
||||
if (queryDB) {
|
||||
return getRealmDelegate().getGroups(realm);
|
||||
return getGroupDelegate().getGroups(realm);
|
||||
}
|
||||
|
||||
GroupListQuery query = cache.get(cacheKey, GroupListQuery.class);
|
||||
|
@ -875,7 +880,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
if (query == null) {
|
||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||
List<GroupModel> model = getRealmDelegate().getGroups(realm);
|
||||
List<GroupModel> model = getGroupDelegate().getGroups(realm);
|
||||
if (model == null) return null;
|
||||
Set<String> ids = new HashSet<>();
|
||||
for (GroupModel client : model) ids.add(client.getId());
|
||||
|
@ -886,10 +891,10 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
}
|
||||
List<GroupModel> list = new LinkedList<>();
|
||||
for (String id : query.getGroups()) {
|
||||
GroupModel group = session.realms().getGroupById(id, realm);
|
||||
GroupModel group = session.groups().getGroupById(realm, id);
|
||||
if (group == null) {
|
||||
invalidations.add(cacheKey);
|
||||
return getRealmDelegate().getGroups(realm);
|
||||
return getGroupDelegate().getGroups(realm);
|
||||
}
|
||||
list.add(group);
|
||||
}
|
||||
|
@ -901,7 +906,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
@Override
|
||||
public Long getGroupsCount(RealmModel realm, Boolean onlyTopGroups) {
|
||||
return getRealmDelegate().getGroupsCount(realm, onlyTopGroups);
|
||||
return getGroupDelegate().getGroupsCount(realm, onlyTopGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -911,12 +916,12 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
@Override
|
||||
public Long getGroupsCountByNameContaining(RealmModel realm, String search) {
|
||||
return getRealmDelegate().getGroupsCountByNameContaining(realm, search);
|
||||
return getGroupDelegate().getGroupsCountByNameContaining(realm, search);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupModel> getGroupsByRole(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
||||
return getRealmDelegate().getGroupsByRole(realm, role, firstResult, maxResults);
|
||||
return getGroupDelegate().getGroupsByRole(realm, role, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -924,7 +929,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
String cacheKey = getTopGroupsQueryCacheKey(realm.getId());
|
||||
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
|
||||
if (queryDB) {
|
||||
return getRealmDelegate().getTopLevelGroups(realm);
|
||||
return getGroupDelegate().getTopLevelGroups(realm);
|
||||
}
|
||||
|
||||
GroupListQuery query = cache.get(cacheKey, GroupListQuery.class);
|
||||
|
@ -934,7 +939,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
if (query == null) {
|
||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||
List<GroupModel> model = getRealmDelegate().getTopLevelGroups(realm);
|
||||
List<GroupModel> model = getGroupDelegate().getTopLevelGroups(realm);
|
||||
if (model == null) return null;
|
||||
Set<String> ids = new HashSet<>();
|
||||
for (GroupModel client : model) ids.add(client.getId());
|
||||
|
@ -945,10 +950,10 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
}
|
||||
List<GroupModel> list = new LinkedList<>();
|
||||
for (String id : query.getGroups()) {
|
||||
GroupModel group = session.realms().getGroupById(id, realm);
|
||||
GroupModel group = session.groups().getGroupById(realm, id);
|
||||
if (group == null) {
|
||||
invalidations.add(cacheKey);
|
||||
return getRealmDelegate().getTopLevelGroups(realm);
|
||||
return getGroupDelegate().getTopLevelGroups(realm);
|
||||
}
|
||||
list.add(group);
|
||||
}
|
||||
|
@ -963,7 +968,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
String cacheKey = getTopGroupsQueryCacheKey(realm.getId() + first + max);
|
||||
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId() + first + max);
|
||||
if (queryDB) {
|
||||
return getRealmDelegate().getTopLevelGroups(realm, first, max);
|
||||
return getGroupDelegate().getTopLevelGroups(realm, first, max);
|
||||
}
|
||||
|
||||
GroupListQuery query = cache.get(cacheKey, GroupListQuery.class);
|
||||
|
@ -973,7 +978,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
if (Objects.isNull(query)) {
|
||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||
List<GroupModel> model = getRealmDelegate().getTopLevelGroups(realm, first, max);
|
||||
List<GroupModel> model = getGroupDelegate().getTopLevelGroups(realm, first, max);
|
||||
if (model == null) return null;
|
||||
Set<String> ids = new HashSet<>();
|
||||
for (GroupModel client : model) ids.add(client.getId());
|
||||
|
@ -984,10 +989,10 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
}
|
||||
List<GroupModel> list = new LinkedList<>();
|
||||
for (String id : query.getGroups()) {
|
||||
GroupModel group = session.realms().getGroupById(id, realm);
|
||||
GroupModel group = session.groups().getGroupById(realm, id);
|
||||
if (Objects.isNull(group)) {
|
||||
invalidations.add(cacheKey);
|
||||
return getRealmDelegate().getTopLevelGroups(realm);
|
||||
return getGroupDelegate().getTopLevelGroups(realm);
|
||||
}
|
||||
list.add(group);
|
||||
}
|
||||
|
@ -999,7 +1004,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
@Override
|
||||
public List<GroupModel> searchForGroupByName(RealmModel realm, String search, Integer first, Integer max) {
|
||||
return getRealmDelegate().searchForGroupByName(realm, search, first, max);
|
||||
return getGroupDelegate().searchForGroupByName(realm, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1013,7 +1018,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
invalidationEvents.add(GroupRemovedEvent.create(group, realm.getId()));
|
||||
|
||||
return getRealmDelegate().removeGroup(realm, group);
|
||||
return getGroupDelegate().removeGroup(realm, group);
|
||||
}
|
||||
|
||||
private GroupModel groupAdded(RealmModel realm, GroupModel group, GroupModel toParent) {
|
||||
|
@ -1027,7 +1032,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
@Override
|
||||
public GroupModel createGroup(RealmModel realm, String id, String name, GroupModel toParent) {
|
||||
GroupModel group = getRealmDelegate().createGroup(realm, id, name, toParent);
|
||||
GroupModel group = getGroupDelegate().createGroup(realm, id, name, toParent);
|
||||
return groupAdded(realm, group, toParent);
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1045,7 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
addGroupEventIfAbsent(GroupMovedEvent.create(subGroup, null, realm.getId()));
|
||||
|
||||
getRealmDelegate().addTopLevelGroup(realm, subGroup);
|
||||
getGroupDelegate().addTopLevelGroup(realm, subGroup);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -352,7 +352,7 @@ public class UserAdapter implements CachedUserModel {
|
|||
if (updated != null) return updated.getGroups();
|
||||
Set<GroupModel> groups = new LinkedHashSet<>();
|
||||
for (String id : cached.getGroups(modelSupplier)) {
|
||||
GroupModel groupModel = keycloakSession.realms().getGroupById(id, realm);
|
||||
GroupModel groupModel = keycloakSession.groups().getGroupById(realm, id);
|
||||
if (groupModel == null) {
|
||||
// chance that role was removed, so just delete to persistence and get user invalidated
|
||||
getDelegateForUpdate();
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2020 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.keycloak.Config;
|
||||
import org.keycloak.connections.jpa.JpaConnectionProvider;
|
||||
import org.keycloak.models.GroupProvider;
|
||||
import org.keycloak.models.GroupProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
public class JpaGroupProviderFactory implements GroupProviderFactory {
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "jpa";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupProvider create(KeycloakSession session) {
|
||||
EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||
return new JpaRealmProvider(session, em);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@ import org.keycloak.models.ClientModel;
|
|||
import org.keycloak.models.ClientProvider;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.GroupProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -57,7 +58,7 @@ import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProvider {
|
||||
public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupProvider, RoleProvider {
|
||||
protected static final Logger logger = Logger.getLogger(JpaRealmProvider.class);
|
||||
private final KeycloakSession session;
|
||||
protected EntityManager em;
|
||||
|
@ -169,7 +170,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
removeRoles(adapter);
|
||||
|
||||
for (GroupModel group : adapter.getGroups()) {
|
||||
session.realms().removeGroup(adapter, group);
|
||||
session.groups().removeGroup(adapter, group);
|
||||
}
|
||||
|
||||
num = em.createNamedQuery("removeClientInitialAccessByRealm")
|
||||
|
@ -395,7 +396,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
}
|
||||
|
||||
@Override
|
||||
public GroupModel getGroupById(String id, RealmModel realm) {
|
||||
public GroupModel getGroupById(RealmModel realm, String id) {
|
||||
GroupEntity groupEntity = em.find(GroupEntity.class, id);
|
||||
if (groupEntity == null) return null;
|
||||
if (!groupEntity.getRealm().equals(realm.getId())) return null;
|
||||
|
@ -413,7 +414,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
}
|
||||
group.setParent(toParent);
|
||||
if (toParent != null) toParent.addChild(group);
|
||||
else session.realms().addTopLevelGroup(realm, group);
|
||||
else session.groups().addTopLevelGroup(realm, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -421,7 +422,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
RealmEntity ref = em.getReference(RealmEntity.class, realm.getId());
|
||||
|
||||
return ref.getGroups().stream()
|
||||
.map(g -> session.realms().getGroupById(g.getId(), realm))
|
||||
.map(g -> session.groups().getGroupById(realm, g.getId()))
|
||||
.sorted(Comparator.comparing(GroupModel::getName))
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toList(), Collections::unmodifiableList));
|
||||
|
@ -479,7 +480,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
|
||||
return ref.getGroups().stream()
|
||||
.filter(g -> GroupEntity.TOP_PARENT_ID.equals(g.getParentId()))
|
||||
.map(g -> session.realms().getGroupById(g.getId(), realm))
|
||||
.map(g -> session.groups().getGroupById(realm, g.getId()))
|
||||
.sorted(Comparator.comparing(GroupModel::getName))
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toList(), Collections::unmodifiableList));
|
||||
|
@ -496,7 +497,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
List<GroupModel> list = new ArrayList<>();
|
||||
if(Objects.nonNull(groupIds) && !groupIds.isEmpty()) {
|
||||
for (String id : groupIds) {
|
||||
GroupModel group = getGroupById(id, realm);
|
||||
GroupModel group = getGroupById(realm, id);
|
||||
list.add(group);
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +533,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
|
||||
realm.removeDefaultGroup(group);
|
||||
for (GroupModel subGroup : group.getSubGroups()) {
|
||||
session.realms().removeGroup(realm, subGroup);
|
||||
session.groups().removeGroup(realm, subGroup);
|
||||
}
|
||||
GroupEntity groupEntity = em.find(GroupEntity.class, group.getId(), LockModeType.PESSIMISTIC_WRITE);
|
||||
if ((groupEntity == null) || (!groupEntity.getRealm().equals(realm.getId()))) {
|
||||
|
@ -753,9 +754,9 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, RoleProv
|
|||
if (Objects.isNull(groups)) return Collections.EMPTY_LIST;
|
||||
List<GroupModel> list = new ArrayList<>();
|
||||
for (String id : groups) {
|
||||
GroupModel groupById = session.realms().getGroupById(id, realm);
|
||||
GroupModel groupById = session.groups().getGroupById(realm, id);
|
||||
while(Objects.nonNull(groupById.getParentId())) {
|
||||
groupById = session.realms().getGroupById(groupById.getParentId(), realm);
|
||||
groupById = session.groups().getGroupById(realm, groupById.getParentId());
|
||||
}
|
||||
if(!list.contains(groupById)) {
|
||||
list.add(groupById);
|
||||
|
|
|
@ -797,7 +797,7 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
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));
|
||||
defaultGroups.add(session.groups().getGroupById(this, entity.getId()));
|
||||
}
|
||||
return Collections.unmodifiableList(defaultGroups);
|
||||
}
|
||||
|
@ -2022,52 +2022,52 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
@Override
|
||||
public GroupModel createGroup(String id, String name, GroupModel toParent) {
|
||||
return session.realms().createGroup(this, id, name, toParent);
|
||||
return session.groups().createGroup(this, id, name, toParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveGroup(GroupModel group, GroupModel toParent) {
|
||||
session.realms().moveGroup(this, group, toParent);
|
||||
session.groups().moveGroup(this, group, toParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupModel getGroupById(String id) {
|
||||
return session.realms().getGroupById(id, this);
|
||||
return session.groups().getGroupById(this, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupModel> getGroups() {
|
||||
return session.realms().getGroups(this);
|
||||
return session.groups().getGroups(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getGroupsCount(Boolean onlyTopGroups) {
|
||||
return session.realms().getGroupsCount(this, onlyTopGroups);
|
||||
return session.groups().getGroupsCount(this, onlyTopGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getGroupsCountByNameContaining(String search) {
|
||||
return session.realms().getGroupsCountByNameContaining(this, search);
|
||||
return session.groups().getGroupsCountByNameContaining(this, search);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupModel> getTopLevelGroups() {
|
||||
return session.realms().getTopLevelGroups(this);
|
||||
return session.groups().getTopLevelGroups(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupModel> getTopLevelGroups(Integer first, Integer max) {
|
||||
return session.realms().getTopLevelGroups(this, first, max);
|
||||
return session.groups().getTopLevelGroups(this, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupModel> searchForGroupByName(String search, Integer first, Integer max) {
|
||||
return session.realms().searchForGroupByName(this, search, first, max);
|
||||
return session.groups().searchForGroupByName(this, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeGroup(GroupModel group) {
|
||||
return session.realms().removeGroup(this, group);
|
||||
return session.groups().removeGroup(this, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# Copyright 2020 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.
|
||||
#
|
||||
|
||||
org.keycloak.models.jpa.JpaGroupProviderFactory
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
public interface GroupProviderFactory extends ProviderFactory<GroupProvider> {
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.provider.Spi;
|
||||
|
||||
public class GroupSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public boolean isInternal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "group";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return GroupProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return GroupProviderFactory.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
package org.keycloak.models.cache;
|
||||
|
||||
import org.keycloak.models.ClientProvider;
|
||||
import org.keycloak.models.GroupProvider;
|
||||
import org.keycloak.models.RealmProvider;
|
||||
import org.keycloak.models.RoleProvider;
|
||||
|
||||
|
@ -25,7 +26,7 @@ import org.keycloak.models.RoleProvider;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface CacheRealmProvider extends RealmProvider, ClientProvider, RoleProvider {
|
||||
public interface CacheRealmProvider extends RealmProvider, ClientProvider, GroupProvider, RoleProvider {
|
||||
void clear();
|
||||
RealmProvider getRealmDelegate();
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ org.keycloak.provider.ExceptionConverterSpi
|
|||
org.keycloak.storage.UserStorageProviderSpi
|
||||
org.keycloak.storage.federated.UserFederatedStorageProviderSpi
|
||||
org.keycloak.models.ClientSpi
|
||||
org.keycloak.models.GroupSpi
|
||||
org.keycloak.models.RealmSpi
|
||||
org.keycloak.models.RoleSpi
|
||||
org.keycloak.models.ActionTokenStoreSpi
|
||||
|
|
198
server-spi/src/main/java/org/keycloak/models/GroupProvider.java
Normal file
198
server-spi/src/main/java/org/keycloak/models/GroupProvider.java
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright 2020 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;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Provider of group records
|
||||
* @author mhajas
|
||||
*
|
||||
*/
|
||||
public interface GroupProvider extends Provider {
|
||||
|
||||
/**
|
||||
* Returns a group from the given realm with the corresponding id
|
||||
*
|
||||
* @param id Id.
|
||||
* @param realm Realm.
|
||||
* @return GroupModel with the corresponding id.
|
||||
* @deprecated Use method {@code getGroupById(realm, id)}
|
||||
*/
|
||||
default GroupModel getGroupById(String id, RealmModel realm) {
|
||||
return getGroupById(realm, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group from the given realm with the corresponding id
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param id Id.
|
||||
* @return GroupModel with the corresponding id.
|
||||
*/
|
||||
GroupModel getGroupById(RealmModel realm, String id);
|
||||
|
||||
/**
|
||||
* Returns groups for the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @return List of groups in the Realm.
|
||||
*/
|
||||
List<GroupModel> getGroups(RealmModel realm);
|
||||
|
||||
/**
|
||||
* Returns a number of groups/top level groups (i.e. groups without parent group) for the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param onlyTopGroups When true the function returns a count of top level groups only.
|
||||
* @return Number of groups/top level groups.
|
||||
*/
|
||||
Long getGroupsCount(RealmModel realm, Boolean onlyTopGroups);
|
||||
|
||||
/**
|
||||
* Returns number of groups with the given string in name for the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param search Searched string.
|
||||
* @return Number of groups with the given string in its name.
|
||||
*/
|
||||
Long getGroupsCountByNameContaining(RealmModel realm, String search);
|
||||
|
||||
/**
|
||||
* Returns groups with the given role in the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param role Role.
|
||||
* @param firstResult First result to return. Ignored if negative.
|
||||
* @param maxResults Maximum number of results to return. Ignored if negative.
|
||||
* @return List of groups with the given role.
|
||||
*/
|
||||
List<GroupModel> getGroupsByRole(RealmModel realm, RoleModel role, int firstResult, int maxResults);
|
||||
|
||||
/**
|
||||
* Returns all top level groups (i.e. groups without parent group) for the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @return List of all top level groups in the realm.
|
||||
*/
|
||||
List<GroupModel> getTopLevelGroups(RealmModel realm);
|
||||
|
||||
/**
|
||||
* Returns top level groups (i.e. groups without parent group) for the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param firstResult First result to return.
|
||||
* @param maxResults Maximum number of results to return.
|
||||
* @return List of top level groups in the realm.
|
||||
*/
|
||||
List<GroupModel> getTopLevelGroups(RealmModel realm, Integer firstResult, Integer maxResults);
|
||||
|
||||
/**
|
||||
* Returns groups with the given string in name for the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param search Searched string.
|
||||
* @param firstResult First result to return. Ignored if {@code null}.
|
||||
* @param maxResults Maximum number of results to return. Ignored if {@code null}.
|
||||
* @return List of groups with the given string in name.
|
||||
*/
|
||||
List<GroupModel> searchForGroupByName(RealmModel realm, String search, Integer firstResult, Integer maxResults);
|
||||
|
||||
/**
|
||||
* Creates a new group with the given name in the given realm.
|
||||
* Effectively the same as {@code createGroup(realm, null, name, null)}.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param name Name.
|
||||
* @return Model of the created group.
|
||||
*/
|
||||
default GroupModel createGroup(RealmModel realm, String name) {
|
||||
return createGroup(realm, null, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new group with the given id and name in the given realm.
|
||||
* Effectively the same as {@code createGroup(realm, id, name, null)}
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param id Id.
|
||||
* @param name Name.
|
||||
* @return Model of the created group
|
||||
*/
|
||||
default GroupModel createGroup(RealmModel realm, String id, String name) {
|
||||
return createGroup(realm, id, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new group with the given name and parent to the given realm.
|
||||
* Effectively the same as {@code createGroup(realm, null, name, toParent)}.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param name Name.
|
||||
* @param toParent Parent group.
|
||||
* @return Model of the created group.
|
||||
*/
|
||||
default GroupModel createGroup(RealmModel realm, String name, GroupModel toParent) {
|
||||
return createGroup(realm, null, name, toParent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new group with the given name, id, name and parent to the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param id Id, will be generated if {@code null}.
|
||||
* @param name Name.
|
||||
* @param toParent Parent group, or {@code null} if the group is top level group
|
||||
* @return Model of the created group
|
||||
*/
|
||||
GroupModel createGroup(RealmModel realm, String id, String name, GroupModel toParent);
|
||||
|
||||
/**
|
||||
* Removes the given group for the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param group Group.
|
||||
* @return true if the group was removed, false if group doesn't exist or doesn't belong to the given realm
|
||||
*/
|
||||
boolean removeGroup(RealmModel realm, GroupModel group);
|
||||
|
||||
/**
|
||||
* This method is used for moving groups in group structure, for example:
|
||||
* <ul>
|
||||
* <li>making an existing child group child group of some other group,</li>
|
||||
* <li>setting a top level group (i.e. group without parent group) child of some group,</li>
|
||||
* <li>making a child group top level group (i.e. removing its parent group).</li>
|
||||
* <ul/>
|
||||
*
|
||||
* @param realm Realm owning this group.
|
||||
* @param group Group to update.
|
||||
* @param toParent New parent group, or {@code null} if we are moving the group to top level group.
|
||||
*/
|
||||
void moveGroup(RealmModel realm, GroupModel group, GroupModel toParent);
|
||||
|
||||
/**
|
||||
* Removes parent group for the given group in the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param subGroup Group.
|
||||
*/
|
||||
void addTopLevelGroup(RealmModel realm, GroupModel subGroup);
|
||||
}
|
|
@ -115,6 +115,14 @@ public interface KeycloakSession {
|
|||
*/
|
||||
ClientProvider clients();
|
||||
|
||||
/**
|
||||
* Returns a managed group provider instance.
|
||||
*
|
||||
* @return Currently used GroupProvider instance.
|
||||
* @throws IllegalStateException if transaction is not active
|
||||
*/
|
||||
GroupProvider groups();
|
||||
|
||||
/**
|
||||
* Returns a managed provider instance. Will start a provider transaction. This transaction is managed by the KeycloakSession
|
||||
* transaction.
|
||||
|
@ -192,6 +200,13 @@ public interface KeycloakSession {
|
|||
*/
|
||||
ClientProvider clientLocalStorage();
|
||||
|
||||
/**
|
||||
* Keycloak specific local storage for groups. No cache in front, this api talks directly to storage configured for Keycloak
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
GroupProvider groupLocalStorage();
|
||||
|
||||
/**
|
||||
* Keycloak specific local storage for roles. No cache in front, this api talks directly to storage configured for Keycloak
|
||||
*
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.stream.Collectors;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface RealmProvider extends Provider /* TODO: Remove in future version */, ClientProvider, RoleProvider /* up to here */ {
|
||||
public interface RealmProvider extends Provider /* TODO: Remove in future version */, ClientProvider, GroupProvider, RoleProvider /* up to here */ {
|
||||
|
||||
// Note: The reason there are so many query methods here is for layering a cache on top of an persistent KeycloakSession
|
||||
MigrationModel getMigrationModel();
|
||||
|
@ -37,42 +37,7 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
|||
RealmModel getRealm(String id);
|
||||
RealmModel getRealmByName(String name);
|
||||
|
||||
void moveGroup(RealmModel realm, GroupModel group, GroupModel toParent);
|
||||
|
||||
List<GroupModel> getGroups(RealmModel realm);
|
||||
|
||||
Long getGroupsCount(RealmModel realm, Boolean onlyTopGroups);
|
||||
|
||||
Long getGroupsCountByNameContaining(RealmModel realm, String search);
|
||||
|
||||
List<GroupModel> getGroupsByRole(RealmModel realm, RoleModel role, int firstResult, int maxResults);
|
||||
|
||||
List<GroupModel> getTopLevelGroups(RealmModel realm);
|
||||
|
||||
List<GroupModel> getTopLevelGroups(RealmModel realm, Integer first, Integer max);
|
||||
|
||||
List searchForGroupByName(RealmModel realm, String search, Integer first, Integer max);
|
||||
|
||||
boolean removeGroup(RealmModel realm, GroupModel group);
|
||||
|
||||
default GroupModel createGroup(RealmModel realm, String name) {
|
||||
return createGroup(realm, null, name, null);
|
||||
}
|
||||
|
||||
default GroupModel createGroup(RealmModel realm, String id, String name) {
|
||||
return createGroup(realm, id, name, null);
|
||||
}
|
||||
|
||||
default GroupModel createGroup(RealmModel realm, String name, GroupModel toParent) {
|
||||
return createGroup(realm, null, name, toParent);
|
||||
}
|
||||
|
||||
GroupModel createGroup(RealmModel realm, String id, String name, GroupModel toParent);
|
||||
|
||||
void addTopLevelGroup(RealmModel realm, GroupModel subGroup);
|
||||
|
||||
ClientScopeModel getClientScopeById(String id, RealmModel realm);
|
||||
GroupModel getGroupById(String id, RealmModel realm);
|
||||
|
||||
List<RealmModel> getRealms();
|
||||
List<RealmModel> getRealmsWithProviderType(Class<?> type);
|
||||
|
@ -232,4 +197,93 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
|||
return searchForClientRolesStream(client, search, first, max).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/* GROUP PROVIDER METHODS */
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
void moveGroup(RealmModel realm, GroupModel group, GroupModel toParent);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
GroupModel getGroupById(RealmModel realm, String id);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
default GroupModel getGroupById(String id, RealmModel realm) {
|
||||
return getGroupById(realm, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
List<GroupModel> getGroups(RealmModel realm);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
Long getGroupsCount(RealmModel realm, Boolean onlyTopGroups);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
Long getGroupsCountByNameContaining(RealmModel realm, String search);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
List<GroupModel> getGroupsByRole(RealmModel realm, RoleModel role, int firstResult, int maxResults);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
List<GroupModel> getTopLevelGroups(RealmModel realm);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
List<GroupModel> getTopLevelGroups(RealmModel realm, Integer first, Integer max);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
List searchForGroupByName(RealmModel realm, String search, Integer first, Integer max);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
boolean removeGroup(RealmModel realm, GroupModel group);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
default GroupModel createGroup(RealmModel realm, String name) {
|
||||
return createGroup(realm, null, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
default GroupModel createGroup(RealmModel realm, String id, String name) {
|
||||
return createGroup(realm, id, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
default GroupModel createGroup(RealmModel realm, String name, GroupModel toParent) {
|
||||
return createGroup(realm, null, name, toParent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
GroupModel createGroup(RealmModel realm, String id, String name, GroupModel toParent);
|
||||
|
||||
/**
|
||||
* @deprecated Use the corresponding method from {@link GroupProvider}. */
|
||||
@Override
|
||||
void addTopLevelGroup(RealmModel realm, GroupModel subGroup);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.credential.UserCredentialStoreManager;
|
|||
import org.keycloak.jose.jws.DefaultTokenManager;
|
||||
import org.keycloak.keys.DefaultKeyManager;
|
||||
import org.keycloak.models.ClientProvider;
|
||||
import org.keycloak.models.GroupProvider;
|
||||
import org.keycloak.models.TokenManager;
|
||||
import org.keycloak.models.KeycloakContext;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -69,6 +70,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
private final Map<String, Object> attributes = new HashMap<>();
|
||||
private RealmProvider model;
|
||||
private ClientProvider clientProvider;
|
||||
private GroupProvider groupProvider;
|
||||
private RoleProvider roleProvider;
|
||||
private UserStorageManager userStorageManager;
|
||||
private ClientStorageManager clientStorageManager;
|
||||
|
@ -114,6 +116,16 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
}
|
||||
}
|
||||
|
||||
private GroupProvider getGroupProvider() {
|
||||
// TODO: Extract GroupProvider from CacheRealmProvider and use that instead
|
||||
GroupProvider cache = getProvider(CacheRealmProvider.class);
|
||||
if (cache != null) {
|
||||
return cache;
|
||||
} else {
|
||||
return groupLocalStorage();
|
||||
}
|
||||
}
|
||||
|
||||
private RoleProvider getRoleProvider() {
|
||||
// TODO: Extract RoleProvider from CacheRealmProvider and use that instead
|
||||
RoleProvider cache = getProvider(CacheRealmProvider.class);
|
||||
|
@ -190,6 +202,11 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
return getProvider(ClientProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupProvider groupLocalStorage() {
|
||||
return getProvider(GroupProvider.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientProvider clientStorageManager() {
|
||||
if (clientStorageManager == null) {
|
||||
|
@ -323,6 +340,14 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
return clientProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupProvider groups() {
|
||||
if (groupProvider == null) {
|
||||
groupProvider = getGroupProvider();
|
||||
}
|
||||
return groupProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoleProvider roles() {
|
||||
if (roleProvider == null) {
|
||||
|
|
|
@ -455,7 +455,7 @@ public class RoleContainerResource extends RoleResource {
|
|||
throw new NotFoundException("Could not find role");
|
||||
}
|
||||
|
||||
List<GroupModel> groupsModel = session.realms().getGroupsByRole(realm, role, firstResult, maxResults);
|
||||
List<GroupModel> groupsModel = session.groups().getGroupsByRole(realm, role, firstResult, maxResults);
|
||||
|
||||
return groupsModel.stream()
|
||||
.map(g -> ModelToRepresentation.toRepresentation(g, !briefRepresentation))
|
||||
|
|
|
@ -79,7 +79,6 @@ import javax.ws.rs.Consumes;
|
|||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotSupportedException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
|
@ -911,7 +910,7 @@ public class UserResource {
|
|||
public void removeMembership(@PathParam("groupId") String groupId) {
|
||||
auth.users().requireManageGroupMembership(user);
|
||||
|
||||
GroupModel group = session.realms().getGroupById(groupId, realm);
|
||||
GroupModel group = session.groups().getGroupById(realm, groupId);
|
||||
if (group == null) {
|
||||
throw new NotFoundException("Group not found");
|
||||
}
|
||||
|
@ -934,7 +933,7 @@ public class UserResource {
|
|||
@NoCache
|
||||
public void joinGroup(@PathParam("groupId") String groupId) {
|
||||
auth.users().requireManageGroupMembership(user);
|
||||
GroupModel group = session.realms().getGroupById(groupId, realm);
|
||||
GroupModel group = session.groups().getGroupById(realm, groupId);
|
||||
if (group == null) {
|
||||
throw new NotFoundException("Group not found");
|
||||
}
|
||||
|
|
|
@ -894,7 +894,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
|
|||
|
||||
session.getContext().setRealm(realm);
|
||||
|
||||
GroupModel customerAGroup = session.realms().createGroup(realm, "Customer A");
|
||||
GroupModel customerAGroup = session.groups().createGroup(realm, "Customer A");
|
||||
UserModel customerAManager = session.users().addUser(realm, "customer-a-manager");
|
||||
session.userCredentialManager().updateCredential(realm, customerAManager, UserCredentialModel.password("password"));
|
||||
ClientModel realmAdminClient = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
"provider": "${keycloak.client.provider:jpa}"
|
||||
},
|
||||
|
||||
"group": {
|
||||
"provider": "${keycloak.group.provider:jpa}"
|
||||
},
|
||||
|
||||
"role": {
|
||||
"provider": "${keycloak.role.provider:jpa}"
|
||||
},
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
"provider": "${keycloak.client.provider:jpa}"
|
||||
},
|
||||
|
||||
"group": {
|
||||
"provider": "${keycloak.group.provider:jpa}"
|
||||
},
|
||||
|
||||
"role": {
|
||||
"provider": "${keycloak.role.provider:jpa}"
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue