Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 247a899

Browse files
committed
Get users who do not belong to this group among the members of the organization.
Removed "/{orgId}/{searchMemberName}/{searchGroupId}/members" endpoint.
1 parent 524bc75 commit 247a899

File tree

11 files changed

+121
-111
lines changed

11 files changed

+121
-111
lines changed

‎server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/user/repository/UserRepository.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package org.lowcoder.domain.user.repository;
22

33
import java.util.Collection;
4+
import java.util.List;
45

56
import org.lowcoder.domain.user.model.User;
7+
import org.springframework.data.domain.Pageable;
68
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
79
import org.springframework.stereotype.Repository;
810

911
import reactor.core.publisher.Flux;
1012
import reactor.core.publisher.Mono;
13+
import org.springframework.data.mongodb.repository.Query;
1114

1215
@Repository
1316
public interface UserRepository extends ReactiveMongoRepository<User, String> {
@@ -23,4 +26,10 @@ public interface UserRepository extends ReactiveMongoRepository<User, String> {
2326

2427
//email1 and email2 should be equal
2528
Flux<User> findByEmailOrConnections_Email(String email1, String email2);
29+
30+
@Query("{ '_id': { $in: ?0 }, 'state': ?1, 'isEnabled': ?2, $or: [ { 'name': { $regex: ?3, $options: 'i' } }, { '_id': { $regex: ?3, $options: 'i' } } ] }")
31+
Flux<User> findUsersByIdsAndSearchNameForPagination(Collection<String> ids, String state, boolean isEnabled, String searchRegex, Pageable pageable);
32+
33+
@Query(value = "{ '_id': { $in: ?0 }, 'state': ?1, 'isEnabled': ?2, $or: [ { 'name': { $regex: ?3, $options: 'i' } }, { '_id': { $regex: ?3, $options: 'i' } } ] }", count = true)
34+
Mono<Long> countUsersByIdsAndSearchName(Collection<String> ids, String state, boolean isEnabled, String searchRegex);
2635
}

‎server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/user/service/UserService.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
import java.util.Collection;
44
import java.util.Map;
55

6-
import org.lowcoder.domain.user.model.AuthUser;
7-
import org.lowcoder.domain.user.model.Connection;
8-
import org.lowcoder.domain.user.model.User;
9-
import org.lowcoder.domain.user.model.UserDetail;
6+
import org.lowcoder.domain.user.model.*;
107
import org.lowcoder.infra.annotation.NonEmptyMono;
118
import org.lowcoder.infra.mongo.MongoUpsertHelper.PartialResourceWithId;
9+
import org.springframework.data.domain.Pageable;
1210
import org.springframework.http.codec.multipart.Part;
1311
import org.springframework.web.server.ServerWebExchange;
1412

@@ -68,5 +66,7 @@ public interface UserService {
6866

6967
Flux<User> findBySourceAndIds(String connectionSource, Collection<String> connectionSourceUuids);
7068

71-
}
69+
Flux<User> findUsersByIdsAndSearchNameForPagination(Collection<String> ids, String state, boolean isEnabled, String searchRegex, Pageable pageable);
7270

71+
Mono<Long> countUsersByIdsAndSearchName(Collection<String> ids, String state, boolean isEnabled, String searchRegex);
72+
}

‎server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/user/service/UserServiceImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.lowcoder.sdk.util.HashUtils;
3737
import org.lowcoder.sdk.util.LocaleUtils;
3838
import org.springframework.dao.DuplicateKeyException;
39+
import org.springframework.data.domain.Pageable;
3940
import org.springframework.http.codec.multipart.Part;
4041
import org.springframework.stereotype.Service;
4142
import org.springframework.web.server.ServerWebExchange;
@@ -473,4 +474,13 @@ public Flux<User> findBySourceAndIds(String connectionSource, Collection<String>
473474
return repository.findByConnections_SourceAndConnections_RawIdIn(connectionSource, connectionSourceUuids);
474475
}
475476

477+
@Override
478+
public Flux<User> findUsersByIdsAndSearchNameForPagination(Collection<String> ids, String state, boolean isEnabled, String searchRegex, Pageable pageable) {
479+
return repository.findUsersByIdsAndSearchNameForPagination(ids, state, isEnabled, searchRegex, pageable);
480+
}
481+
482+
@Override
483+
public Mono<Long> countUsersByIdsAndSearchName(Collection<String> ids, String state, boolean isEnabled, String searchRegex) {
484+
return repository.countUsersByIdsAndSearchName(ids, state, isEnabled, searchRegex);
485+
}
476486
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.lowcoder.api.usermanagement;
22

33
import org.lowcoder.api.usermanagement.view.*;
4+
import org.lowcoder.api.usermanagement.view.OrgMemberListView;
45
import org.lowcoder.domain.group.model.Group;
56
import reactor.core.publisher.Mono;
67

@@ -24,4 +25,6 @@ public interface GroupApiService {
2425
Mono<Boolean> update(String groupId, UpdateGroupRequest updateGroupRequest);
2526

2627
Mono<Boolean> removeUser(String groupId, String userId);
28+
29+
Mono<OrgMemberListView> getPotentialGroupMembers(String groupId, String searchName, Integer pageNum, Integer pageSize);
2730
}

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

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,31 @@
99
import static org.lowcoder.sdk.util.StreamUtils.collectList;
1010
import static org.lowcoder.sdk.util.StreamUtils.collectMap;
1111

12-
import java.util.List;
13-
import java.util.Map;
14-
import java.util.Objects;
12+
import java.util.*;
13+
import java.util.regex.Pattern;
1514
import java.util.stream.Collectors;
1615

1716
import com.github.f4b6a3.uuid.UuidCreator;
1817
import lombok.RequiredArgsConstructor;
1918
import org.apache.commons.lang3.tuple.Pair;
2019
import org.lowcoder.api.bizthreshold.AbstractBizThresholdChecker;
2120
import org.lowcoder.api.home.SessionUserService;
22-
import org.lowcoder.api.usermanagement.view.CreateGroupRequest;
23-
import org.lowcoder.api.usermanagement.view.GroupMemberAggregateView;
24-
import org.lowcoder.api.usermanagement.view.GroupMemberView;
25-
import org.lowcoder.api.usermanagement.view.GroupView;
26-
import org.lowcoder.api.usermanagement.view.UpdateGroupRequest;
27-
import org.lowcoder.api.usermanagement.view.UpdateRoleRequest;
21+
import org.lowcoder.api.usermanagement.view.*;
2822
import org.lowcoder.domain.group.model.Group;
2923
import org.lowcoder.domain.group.model.GroupMember;
24+
import org.lowcoder.domain.user.model.UserState;
25+
import org.lowcoder.api.usermanagement.view.OrgMemberListView;
3026
import org.lowcoder.domain.group.service.GroupMemberService;
3127
import org.lowcoder.domain.group.service.GroupService;
3228
import org.lowcoder.domain.organization.model.MemberRole;
3329
import org.lowcoder.domain.organization.model.OrgMember;
3430
import org.lowcoder.domain.organization.service.OrgMemberService;
35-
import org.lowcoder.domain.organization.service.OrganizationService;
3631
import org.lowcoder.domain.user.model.User;
3732
import org.lowcoder.domain.user.service.UserService;
3833
import org.lowcoder.infra.util.TupleUtils;
3934
import org.lowcoder.sdk.exception.BizError;
35+
import org.springframework.data.domain.Pageable;
36+
import org.springframework.data.domain.PageRequest;
4037
import org.springframework.stereotype.Service;
4138

4239
import reactor.core.publisher.Flux;
@@ -53,7 +50,6 @@ public class GroupApiServiceImpl implements GroupApiService {
5350
private final UserService userService;
5451
private final GroupService groupService;
5552
private final AbstractBizThresholdChecker bizThresholdChecker;
56-
private final OrganizationService organizationService;
5753
private final OrgMemberService orgMemberService;
5854

5955
@Override
@@ -311,4 +307,63 @@ public Mono<Boolean> removeUser(String groupId, String userId) {
311307
return groupMemberService.removeMember(groupId, userId);
312308
});
313309
}
310+
311+
@Override
312+
public Mono<OrgMemberListView> getPotentialGroupMembers(String groupId, String searchName, Integer pageNum, Integer pageSize) {
313+
return groupService.getById(groupId)
314+
.flatMap(group -> {
315+
String orgId = group.getOrganizationId();
316+
Mono<List<OrgMember>> orgMemberUserIdsMono = orgMemberService.getOrganizationMembers(orgId).collectList();
317+
Mono<List<GroupMember>> groupMemberUserIdsMono = groupMemberService.getGroupMembers(groupId);
318+
319+
return Mono.zip(orgMemberUserIdsMono, groupMemberUserIdsMono)
320+
.flatMap(tuple -> {
321+
List<OrgMember> orgMembers = tuple.getT1();
322+
List<GroupMember> groupMembers = tuple.getT2();
323+
324+
Set<String> groupMemberUserIds = groupMembers.stream()
325+
.map(GroupMember::getUserId)
326+
.collect(Collectors.toSet());
327+
328+
Collection<String> potentialUserIds = orgMembers.stream()
329+
.map(OrgMember::getUserId)
330+
.filter(uid -> !groupMemberUserIds.contains(uid))
331+
.collect(Collectors.toList());
332+
333+
if (potentialUserIds.isEmpty()) {
334+
return Mono.just(OrgMemberListView.builder()
335+
.members(List.of())
336+
.total(0)
337+
.pageNum(pageNum)
338+
.pageSize(pageSize)
339+
.build());
340+
}
341+
342+
Pageable pageable = PageRequest.of(pageNum - 1, pageSize);
343+
String searchRegex = searchName != null && !searchName.isBlank() ? ".*" + Pattern.quote(searchName) + ".*" : ".*";
344+
345+
return userService.findUsersByIdsAndSearchNameForPagination(
346+
potentialUserIds, String.valueOf(UserState.ACTIVATED), true, searchRegex, pageable)
347+
.collectList()
348+
.zipWith(userService.countUsersByIdsAndSearchName(
349+
potentialUserIds, String.valueOf(UserState.ACTIVATED), true, searchRegex))
350+
.map(tupleUser -> {
351+
List<User> users = tupleUser.getT1();
352+
long total = tupleUser.getT2();
353+
List<OrgMemberListView.OrgMemberView> memberViews = users.stream()
354+
.map(u -> OrgMemberListView.OrgMemberView.builder()
355+
.userId(u.getId())
356+
.name(u.getName())
357+
.build())
358+
.collect(Collectors.toList());
359+
return OrgMemberListView.builder()
360+
.members(memberViews)
361+
.total((int) total)
362+
.pageNum(pageNum)
363+
.pageSize(pageSize)
364+
.build();
365+
});
366+
});
367+
});
368+
}
314369
}

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
import org.lowcoder.domain.organization.service.OrgMemberService;
2121
import org.lowcoder.sdk.exception.BizError;
2222
import org.springframework.beans.factory.annotation.Autowired;
23-
import org.springframework.web.bind.annotation.PathVariable;
24-
import org.springframework.web.bind.annotation.RequestBody;
25-
import org.springframework.web.bind.annotation.RequestParam;
26-
import org.springframework.web.bind.annotation.RestController;
23+
import org.springframework.web.bind.annotation.*;
24+
import org.lowcoder.api.usermanagement.view.OrgMemberListView;
2725

2826
import reactor.core.publisher.Mono;
2927
import reactor.util.function.Tuple2;
@@ -180,4 +178,15 @@ public Mono<ResponseView<Boolean>> removeUser(@PathVariable String groupId,
180178
.map(Tuple2::getT2)
181179
.map(ResponseView::success));
182180
}
181+
182+
@Override
183+
public Mono<ResponseView<OrgMemberListView>> searchPotentialGroupMembers(
184+
@PathVariable String groupId,
185+
@RequestParam(required = false) String searchName,
186+
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
187+
@RequestParam(required = false, defaultValue = "1000") Integer pageSize) {
188+
return gidService.convertGroupIdToObjectId(groupId).flatMap(id ->
189+
groupApiService.getPotentialGroupMembers(id, searchName, pageNum, pageSize)
190+
.map(ResponseView::success));
191+
}
183192
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,19 @@ public Mono<ResponseView<Boolean>> updateRoleForMember(@RequestBody UpdateRoleRe
115115
@DeleteMapping("/{groupId}/remove")
116116
public Mono<ResponseView<Boolean>> removeUser(@PathVariable String groupId,
117117
@RequestParam String userId);
118+
119+
@Operation(
120+
tags = TAG_GROUP_MEMBERS,
121+
operationId = "searchPotentialGroupMembers",
122+
summary = "Search Potential Group Members",
123+
description = "Retrieve a list of users who are not currently members of the specified group within an organization."
124+
)
125+
126+
@GetMapping("/{groupId}/potential-members")
127+
public Mono<ResponseView<OrgMemberListView>> searchPotentialGroupMembers(
128+
@PathVariable String groupId,
129+
@RequestParam(required = false) String searchName,
130+
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
131+
@RequestParam(required = false, defaultValue = "1000") Integer pageSize
132+
);
118133
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,5 @@ public interface OrgApiService {
5353
Mono<ConfigView> getOrganizationConfigs(String orgId);
5454

5555
Mono<Long> getApiUsageCount(String orgId, Boolean lastMonthOnly);
56-
57-
Mono<OrgMemberListView> getOrganizationMembersForSearch(String orgId, String searchMemberName, String searchGroupId, Integer pageNum, Integer pageSize);
5856
}
5957

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

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -90,78 +90,6 @@ public Mono<OrgMemberListView> getOrganizationMembers(String orgId, int page, in
9090
.then(getOrgMemberListView(orgId, page, count));
9191
}
9292

93-
// Update getOrgMemberListViewForSearch to filter by group membership
94-
private Mono<OrgMemberListView> getOrgMemberListViewForSearch(String orgId, String searchMemberName, String searchGroupId, Integer page, Integer pageSize) {
95-
return orgMemberService.getOrganizationMembers(orgId)
96-
.collectList()
97-
.flatMap(orgMembers -> {
98-
List<String> userIds = orgMembers.stream()
99-
.map(OrgMember::getUserId)
100-
.collect(Collectors.toList());
101-
Mono<Map<String, User>> users = userService.getByIds(userIds);
102-
103-
// If searchGroupId is provided, fetch group members
104-
Mono<Set<String>> groupUserIdsMono = StringUtils.isBlank(searchGroupId)
105-
? Mono.just(Collections.emptySet())
106-
: groupMemberService.getGroupMembers(searchGroupId)
107-
.map(list -> list.stream()
108-
.map(GroupMember::getUserId)
109-
.collect(Collectors.toSet()));
110-
111-
return Mono.zip(users, groupUserIdsMono)
112-
.map(tuple -> {
113-
Map<String, User> userMap = tuple.getT1();
114-
Set<String> groupUserIds = tuple.getT2();
115-
116-
var list = orgMembers.stream()
117-
.map(orgMember -> {
118-
User user = userMap.get(orgMember.getUserId());
119-
if (user == null) {
120-
log.warn("user {} not exist and will be removed from the result.", orgMember.getUserId());
121-
return null;
122-
}
123-
return buildOrgMemberView(user, orgMember);
124-
})
125-
.filter(Objects::nonNull)
126-
.filter(orgMemberView -> {
127-
// Filter by name
128-
boolean matchesName = StringUtils.isBlank(searchMemberName) ||
129-
StringUtils.containsIgnoreCase(orgMemberView.getName(), searchMemberName);
130-
131-
// Filter by group
132-
boolean matchesGroup = StringUtils.isBlank(searchGroupId) ||
133-
groupUserIds.contains(orgMemberView.getUserId());
134-
135-
return matchesName && matchesGroup;
136-
})
137-
.collect(Collectors.toList());
138-
var pageTotal = list.size();
139-
list = list.subList((page - 1) * pageSize, pageSize == 0 ? pageTotal : Math.min(page * pageSize, pageTotal));
140-
return Pair.of(list, pageTotal);
141-
});
142-
})
143-
.zipWith(sessionUserService.getVisitorOrgMemberCache())
144-
.map(tuple -> {
145-
List<OrgMemberView> memberViews = tuple.getT1().getLeft();
146-
var pageTotal = tuple.getT1().getRight();
147-
OrgMember orgMember = tuple.getT2();
148-
return OrgMemberListView.builder()
149-
.members(memberViews)
150-
.total(pageTotal)
151-
.pageNum(page)
152-
.pageSize(pageSize)
153-
.visitorRole(orgMember.getRole().getValue())
154-
.build();
155-
});
156-
}
157-
@Override
158-
public Mono<OrgMemberListView> getOrganizationMembersForSearch(String orgId, String searchMemberName, String searchGroupId, Integer page, Integer pageSize) {
159-
return sessionUserService.getVisitorId()
160-
.flatMap(visitorId -> orgMemberService.getOrgMember(orgId, visitorId))
161-
.switchIfEmpty(deferredError(BizError.NOT_AUTHORIZED, "NOT_AUTHORIZED"))
162-
.then(getOrgMemberListViewForSearch(orgId, searchMemberName, searchGroupId, page, pageSize));
163-
}
164-
16593
private Mono<OrgMemberListView> getOrgMemberListView(String orgId, int page, int count) {
16694
return orgMemberService.getOrganizationMembers(orgId)
16795
.collectList()

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,6 @@ public Mono<ResponseView<OrgMemberListView>> getOrgMembers(@PathVariable String
118118
orgApiService.getOrganizationMembers(id, pageNum, pageSize)
119119
.map(ResponseView::success));
120120
}
121-
@Override
122-
public Mono<ResponseView<OrgMemberListView>> getOrgMembersForSearch(@PathVariable String orgId,
123-
@PathVariable String searchMemberName,
124-
@PathVariable String searchGroupId,
125-
@RequestParam(required = false, defaultValue = "1") int pageNum,
126-
@RequestParam(required = false, defaultValue = "1000") int pageSize) {
127-
return gidService.convertOrganizationIdToObjectId(orgId).flatMap(id ->
128-
orgApiService.getOrganizationMembersForSearch(id, searchMemberName, searchGroupId, pageNum, pageSize)
129-
.map(ResponseView::success));
130-
}
131121

132122
@Override
133123
public Mono<ResponseView<Boolean>> updateRoleForMember(@RequestBody UpdateRoleRequest updateRoleRequest,

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,6 @@ public Mono<ResponseView<OrgMemberListView>> getOrgMembers(@PathVariable String
9898
@RequestParam(required = false, defaultValue = "1") int pageNum,
9999
@RequestParam(required = false, defaultValue = "1000") int pageSize);
100100

101-
@GetMapping("/{orgId}/{searchMemberName}/{searchGroupId}/members")
102-
public Mono<ResponseView<OrgMemberListView>> getOrgMembersForSearch(@PathVariable String orgId,
103-
@PathVariable String searchMemberName,
104-
@PathVariable String searchGroupId,
105-
@RequestParam(required = false, defaultValue = "1") int pageNum,
106-
@RequestParam(required = false, defaultValue = "1000") int pageSize);
107-
108101
@Operation(
109102
tags = TAG_ORGANIZATION_MEMBERS,
110103
operationId = "updateOrganizationMemberRole",

0 commit comments

Comments
 (0)