Skip to content

Commit 4ecbcc1

Browse files
authored
Merge pull request #4048 from dBucik/get_groups_by_user_in_vo
feat: 🎸 Filter out embedded groups where user is member + new method groupsManager/getGroupsWhereUserIsActiveMember
2 parents bcf8900 + 1968093 commit 4ecbcc1

File tree

11 files changed

+198
-20
lines changed

11 files changed

+198
-20
lines changed

perun-base/src/main/resources/perun-roles.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,15 @@ perun_policies:
22172217
include_policies:
22182218
- default_policy
22192219

2220+
getGroupsWhereUserIsActiveMember_User_Vo_policy:
2221+
policy_roles:
2222+
- SELF: User
2223+
- PERUNOBSERVER:
2224+
- VOOBSERVER: Vo
2225+
- VOADMIN: Vo
2226+
include_policies:
2227+
- default_policy
2228+
22202229
getRichGroupsAssignedToResourceWithAttributesByNames_Resource_List<String>_policy:
22212230
policy_roles:
22222231
- RESOURCESELFSERVICE: Resource

perun-core/src/main/java/cz/metacentrum/perun/core/api/GroupsManager.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,4 +1513,14 @@ public interface GroupsManager {
15131513
* @throws PrivilegeException if unauthorized
15141514
*/
15151515
List<Group> getAllAllowedGroupsToHierarchicalVo(PerunSession sess, Vo vo, Vo memberVo) throws VoNotExistsException, PrivilegeException;
1516+
1517+
/**
1518+
* Returns groups in which the user is active member. Groups are looked up only for the specified VO
1519+
* @param session session
1520+
* @param user user object
1521+
* @param vo VO object
1522+
* @return List of groups
1523+
*/
1524+
List<Group> getGroupsWhereUserIsActiveMember(PerunSession session, User user, Vo vo) throws VoNotExistsException, UserNotExistsException, PrivilegeException;
1525+
15161526
}

perun-core/src/main/java/cz/metacentrum/perun/core/bl/GroupsManagerBl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,4 +2191,13 @@ public interface GroupsManagerBl {
21912191
*/
21922192
List<Group> getAllAllowedGroupsToHierarchicalVo(PerunSession sess, Vo vo, Vo memberVo);
21932193

2194+
/**
2195+
* Returns groups in which the user is active member. Groups are looked up only for the specified VO.
2196+
*
2197+
* @param sess session
2198+
* @param user user object
2199+
* @param vo VO object
2200+
* @return List of groups
2201+
*/
2202+
List<Group> getGroupsWhereUserIsActiveMember(PerunSession sess, User user, Vo vo);
21942203
}

perun-core/src/main/java/cz/metacentrum/perun/core/blImpl/GroupsManagerBlImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6084,4 +6084,11 @@ public List<Group> getAllAllowedGroupsToHierarchicalVo(PerunSession sess, Vo vo)
60846084
public List<Group> getAllAllowedGroupsToHierarchicalVo(PerunSession sess, Vo vo, Vo memberVo) {
60856085
return this.groupsManagerImpl.getAllAllowedGroupsToHierarchicalVo(sess, vo, memberVo);
60866086
}
6087+
6088+
@Override
6089+
public List<Group> getGroupsWhereUserIsActiveMember(PerunSession sess, User user, Vo vo) {
6090+
List<Group> groups = this.groupsManagerImpl.getGroupsWhereUserIsActiveMember(sess, user, vo);
6091+
groups.removeIf(g -> VosManager.MEMBERS_GROUP.equals(g.getName()));
6092+
return groups;
6093+
}
60876094
}

perun-core/src/main/java/cz/metacentrum/perun/core/entry/GroupsManagerEntry.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,4 +1746,18 @@ public List<Group> getAllAllowedGroupsToHierarchicalVo(PerunSession sess, Vo vo,
17461746

17471747
return getGroupsManagerBl().getAllAllowedGroupsToHierarchicalVo(sess, vo, memberVo);
17481748
}
1749+
1750+
@Override
1751+
public List<Group> getGroupsWhereUserIsActiveMember(PerunSession sess, User user, Vo vo)
1752+
throws VoNotExistsException, UserNotExistsException, PrivilegeException {
1753+
Utils.checkPerunSession(sess);
1754+
getPerunBl().getVosManagerBl().checkVoExists(sess, vo);
1755+
getPerunBl().getUsersManagerBl().checkUserExists(sess, user);
1756+
1757+
if (!AuthzResolver.authorizedInternal(sess, "getGroupsWhereUserIsActiveMember_User_Vo_policy", user, vo)) {
1758+
throw new PrivilegeException(sess, "getGroupsWhereUserIsActiveMember");
1759+
}
1760+
1761+
return getGroupsManagerBl().getGroupsWhereUserIsActiveMember(sess, user, vo);
1762+
}
17491763
}

perun-core/src/main/java/cz/metacentrum/perun/core/impl/GroupsManagerImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,18 @@ public List<Group> getAllAllowedGroupsToHierarchicalVo(PerunSession sess, Vo vo,
14691469
}
14701470
}
14711471

1472+
@Override
1473+
public List<Group> getGroupsWhereUserIsActiveMember(PerunSession sess, User user, Vo vo) {
1474+
try {
1475+
return jdbc.query("SELECT " + groupMappingSelectQuery + " FROM groups WHERE groups.vo_id=? AND groups.id IN " +
1476+
"(SELECT groups_members.group_id FROM groups_members WHERE groups_members.source_group_status = ? AND groups_members.member_id IN " +
1477+
"(SELECT members.id FROM members WHERE members.user_id = ? AND members.vo_id = ?))",
1478+
GROUP_MAPPER, vo.getId(), MemberGroupStatus.VALID.getCode(), user.getId(), vo.getId());
1479+
} catch (RuntimeException e) {
1480+
throw new InternalErrorException(e);
1481+
}
1482+
}
1483+
14721484
private String getSQLWhereForGroupsPage(GroupsPageQuery query, MapSqlParameterSource namedParams) {
14731485
if (isEmpty(query.getSearchString())) {
14741486
return "";

perun-core/src/main/java/cz/metacentrum/perun/core/implApi/GroupsManagerImplApi.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,4 +1025,15 @@ public interface GroupsManagerImplApi {
10251025
* @return list of allowed groups to hierarchical VO
10261026
*/
10271027
List<Group> getAllAllowedGroupsToHierarchicalVo(PerunSession sess, Vo vo, Vo memberVo);
1028+
1029+
1030+
/**
1031+
* Returns groups in which the user is active member. Groups are looked up only for the specified VO.
1032+
*
1033+
* @param sess session
1034+
* @param user user object
1035+
* @param vo VO object
1036+
* @return List of groups
1037+
*/
1038+
List<Group> getGroupsWhereUserIsActiveMember(PerunSession sess, User user, Vo vo);
10281039
}

perun-core/src/test/java/cz/metacentrum/perun/core/entry/GroupsManagerEntryIntegrationTest.java

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import cz.metacentrum.perun.core.api.MembershipType;
1919
import cz.metacentrum.perun.core.api.Paginated;
2020
import cz.metacentrum.perun.core.api.PerunClient;
21-
import cz.metacentrum.perun.core.api.PerunSession;
2221
import cz.metacentrum.perun.core.api.PerunPrincipal;
22+
import cz.metacentrum.perun.core.api.PerunSession;
2323
import cz.metacentrum.perun.core.api.Resource;
2424
import cz.metacentrum.perun.core.api.RichGroup;
2525
import cz.metacentrum.perun.core.api.RichMember;
@@ -35,7 +35,6 @@
3535
import cz.metacentrum.perun.core.api.exceptions.ExternallyManagedException;
3636
import cz.metacentrum.perun.core.api.exceptions.GroupExistsException;
3737
import cz.metacentrum.perun.core.api.exceptions.GroupMoveNotAllowedException;
38-
import cz.metacentrum.perun.core.api.exceptions.GroupNotAllowedToAutoRegistrationException;
3938
import cz.metacentrum.perun.core.api.exceptions.GroupNotExistsException;
4039
import cz.metacentrum.perun.core.api.exceptions.GroupRelationAlreadyExists;
4140
import cz.metacentrum.perun.core.api.exceptions.GroupRelationCannotBeRemoved;
@@ -54,12 +53,9 @@
5453
import cz.metacentrum.perun.core.bl.UsersManagerBl;
5554
import cz.metacentrum.perun.core.impl.PerunSessionImpl;
5655
import cz.metacentrum.perun.core.implApi.modules.attributes.AbstractMembershipExpirationRulesModule;
57-
import cz.metacentrum.perun.registrar.model.ApplicationFormItem;
5856
import org.junit.Before;
5957
import org.junit.Test;
60-
import org.mockito.Mockito;
6158
import org.springframework.util.Assert;
62-
import org.testcontainers.shaded.com.fasterxml.jackson.databind.annotation.JsonAppend;
6359

6460
import java.time.LocalDate;
6561
import java.util.ArrayList;
@@ -80,7 +76,6 @@
8076
import static org.junit.Assert.assertEquals;
8177
import static org.junit.Assert.assertFalse;
8278
import static org.junit.Assert.assertNotNull;
83-
import static org.junit.Assert.assertNull;
8479
import static org.junit.Assert.assertSame;
8580
import static org.junit.Assert.assertTrue;
8681

@@ -6534,6 +6529,63 @@ public void getAllAllowedGroupsToHierarchicalVoWithMemberVo() throws Exception {
65346529
assertEquals(group2, result.get(0));
65356530
}
65366531

6532+
@Test
6533+
public void getGroupsWhereUserIsActiveMember() throws Exception {
6534+
System.out.println(CLASS_NAME + "getGroupsWhereUserIsActiveMember");
6535+
6536+
Vo vo = setUpVo();
6537+
Member member = setUpMember(vo);
6538+
User user = perun.getUsersManagerBl().getUserById(sess, member.getUserId());
6539+
6540+
groupsManager.createGroup(sess, vo, group);
6541+
groupsManager.createGroup(sess, vo, group2);
6542+
groupsManager.createGroup(sess, group2, group3);
6543+
groupsManager.createGroup(sess, group2, group4);
6544+
groupsManager.createGroup(sess, group3, group5);
6545+
groupsManager.createGroup(sess, group4, group6);
6546+
6547+
groupsManagerBl.addMember(sess, group, member);
6548+
groupsManagerBl.addMember(sess, group2, member);
6549+
groupsManagerBl.addMember(sess, group6, member);
6550+
6551+
List<Group> result = groupsManager.getGroupsWhereUserIsActiveMember(sess, user, vo);
6552+
6553+
assertEquals(4, result.size());
6554+
assertTrue(result.contains(group));
6555+
assertTrue(result.contains(group2));
6556+
assertTrue(result.contains(group4)); //indirect member
6557+
assertTrue(result.contains(group6));
6558+
}
6559+
6560+
@Test
6561+
public void getGroupsWhereUserIsActiveMemberInactiveInGroup() throws Exception {
6562+
System.out.println(CLASS_NAME + "getGroupsWhereUserIsActiveMemberInactiveInGroup");
6563+
6564+
Vo vo = setUpVo();
6565+
Member member = setUpMember(vo);
6566+
User user = perun.getUsersManagerBl().getUserById(sess, member.getUserId());
6567+
6568+
groupsManager.createGroup(sess, vo, group);
6569+
groupsManager.createGroup(sess, vo, group2);
6570+
groupsManager.createGroup(sess, group2, group3);
6571+
groupsManager.createGroup(sess, group2, group4);
6572+
groupsManager.createGroup(sess, group3, group5);
6573+
groupsManager.createGroup(sess, group4, group6);
6574+
6575+
groupsManagerBl.addMember(sess, group, member);
6576+
groupsManagerBl.addMember(sess, group2, member);
6577+
groupsManagerBl.addMember(sess, group6, member);
6578+
groupsManager.setMemberGroupStatus(sess, member, group6, MemberGroupStatus.EXPIRED);
6579+
6580+
List<Group> result = groupsManager.getGroupsWhereUserIsActiveMember(sess, user, vo);
6581+
6582+
assertEquals(2, result.size());
6583+
assertTrue(result.contains(group));
6584+
assertTrue(result.contains(group2));
6585+
assertFalse(result.contains(group4)); //indirect member expired
6586+
assertFalse(result.contains(group6)); //expired member
6587+
}
6588+
65376589
// PRIVATE METHODS -------------------------------------------------------------
65386590

65396591
private Vo setUpVo() throws Exception {

perun-openapi/openapi.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13888,7 +13888,6 @@ paths:
1388813888
$ref: '#/components/responses/ListOfGroupsResponse'
1388913889
default:
1389013890
$ref: '#/components/responses/ExceptionResponse'
13891-
1389213891
/json/groupsManager/getGroupsWhereMemberIsActive:
1389313892
get:
1389413893
tags:
@@ -13902,6 +13901,20 @@ paths:
1390213901
$ref: '#/components/responses/ListOfGroupsResponse'
1390313902
default:
1390413903
$ref: '#/components/responses/ExceptionResponse'
13904+
/json/groupsManager/getGroupsWhereUserIsActiveMember:
13905+
get:
13906+
tags:
13907+
- GroupsManager
13908+
operationId: getGroupsWhereUserIsActiveMember
13909+
summary: Returns list of groups where user is member in active state. Groups are looked up only for the specfied VO.
13910+
parameters:
13911+
- $ref: '#/components/parameters/userId'
13912+
- $ref: '#/components/parameters/voId'
13913+
responses:
13914+
'200':
13915+
$ref: '#/components/responses/ListOfGroupsResponse'
13916+
default:
13917+
$ref: '#/components/responses/ExceptionResponse'
1390513918

1390613919
#################################################
1390713920
# #

perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,13 +2997,24 @@ public List<ApplicationFormItemWithPrefilledValue> getFormItemsWithPrefilledValu
29972997
throw new MissingRequiredDataException("The administrator set up this form wrongly OR you don't match any conditions OR your IDP doesn't provide data required by this application form.", itemsWithMissingData);
29982998
}
29992999

3000-
itemsWithValues.stream()
3001-
.filter(item -> item.getFormItem().getType() == EMBEDDED_GROUP_APPLICATION)
3002-
.forEach(item -> setGroupsToCheckBoxForGroups(sess, item, vo, group));
3000+
Iterator<ApplicationFormItemWithPrefilledValue> itemsIt = itemsWithValues.iterator();
3001+
while (itemsIt.hasNext()) {
3002+
ApplicationFormItemWithPrefilledValue item = itemsIt.next();
3003+
// Process only EMBEDDED_GROUP_APPLICATION items in this block
3004+
if (item.getFormItem().getType() != EMBEDDED_GROUP_APPLICATION) {
3005+
continue;
3006+
}
3007+
// Generate options for EMBEDDED_GROUP_APPLICATION items.
3008+
setGroupsToCheckBoxForGroups(sess, item, user, vo, group);
3009+
// If the item has no options for the user to offer (bcs user is already member in all possible options,
3010+
// remove it from the form completely
3011+
if (StringUtils.isBlank(item.getFormItem().getI18n().get(ApplicationFormItem.EN).getOptions())) {
3012+
it.remove();
3013+
}
3014+
}
30033015

30043016
// return prefilled form
30053017
return itemsWithValues;
3006-
30073018
}
30083019

30093020
private List<Pair<String, String>> getPrincipalsReservedLogins(PerunSession sess) {
@@ -3022,16 +3033,16 @@ private List<Pair<String, String>> getPrincipalsReservedLogins(PerunSession sess
30223033

30233034
/**
30243035
* To the given EMBEDDED_GROUP_APPLICATION item, sets options of allowed groups.
3025-
*
30263036
* Example format:
30273037
* 111#GroupA|222#GroupB
30283038
*
3029-
* @param sess session
3030-
* @param item item, to which the group options will be set, only EMBEDDED_GROUP_APPLICATION is supported
3031-
* @param vo vo, from which the groups for auto registration are taken
3039+
* @param sess session
3040+
* @param item item, to which the group options will be set, only EMBEDDED_GROUP_APPLICATION is supported
3041+
* @param user
3042+
* @param vo vo, from which the groups for auto registration are taken
30323043
* @param registrationGroup group, from which the subgroups for auto registration are taken - if not null, then it is a group application
30333044
*/
3034-
private void setGroupsToCheckBoxForGroups(PerunSession sess, ApplicationFormItemWithPrefilledValue item, Vo vo, Group registrationGroup) {
3045+
private void setGroupsToCheckBoxForGroups(PerunSession sess, ApplicationFormItemWithPrefilledValue item, User user, Vo vo, Group registrationGroup) {
30353046
if (item.getFormItem().getType() != EMBEDDED_GROUP_APPLICATION) {
30363047
throw new InternalErrorException("Group options can be set only to the EMBEDDED_GROUP_APPLICATION item.");
30373048
}
@@ -3042,10 +3053,18 @@ private void setGroupsToCheckBoxForGroups(PerunSession sess, ApplicationFormItem
30423053
groups = perun.getGroupsManagerBl().getGroupsForAutoRegistration(sess, vo, item.getFormItem());
30433054
}
30443055

3045-
String groupOptions = groups.stream()
3046-
.sorted(Comparator.comparing(Group::getName))
3047-
.map(group -> group.getId() + "#" + group.getName())
3048-
.collect(Collectors.joining("|"));
3056+
if (user != null) {
3057+
List<Group> userGroups = groupsManager.getGroupsWhereUserIsActiveMember(sess, user, vo);
3058+
groups = groups.stream().filter(g -> !userGroups.contains(g)).collect(Collectors.toList());
3059+
}
3060+
3061+
String groupOptions = null;
3062+
if (!groups.isEmpty()) {
3063+
groupOptions = groups.stream()
3064+
.sorted(Comparator.comparing(Group::getName))
3065+
.map(group -> group.getId() + "#" + group.getName())
3066+
.collect(Collectors.joining("|"));
3067+
}
30493068

30503069
if (ApplicationFormItem.CS != null) {
30513070
item.getFormItem().getI18n().get(ApplicationFormItem.CS).setOptions(groupOptions);

0 commit comments

Comments
 (0)