Skip to content

Commit

Permalink
Searching organization members with multiple name as query parameter (#…
Browse files Browse the repository at this point in the history
…208)

* feat: Add function to search for members with multiple user name with comma

* test: Add test for searching members of organization with multiple member names with comma

* refactor add indent

* fix: null to empty array in searchForMembersStream

---------

Co-authored-by: 박시준 <sjpark@logblack.com>
  • Loading branch information
millwheel and millwheel authored Mar 18, 2024
1 parent f8e327e commit f63900a
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,22 @@ public void setAttribute(String name, List<String> values) {
@Override
public Stream<UserModel> searchForMembersStream(
String search, Integer firstResult, Integer maxResults) {
String[] searchTerms = Strings.isNullOrEmpty(search) ? new String[0] : search.split(",");
// TODO this could be optimized for large member lists with a query
return getMembersStream()
.filter(
(m) -> {
if (Strings.isNullOrEmpty(search)) return true;
return (m.getEmail() != null && m.getEmail().toLowerCase().contains(search))
|| (m.getUsername() != null && m.getUsername().toLowerCase().contains(search))
|| (m.getFirstName() != null && m.getFirstName().toLowerCase().contains(search))
|| (m.getLastName() != null && m.getLastName().toLowerCase().contains(search));
for (String searchTerm : searchTerms) {
String term = searchTerm.trim().toLowerCase();
if (term.isEmpty()) continue;
if ((m.getEmail() != null && m.getEmail().toLowerCase().contains(term))
|| (m.getUsername() != null && m.getUsername().toLowerCase().contains(term))
|| (m.getFirstName() != null && m.getFirstName().toLowerCase().contains(term))
|| (m.getLastName() != null && m.getLastName().toLowerCase().contains(term))) {
return true;
}
}
return searchTerms.length == 0;
})
.skip(firstResult)
.limit(maxResults);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,100 @@ void testAddGetDeleteMemberships() throws IOException {
deleteOrganization(id);
}

@Test
void testSearchMembersWithMultipleNameParameter() throws IOException {
OrganizationRepresentation org = createDefaultOrg();
String id = org.getId();

Response response = getRequest(id, "members");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));

// create a user
UserRepresentation user1 = createUser(keycloak, REALM, "johndoe");
UserRepresentation user2 = createUser(keycloak, REALM, "johndow");
UserRepresentation user3 = createUser(keycloak, REALM, "jack");
UserRepresentation user4 = createUser(keycloak, REALM, "jill");

// add membership
response = putRequest("foo", org.getId(), "members", user1.getId());
assertThat(response.getStatusCode(), is(Status.CREATED.getStatusCode()));
response = putRequest("foo", org.getId(), "members", user2.getId());
assertThat(response.getStatusCode(), is(Status.CREATED.getStatusCode()));
response = putRequest("foo", org.getId(), "members", user3.getId());
assertThat(response.getStatusCode(), is(Status.CREATED.getStatusCode()));
response = putRequest("foo", org.getId(), "members", user4.getId());
assertThat(response.getStatusCode(), is(Status.CREATED.getStatusCode()));

response = getRequest(id, "members");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
List<UserRepresentation> members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(5)); // including org admin default

// search members with query parameter
response = getRequest(id, "members?search=john");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(2));
assertThat(members, hasItem(hasProperty("username", is("johndoe"))));
assertThat(members, hasItem(hasProperty("username", is("johndow"))));

response = getRequest(id, "members?search=jack,jill");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(2));
assertThat(members, hasItem(hasProperty("username", is("jack"))));
assertThat(members, hasItem(hasProperty("username", is("jill"))));

response = getRequest(id, "members?search=john, jack, jill");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(4));
assertThat(members, hasItem(hasProperty("username", is("johndoe"))));
assertThat(members, hasItem(hasProperty("username", is("johndow"))));
assertThat(members, hasItem(hasProperty("username", is("jack"))));
assertThat(members, hasItem(hasProperty("username", is("jill"))));

response = getRequest(id, "members?search=,,jack");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(1));
assertThat(members, hasItem(hasProperty("username", is("jack"))));

response = getRequest(id, "members?search=,, ,");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(0));

response = getRequest(id, "members?search= ,, jack , ");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(1));
assertThat(members, hasItem(hasProperty("username", is("jack"))));

response = getRequest(id, "members?search=");
assertThat(response.statusCode(), is(Status.OK.getStatusCode()));
members = objectMapper().readValue(response.getBody().asString(), new TypeReference<>() {});
assertThat(members, notNullValue());
assertThat(members, hasSize(5));


// delete user
deleteUser(keycloak, REALM, user1.getId());
deleteUser(keycloak, REALM, user2.getId());
deleteUser(keycloak, REALM, user3.getId());
deleteUser(keycloak, REALM, user4.getId());

// delete org
deleteOrganization(id);
}

@Test
void testDuplicateRoles() throws IOException {
OrganizationRepresentation org = createDefaultOrg();
Expand Down

0 comments on commit f63900a

Please sign in to comment.