Skip to content

Commit 4278242

Browse files
dragonpooludomikula
authored andcommitted
Fix: group members filtering and sorting
1 parent 1daf513 commit 4278242

File tree

7 files changed

+122
-11
lines changed

7 files changed

+122
-11
lines changed

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/group/service/GroupMemberService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ public interface GroupMemberService {
4141

4242
Mono<Boolean> bulkRemoveMember(String groupId, Collection<String> userIds);
4343

44+
Mono<List<GroupMember>> getGroupMembersByIdAndRole(String groupId, String role);
45+
4446
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/group/service/GroupMemberServiceImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ public Mono<List<GroupMember>> getGroupMembers(String groupId) {
3535
.collectList();
3636
}
3737

38+
@Override
39+
public Mono<List<GroupMember>> getGroupMembersByIdAndRole(String groupId, String role) {
40+
return biRelationService.getBySourceIdAndRelation(GROUP_MEMBER, groupId, role)
41+
.map(GroupMember::from)
42+
.collectList();
43+
}
44+
3845
@Override
3946
public Mono<Boolean> addMember(String orgId, String groupId, String userId, MemberRole memberRole) {
4047
return biRelationService.addBiRelation(GROUP_MEMBER, groupId,

server/api-service/lowcoder-infra/src/main/java/org/lowcoder/infra/birelation/BiRelationServiceImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ public Mono<Boolean> updateState(BiRelationBizType bizType, String sourceId, Str
185185

186186
@Override
187187
public Flux<BiRelation> getBySourceIdAndRelation(BiRelationBizType bizType, String sourceId, String relation) {
188+
if (relation == null || relation.isBlank()) {
189+
return biRelationRepository.findByBizTypeAndSourceId(bizType, sourceId);
190+
}
188191
Query query = new Query();
189192
query.addCriteria(where(BIZ_TYPE).is(bizType));
190193
query.addCriteria(where(SOURCE_ID).is(sourceId));

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/GroupApiService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
public interface GroupApiService {
1111
Mono<GroupMemberAggregateView> getGroupMembers(String groupId, int page, int count);
1212

13+
Mono<GroupMemberAggregateView> getGroupMembersForSearch(String groupId, String search, String role, String sort, String order, Integer pageNum, Integer pageSize);
14+
1315
Mono<Boolean> addGroupMember(String groupId, String newUserId, String roleName);
1416

1517
Mono<Boolean> updateRoleForMember(String groupId, UpdateRoleRequest updateRoleRequest);

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/GroupApiServiceImpl.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,91 @@ public Mono<GroupMemberAggregateView> getGroupMembers(String groupId, int page,
111111
});
112112
}
113113

114+
@Override
115+
public Mono<GroupMemberAggregateView> getGroupMembersForSearch(String groupId, String search, String role, String sort, String order, Integer pageNum, Integer pageSize) {
116+
Mono<Tuple2<GroupMember, OrgMember>> groupAndOrgMemberInfo = getGroupAndOrgMemberInfo(groupId).cache();
117+
118+
Mono<MemberRole> visitorRoleMono = groupAndOrgMemberInfo.flatMap(tuple -> {
119+
GroupMember groupMember = tuple.getT1();
120+
OrgMember orgMember = tuple.getT2();
121+
if (groupMember.isSuperAdmin() || orgMember.isSuperAdmin()) {
122+
return Mono.just(MemberRole.SUPER_ADMIN);
123+
}
124+
if (groupMember.isAdmin() || orgMember.isAdmin()) {
125+
return Mono.just(MemberRole.ADMIN);
126+
}
127+
if (groupMember.isValid()) {
128+
return Mono.just(MemberRole.MEMBER);
129+
}
130+
return ofError(BizError.NOT_AUTHORIZED, NOT_AUTHORIZED);
131+
});
132+
133+
return groupAndOrgMemberInfo
134+
.filter(this::hasReadPermission)
135+
.switchIfEmpty(deferredError(BizError.NOT_AUTHORIZED, NOT_AUTHORIZED))
136+
.flatMap(groupMember -> groupMemberService.getGroupMembersByIdAndRole(groupId, role))
137+
.<Pair<List<GroupMemberView>, Integer>> flatMap(members -> {
138+
if (members.isEmpty()) {
139+
return Mono.just(Pair.of(emptyList(), 0));
140+
}
141+
142+
List<String> userIds = collectList(members, GroupMember::getUserId);
143+
Mono<Map<String, User>> userMapMono = userService.getByIds(userIds);
144+
return userMapMono.map(map -> {
145+
var list = members.stream()
146+
.map(orgMember -> {
147+
User user = map.get(orgMember.getUserId());
148+
if (user == null) {
149+
return null;
150+
}
151+
return new GroupMemberView(orgMember, user);
152+
})
153+
.filter(Objects::nonNull)
154+
.filter(view -> {
155+
if (search == null || search.isBlank()) return true;
156+
return view.getUserName() != null &&
157+
view.getUserName().toLowerCase().contains(search.toLowerCase());
158+
})
159+
.toList();
160+
List<GroupMemberView> mutableList = new ArrayList<>(list);
161+
if (sort != null && !sort.isBlank()) {
162+
Comparator<GroupMemberView> comparator = null;
163+
if ("userName".equalsIgnoreCase(sort)) {
164+
comparator = Comparator.comparing(GroupMemberView::getUserName, Comparator.nullsLast(String::compareToIgnoreCase));
165+
} else if ("role".equalsIgnoreCase(sort)) {
166+
comparator = Comparator.comparing(GroupMemberView::getRole, Comparator.nullsLast(String::compareToIgnoreCase));
167+
} else if ("joinTime".equalsIgnoreCase(sort)) {
168+
comparator = Comparator.comparing(GroupMemberView::getJoinTime, Comparator.nullsLast(Long::compareTo));
169+
}
170+
if (comparator != null && "desc".equalsIgnoreCase(order)) {
171+
comparator = comparator.reversed();
172+
}
173+
if (comparator != null) {
174+
mutableList.sort(comparator);
175+
}
176+
}
177+
178+
int pageTotal = mutableList.size();
179+
int fromIndex = Math.max(0, (pageNum - 1) * pageSize);
180+
int toIndex = pageSize == 0 ? pageTotal : Math.min(pageNum * pageSize, pageTotal);
181+
List<GroupMemberView> pagedList = fromIndex < toIndex ? mutableList.subList(fromIndex, toIndex) : emptyList();
182+
183+
return Pair.of(pagedList, pageTotal);
184+
});
185+
})
186+
.zipWith(visitorRoleMono)
187+
.map(tuple -> {
188+
Pair<List<GroupMemberView>, Integer> t1 = tuple.getT1();
189+
return GroupMemberAggregateView.builder()
190+
.members(t1.getLeft())
191+
.total(t1.getRight())
192+
.pageNum(pageNum)
193+
.pageSize(pageSize)
194+
.visitorRole(tuple.getT2().getValue())
195+
.build();
196+
});
197+
}
198+
114199
private boolean hasReadPermission(Tuple2<GroupMember, OrgMember> tuple) {
115200
GroupMember groupMember = tuple.getT1();
116201
OrgMember orgMember = tuple.getT2();
@@ -366,4 +451,5 @@ public Mono<OrgMemberListView> getPotentialGroupMembers(String groupId, String s
366451
});
367452
});
368453
}
454+
369455
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/GroupController.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,16 @@ public Mono<GroupListResponseView<List<GroupView>>> getOrgGroups(@RequestParam(r
116116

117117

118118
@Override
119-
public Mono<ResponseView<GroupMemberAggregateView>> getGroupMembers(@PathVariable String groupId,
120-
@RequestParam(required = false, defaultValue = "1") int pageNum,
121-
@RequestParam(required = false, defaultValue = "100") int pageSize) {
119+
public Mono<ResponseView<GroupMemberAggregateView>> getGroupMembers(
120+
@PathVariable String groupId,
121+
@RequestParam(required = false) String search,
122+
@RequestParam(required = false) String role,
123+
@RequestParam(required = false) String sort,
124+
@RequestParam(required = false) String order,
125+
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
126+
@RequestParam(required = false, defaultValue = "100") Integer pageSize) {
122127
return gidService.convertGroupIdToObjectId(groupId).flatMap(objectId ->
123-
groupApiService.getGroupMembers(objectId, pageNum, pageSize)
128+
groupApiService.getGroupMembersForSearch(objectId, search, role, sort, order, pageNum, pageSize)
124129
.map(ResponseView::success));
125130
}
126131

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/GroupEndpoints.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,20 @@ public Mono<GroupListResponseView<List<GroupView>>> getOrgGroups(@RequestParam(r
6868

6969
@Operation(
7070
tags = TAG_GROUP_MEMBERS,
71-
operationId = "listGroupMembers",
72-
summary = "List User Group Members",
73-
description = "Retrieve a list of Users / Members within a specific User Group in Lowcoder, showing the group's composition."
71+
operationId = "listGroupMembersWithSearchAndSort",
72+
summary = "List User Group Members with Search and Sort",
73+
description = "Retrieve a paginated, searchable, and sortable list of Users / Members within a specific User Group in Lowcoder."
7474
)
75-
@GetMapping("/{groupId}/members")
76-
public Mono<ResponseView<GroupMemberAggregateView>> getGroupMembers(@PathVariable String groupId,
77-
@RequestParam(required = false, defaultValue = "1") int pageNum,
78-
@RequestParam(required = false, defaultValue = "100") int pageSize);
75+
@GetMapping("/{groupId}/members")
76+
public Mono<ResponseView<GroupMemberAggregateView>> getGroupMembers(
77+
@PathVariable String groupId,
78+
@RequestParam(required = false) String search,
79+
@RequestParam(required = false) String role,
80+
@RequestParam(required = false) String sort,
81+
@RequestParam(required = false) String order,
82+
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
83+
@RequestParam(required = false, defaultValue = "100") Integer pageSize
84+
);
7985

8086
@Operation(
8187
tags = TAG_GROUP_MEMBERS,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy