From 7f1cf4c531fe5b7dd5069bcb4645f35dbc8662f4 Mon Sep 17 00:00:00 2001 From: Dominik Frantisek Bucik <bucik@ics.muni.cz> Date: Wed, 15 May 2024 15:25:51 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20filtering=20of=20assigne?= =?UTF-8?q?d=20resource=20groups=20in=20entitlements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Entitlements claim sources now support specifying a resource attribute, which if set and non-null on Resource object, groups from this resource will not be considered for producing group-based entitlements. --- .../server/adapters/PerunAdapterMethods.java | 11 ++- .../adapters/impl/PerunAdapterImpl.java | 11 ++- .../adapters/impl/PerunAdapterLdap.java | 84 +++++++++++++++++-- .../server/adapters/impl/PerunAdapterRpc.java | 77 +++++++++++++++-- .../ics/oidc/server/claims/ClaimUtils.java | 10 ++- .../EntitlementExtendedClaimSource.java | 3 +- .../claims/sources/EntitlementSource.java | 13 ++- .../claims/sources/GroupNamesSource.java | 2 +- ...AssignedActiveMemberGroupsClaimSource.java | 2 +- 9 files changed, 182 insertions(+), 31 deletions(-) diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java index d823ea008..d2a7cf172 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/PerunAdapterMethods.java @@ -156,11 +156,16 @@ public interface PerunAdapterMethods { /** * Get groups where user is active (also in VO in which group exists) and are assigned to the resources of facility. * Fill the uniqueGroupName for groups as well. - * @param facilityId Id of Facility - * @param userId Id of User + * + * @param facilityId Id of Facility + * @param userId Id of User + * @param resourceGroupEntitlementDisabledAttribute Attribute to check if groups assigned to resource should be + * considered. Pass null to ignore the setting. * @return Set of groups (filled or empty) */ - Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, Long userId); + Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, + Long userId, + String resourceGroupEntitlementDisabledAttribute); /** * Fetch VO attribute values diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java index 33ecd0a2b..36b09cd6d 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterImpl.java @@ -334,12 +334,17 @@ public class PerunAdapterImpl extends PerunAdapter { } @Override - public Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, Long userId) { + public Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, + Long userId, + String resourceGroupEntitlementDisabledAttribute) + { try { - return this.getAdapterPrimary().getGroupsWhereUserIsActiveWithUniqueNames(facilityId, userId); + return this.getAdapterPrimary().getGroupsWhereUserIsActiveWithUniqueNames( + facilityId, userId, resourceGroupEntitlementDisabledAttribute); } catch (UnsupportedOperationException e) { if (this.isCallFallback()) { - return this.getAdapterFallback().getGroupsWhereUserIsActiveWithUniqueNames(facilityId, userId); + return this.getAdapterFallback().getGroupsWhereUserIsActiveWithUniqueNames( + facilityId, userId, resourceGroupEntitlementDisabledAttribute); } else { throw e; } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java index ba6b673e1..e38c288ac 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterLdap.java @@ -143,7 +143,7 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements @Override public boolean canUserAccessBasedOnMembership(Facility facility, Long userId) { - Set<Long> groupsWithAccessIds = getGroupIdsWithAccessToFacility(facility.getId()); + Set<Long> groupsWithAccessIds = getGroupIdsAssignedToFacility(facility.getId(), null); if (groupsWithAccessIds == null || groupsWithAccessIds.isEmpty()) { return false; } @@ -212,7 +212,7 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements public List<String> getGroupsAssignedToResourcesWithUniqueNames(Facility facility) { List<String> res = new ArrayList<>(); - Set<Long> groupIds = getGroupIdsWithAccessToFacility(facility.getId()); + Set<Long> groupIds = getGroupIdsAssignedToFacility(facility.getId(), null); if (groupIds == null || groupIds.isEmpty()) { return res; } @@ -415,9 +415,13 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements } @Override - public Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, Long userId) { - Set<Long> userGroups = this.getGroupIdsWhereUserIsMember(userId, null); - Set<Long> facilityGroups = this.getGroupIdsWithAccessToFacility(facilityId); + public Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, + Long userId, + String resourceGroupEntitlementDisabledAttribute) + { + Set<Long> userGroups = getGroupIdsWhereUserIsMember(userId, null); + Set<Long> facilityGroups = getGroupIdsAssignedToFacility( + facilityId, resourceGroupEntitlementDisabledAttribute); Set<Long> groupIds = userGroups.stream() .filter(facilityGroups::contains) .collect(Collectors.toSet()); @@ -659,15 +663,50 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements return PERUN_USER_ID + '=' + userId + ',' + OU_PEOPLE; } - private Set<Long> getGroupIdsWithAccessToFacility(Long facilityId) { + private Set<Long> getGroupIdsAssignedToFacility(Long facilityId, String ignoreGroupsAttribute) { + String ldapResourceGroupEntitlementDisabledAttrName = null; + if (ignoreGroupsAttribute != null) { + AttributeMapping mapping = getMappingForAttrName(PerunEntityType.RESOURCE, ignoreGroupsAttribute); + if (mapping == null) { + log.warn("No Attribute mapping found for '{}'", ignoreGroupsAttribute); + } else { + ldapResourceGroupEntitlementDisabledAttrName = mapping.getLdapName(); + } + } + + final String ignoreResourceAttr = ldapResourceGroupEntitlementDisabledAttrName; + FilterBuilder filter = and(equal(OBJECT_CLASS, PERUN_RESOURCE), equal(PERUN_FACILITY_ID, String.valueOf(facilityId))); - String[] attributes = new String[] { ASSIGNED_GROUP_ID }; + Set<String> attributesToFetch = new HashSet<>(); + attributesToFetch.add(ASSIGNED_GROUP_ID); + + final String[] mandatoryAttributes = attributesToFetch.toArray(new String[] {}); + if (StringUtils.hasText(ignoreResourceAttr)) { + attributesToFetch.add(ignoreResourceAttr); + } + + final String[] attributes = attributesToFetch.toArray(new String[] {}); + EntryMapper<Set<Long>> mapper = e -> { Set<Long> ids = new HashSet<>(); - if (checkHasAttributes(e, attributes)) { + if (checkHasAttributes(e, mandatoryAttributes)) { + boolean ignore = false; + if (StringUtils.hasText(ignoreResourceAttr)) { + Attribute ignoreAttr = e.get(ignoreResourceAttr); + if (ignoreAttr != null && "true".equalsIgnoreCase(ignoreAttr.getString())) { + ignore = true; + } + } Attribute a = e.get(ASSIGNED_GROUP_ID); if (a != null) { - a.iterator().forEachRemaining(id -> ids.add(Long.valueOf(id.getString()))); + final Set<Long> groupIds = new HashSet<>(); + a.iterator().forEachRemaining(id -> groupIds.add(Long.valueOf(id.getString()))); + if (!ignore) { + log.debug("Including groups '{}' due to '{}' not set on a resource", groupIds, ignoreGroupsAttribute); + ids.addAll(groupIds); + } else { + log.debug("Ignoring groups '{}' due to '{}' set on a resource", groupIds, ignoreGroupsAttribute); + } } } @@ -844,6 +883,33 @@ public class PerunAdapterLdap extends PerunAdapterWithMappingServices implements return mappings; } + private AttributeMapping getMappingForAttrName(PerunEntityType entity, String attrToFetch) { + AttributeMapping mapping; + switch (entity) { + case USER: + mapping = getUserAttributesMappingService().getMappingByIdentifier(attrToFetch); + break; + case FACILITY: + mapping = getFacilityAttributesMappingService().getMappingByIdentifier(attrToFetch); + break; + case VO: + mapping = getVoAttributesMappingService().getMappingByIdentifier(attrToFetch); + break; + case GROUP: + mapping = getGroupAttributesMappingService().getMappingByIdentifier(attrToFetch); + break; + case RESOURCE: + mapping = getResourceAttributesMappingService().getMappingByIdentifier(attrToFetch); + break; + default: + log.error("Unknown ENTITY {}", entity); + mapping = null; + break; + } + + return mapping; + } + private String[] getAttributesFromMappings(Set<AttributeMapping> mappings) { return mappings.stream() .map(AttributeMapping::getLdapName) diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java index 68be610d7..66db96adb 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/adapters/impl/PerunAdapterRpc.java @@ -137,7 +137,7 @@ public class PerunAdapterRpc extends PerunAdapterWithMappingServices implements return true; } - List<Group> activeGroups = getGroupsWhereUserIsActive(facility, userId); + List<Group> activeGroups = getGroupsWhereUserIsActiveByFacility(facility.getId(), userId); return !activeGroups.isEmpty(); } @@ -811,12 +811,15 @@ public class PerunAdapterRpc extends PerunAdapterWithMappingServices implements } @Override - public Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, Long userId) { + public Set<Group> getGroupsWhereUserIsActiveWithUniqueNames(Long facilityId, + Long userId, + String resourceGroupEntitlementDisabledAttribute) + { if (!this.connectorRpc.isEnabled()) { return new HashSet<>(); } - Set<Group> groups = this.getGroupsWhereUserIsActive(facilityId, userId); + Set<Group> groups = this.getGroupsWhereUserIsActive(facilityId, userId, resourceGroupEntitlementDisabledAttribute); Map<Long, String> voIdToShortNameMap = new HashMap<>(); groups.forEach(g -> { @@ -980,19 +983,71 @@ public class PerunAdapterRpc extends PerunAdapterWithMappingServices implements return RpcMapper.mapMember(jsonNode); } - private Set<Group> getGroupsWhereUserIsActive(Long facilityId, Long userId) { + private Set<Group> getGroupsWhereUserIsActive(Long facilityId, Long userId, String ignoreGroupsAttribute) { + if (!this.connectorRpc.isEnabled()) { + return new HashSet<>(); + } + + Set<Group> groups = new HashSet<>(); + if (StringUtils.hasText(ignoreGroupsAttribute)) { + Set<Resource> resources = getResourcesAssignedToFacility(facilityId, userId, ignoreGroupsAttribute); + for (Resource resource : resources) { + groups.addAll( + getGroupsWhereUserIsActiveByResource(resource.getId(), userId) + ); + } + } else { + groups.addAll(getGroupsWhereUserIsActiveByFacility(facilityId, userId)); + } + return groups; + } + + private Set<Resource> getResourcesAssignedToFacility(Long facilityId, Long userId, String ignoreAttribute) { + if (!this.connectorRpc.isEnabled()) { + return new HashSet<>(); + } + Set<Resource> resources = getAllowedResources(facilityId, userId); + Set<Resource> result = new HashSet<>(); + for (Resource resource : resources) { + PerunAttributeValue attrValue = getResourceAttributeValue(resource.getId(), ignoreAttribute); + if (attrValue == null || attrValue.isNullValue()) { + result.add(resource); + } else { + log.debug( + "getResourcesAssignedToFacility - non null attr value for '{}', skipping resource '{}'", + ignoreAttribute, resource + ); + } + } + return result; + } + + private Set<Group> getGroupsWhereUserIsActiveByResource(Long resourceId, Long userId) { if (!this.connectorRpc.isEnabled()) { return new HashSet<>(); } Map<String, Object> map = new LinkedHashMap<>(); - map.put("facility", facilityId); map.put("user", userId); - JsonNode res = connectorRpc.post(USERS_MANAGER, "getGroupsWhereUserIsActive", map); + map.put("resource", resourceId); + JsonNode res = connectorRpc.post(USERS_MANAGER, "getGroupsWhereUserIsActive", map); return new HashSet<>(RpcMapper.mapGroups(res)); } + private Set<Resource> getAllowedResources(Long facilityId, Long userId) { + if (!this.connectorRpc.isEnabled()) { + return new HashSet<>(); + } + + Map<String, Object> map = new LinkedHashMap<>(); + map.put("user", userId); + map.put("facility", facilityId); + + JsonNode res = connectorRpc.post(USERS_MANAGER, "getAllowedResources", map); + return new HashSet<>(RpcMapper.mapResources(res)); + } + private Vo getVoById(Long voId) { if (!this.connectorRpc.isEnabled()) { return null; @@ -1196,13 +1251,13 @@ public class PerunAdapterRpc extends PerunAdapterWithMappingServices implements return true; } - private List<Group> getGroupsWhereUserIsActive(Facility facility, Long userId) { + private List<Group> getGroupsWhereUserIsActiveByFacility(Long facilityId, Long userId) { if (!this.connectorRpc.isEnabled()) { return new ArrayList<>(); } Map<String, Object> map = new LinkedHashMap<>(); - map.put("facility", facility.getId()); + map.put("facility", facilityId); map.put("user", userId); JsonNode jsonNode = connectorRpc.post(USERS_MANAGER, "getGroupsWhereUserIsActive", map); @@ -1223,12 +1278,16 @@ public class PerunAdapterRpc extends PerunAdapterWithMappingServices implements } private List<Resource> getAssignedResources(Facility facility) { + return getAssignedResources(facility.getId()); + } + + private List<Resource> getAssignedResources(Long facilityId) { if (!this.connectorRpc.isEnabled()) { return new ArrayList<>(); } Map<String, Object> map = new LinkedHashMap<>(); - map.put("facility", facility.getId()); + map.put("facility", facilityId); JsonNode res = connectorRpc.post(FACILITIES_MANAGER, "getAssignedResources", map); return RpcMapper.mapResources(res); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java index 2c64a15bb..a9d0a06df 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/ClaimUtils.java @@ -96,14 +96,18 @@ public class ClaimUtils { return res; } - public static Set<Group> getUserGroupsOnFacility(Facility facility, Long userId, - PerunAdapter perunAdapter, String claimName) + public static Set<Group> getUserGroupsOnFacility(Facility facility, + Long userId, + PerunAdapter perunAdapter, + String resourceGroupEntitlementDisabledAttribute, + String claimName) { Set<Group> userGroups = new HashSet<>(); if (facility == null) { log.warn("{} - no facility provided when searching for user groups, will return empty set", claimName); } else { - userGroups = perunAdapter.getGroupsWhereUserIsActiveWithUniqueNames(facility.getId(), userId); + userGroups = perunAdapter.getGroupsWhereUserIsActiveWithUniqueNames( + facility.getId(), userId, resourceGroupEntitlementDisabledAttribute); } log.trace("{} - found user groups: '{}'", claimName, userGroups); return userGroups; diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java index 3e6810da4..45b12129f 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementExtendedClaimSource.java @@ -45,7 +45,8 @@ public class EntitlementExtendedClaimSource extends EntitlementSource { } private Set<String> produceEntitlementsExtended(Facility facility, Long userId, PerunAdapter perunAdapter) { - Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName()); + Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility( + facility, userId, perunAdapter, getClaimName(), getGroupEntitlementDisabledAttr()); Map<Long, String> groupIdToNameMap = super.getGroupIdToNameMap(userGroups, false); Set<String> entitlements = new TreeSet<>(); this.fillUuidEntitlements(userGroups, entitlements); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java index bc7868dec..25582f0a5 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/EntitlementSource.java @@ -9,6 +9,7 @@ import cz.muni.ics.oidc.server.adapters.PerunAdapter; import cz.muni.ics.oidc.server.claims.ClaimSourceInitContext; import cz.muni.ics.oidc.server.claims.ClaimSourceProduceContext; import cz.muni.ics.oidc.server.claims.ClaimUtils; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; @@ -30,6 +31,10 @@ import java.util.TreeSet; * </li> * <li><b>custom.claim.[claimName].source.resourceCapabilities</b> - resource capabilities attribute name for resources</li> * <li><b>custom.claim.[claimName].source.facilityCapabilities</b> - resource capabilities attribute name for facility</li> + * <li> + * <b>custom.claim.[claimName].source.groupEntitlementDisabledAttribute</b> - resource attribute which triggers + * if resource assigned groups should not be used for generating group entitlements. + * When not specified, all groups will be used</li> * <li><b>custom.claim.[claimName].source.prefix</b> - string to be prepended to the value,</li> * <li> * <b>custom.claim.[claimName].source.authority</b> - string to be appended to the value, represents authority @@ -48,12 +53,17 @@ public class EntitlementSource extends GroupNamesSource { protected static final String FORWARDED_ENTITLEMENTS = "forwardedEntitlements"; protected static final String RESOURCE_CAPABILITIES = "resourceCapabilities"; protected static final String FACILITY_CAPABILITIES = "facilityCapabilities"; + + protected static final String GROUP_ENTITLEMENT_DISABLED_ATTR = "groupEntitlementDisabledAttribute"; protected static final String PREFIX = "prefix"; protected static final String AUTHORITY = "authority"; private final String forwardedEntitlements; private final String resourceCapabilities; + private final String facilityCapabilities; + @Getter + private final String groupEntitlementDisabledAttr; private final String prefix; private final String authority; @@ -63,6 +73,7 @@ public class EntitlementSource extends GroupNamesSource { this.forwardedEntitlements = ClaimUtils.fillStringPropertyOrDefaultVal(FORWARDED_ENTITLEMENTS, ctx, null); this.resourceCapabilities = ClaimUtils.fillStringPropertyOrDefaultVal(RESOURCE_CAPABILITIES, ctx, null); this.facilityCapabilities = ClaimUtils.fillStringPropertyOrDefaultVal(FACILITY_CAPABILITIES, ctx, null); + this.groupEntitlementDisabledAttr = ClaimUtils.fillStringPropertyOrDefaultVal(GROUP_ENTITLEMENT_DISABLED_ATTR, ctx, null); this.prefix = ClaimUtils.fillStringMandatoryProperty(PREFIX, ctx, getClaimName()); this.authority = ClaimUtils.fillStringMandatoryProperty(AUTHORITY, ctx, getClaimName()); @@ -86,7 +97,7 @@ public class EntitlementSource extends GroupNamesSource { PerunAdapter perunAdapter = pctx.getPerunAdapter(); Long userId = pctx.getPerunUserId(); Facility facility = pctx.getFacility(); - Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName()); + Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, groupEntitlementDisabledAttr, getClaimName()); Set<String> entitlements = produceEntitlements(facility, userGroups, userId, perunAdapter); JsonNode result = ClaimUtils.convertResultStringsToJsonArray(entitlements); diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java index cfdaba451..fa5db66a4 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/GroupNamesSource.java @@ -49,7 +49,7 @@ public class GroupNamesSource extends ClaimSource { log.trace("{} - produce group names with trimming 'members' part of the group names", getClaimName()); Facility facility = pctx.getFacility(); Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, pctx.getPerunUserId(), - pctx.getPerunAdapter(), getClaimName()); + pctx.getPerunAdapter(), getClaimName(), null); return getGroupIdToNameMap(userGroups, true); } diff --git a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/ResourceAssignedActiveMemberGroupsClaimSource.java b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/ResourceAssignedActiveMemberGroupsClaimSource.java index db95b3a1d..5e384f264 100644 --- a/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/ResourceAssignedActiveMemberGroupsClaimSource.java +++ b/perun-oidc-server/src/main/java/cz/muni/ics/oidc/server/claims/sources/ResourceAssignedActiveMemberGroupsClaimSource.java @@ -58,7 +58,7 @@ public class ResourceAssignedActiveMemberGroupsClaimSource extends ClaimSource { Long userId = pctx.getPerunUserId(); Facility facility = pctx.getFacility(); PerunAdapter perunAdapter = pctx.getPerunAdapter(); - Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName()); + Set<Group> userGroups = ClaimUtils.getUserGroupsOnFacility(facility, userId, perunAdapter, getClaimName(), null); return getValuesFromAttribute(userGroups, perunAdapter); } -- GitLab