Skip to content
Snippets Groups Projects
Commit f90c7f47 authored by OZGCloud's avatar OZGCloud
Browse files

Merge pull request 'OZG-3947 Search for Bearbeiter by full name' (#81) from...

Merge pull request 'OZG-3947 Search for Bearbeiter by full name' (#81) from OZG-3947-extend-bearbeiter-search-simple into master

Reviewed-on: https://git.ozg-sh.de/mgm/user-manager/pulls/81
parents d2edd1f5 dc82b2a5
No related branches found
No related tags found
No related merge requests found
......@@ -57,6 +57,8 @@ public class User {
public static final String LAST_SYNC_TIMESTAMP_FIELD = "lastSyncTimestamp";
public static final String LASTNAME_FIELD = "lastName";
public static final String FIRSTNAME_FIELD = "firstName";
public static final String FULL_NAME_FIELD = "fullName";
public static final String FULL_NAME_REVERSED_FIELD = "fullNameReversed";
public static final String USERNAME_FIELD = "username";
public static final String ORGANISATIONS_EINHEIT_IDS_FIELD = "organisationsEinheitIds";
public static final String NOTIFICATION_SEND_FOR_FIELD = "userSettings.notificationsSendFor";
......@@ -70,6 +72,10 @@ public class User {
private String keycloakUserId;
private String firstName;
private String lastName;
@JsonIgnore
private String fullName;
@JsonIgnore
private String fullNameReversed;
private String username;
private String email;
@JsonIgnore
......
......@@ -50,6 +50,8 @@ class UserRepository implements PanacheMongoRepository<User> {
private static final String SEARCH_QUERY = LASTNAME_FIELD + LIKE_OR +
FIRSTNAME_FIELD + LIKE_OR +
USERNAME_FIELD + LIKE_OR +
FULL_NAME_FIELD + LIKE_OR +
FULL_NAME_REVERSED_FIELD + LIKE_OR +
EMAIL_FIELD + " like " + param(PARAM_NAME_SEARCH_BY);
private static final String AND_DELETED = " and deleted = " + param(PARAM_NAME_DELETED);
......
......@@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import jakarta.inject.Inject;
......@@ -58,6 +59,8 @@ public abstract class UserResourceMapper {
@Mapping(target = "email", expression = "java(mapEmail(userRes))")
@Mapping(target = "firstName", expression = "java(mapFirstName(userRes))")
@Mapping(target = "lastName", expression = "java(mapLastName(userRes))")
@Mapping(target = "fullName", expression = "java(mapFullName(userRes))")
@Mapping(target = "fullNameReversed", expression = "java(mapFullNameReversed(userRes))")
@Mapping(target = "username", expression = "java(mapUsername(userRes))")
@Mapping(target = "externalId", expression = "java(mapId(userRes))")
@Mapping(target = "keycloakUserId", expression = "java(mapKeycloakUserId(userRes))")
......@@ -97,7 +100,6 @@ public abstract class UserResourceMapper {
List<String> mapRoles(UserResource userRes) {
var roleRepresentation = Optional.ofNullable(userRes.roles().getAll().getClientMappings())
.filter(Objects::nonNull)
.filter(map -> map.containsKey(properties.client()))
.map(map -> map.get(properties.client()))
.map(ClientMappingsRepresentation::getMappings)
......@@ -111,7 +113,6 @@ public abstract class UserResourceMapper {
return Optional.ofNullable(userRepresentation.getAttributes())
.map(attributes -> attributes.get(properties.ldapIdKey()))
.filter(Objects::nonNull)
.map(id -> id.get(0))
.orElseGet(userRepresentation::getId);
......@@ -136,4 +137,14 @@ public abstract class UserResourceMapper {
String mapUsername(UserResource userRes) {
return userRes.toRepresentation().getUsername();
}
String mapFullName(UserResource userRes) {
return String.join(" ", Stream.of(userRes.toRepresentation().getFirstName(), userRes.toRepresentation().getLastName())
.filter(Objects::nonNull).toArray(String[]::new));
}
String mapFullNameReversed(UserResource userRes) {
return String.join(" ", Stream.of(userRes.toRepresentation().getLastName(), userRes.toRepresentation().getFirstName())
.filter(Objects::nonNull).toArray(String[]::new));
}
}
......@@ -27,6 +27,7 @@ import static java.util.function.Predicate.not;
import static org.assertj.core.api.Assertions.*;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
......@@ -37,6 +38,9 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import com.thedeanda.lorem.LoremIpsum;
......@@ -234,6 +238,73 @@ class UserRepositoryITCase {
}
}
@Nested
class TestFindByFullName {
@BeforeEach
void init() {
repository.deleteAll();
}
@ParameterizedTest
@MethodSource("provideDataForFindUsersByFullName")
void shouldFindUsersByFullName(String query, String[] expectedUsernames) {
Arrays.asList(
UserTestFactory.createBuilder().id(null).username("user1").fullName("Franz Vogel").build(),
UserTestFactory.createBuilder().id(null).username("user2").fullName("Franz von Holzhausen").build(),
UserTestFactory.createBuilder().id(null).username("user3").fullName("Peter Lustig").build()
).forEach(repository::persist);
var foundUsernames = repository.findUsers(query, 10).map(User::getUsername);
assertThat(foundUsernames).containsExactlyInAnyOrder(expectedUsernames);
}
private static Stream<Arguments> provideDataForFindUsersByFullName() {
return Stream.of(
Arguments.of("Fra", new String[] { "user1", "user2" }),
Arguments.of("Franz", new String[] { "user1", "user2" }),
Arguments.of("Franz v", new String[] { "user1", "user2" }),
Arguments.of("Franz Vo ", new String[0]),
Arguments.of("Franz von", new String[] { "user2" }),
Arguments.of("Franz von Holzhausen", new String[] { "user2" }),
Arguments.of("Franz L", new String[0]),
Arguments.of("Peter V", new String[0])
);
}
}
@Nested
class TestFindByFullNameReversed {
@BeforeEach
void init() {
repository.deleteAll();
}
@ParameterizedTest
@MethodSource("provideDataForFindUsersByFullNameReversed")
void shouldFindUsersByFullNameReversed(String query, String[] expectedUsernames) {
Arrays.asList(
UserTestFactory.createBuilder().id(null).username("user1").fullNameReversed("Langbein Franz").build(),
UserTestFactory.createBuilder().id(null).username("user2").fullNameReversed("Lustig Peter").build(),
UserTestFactory.createBuilder().id(null).username("user3").fullNameReversed("Ilona Nowak").build()
).forEach(repository::persist);
var foundUsernames = repository.findUsers(query, 10).map(User::getUsername);
assertThat(foundUsernames).containsExactlyInAnyOrder(expectedUsernames);
}
private static Stream<Arguments> provideDataForFindUsersByFullNameReversed() {
return Stream.of(
Arguments.of("L", new String[] { "user1", "user2", "user3" }),
Arguments.of("Lustig", new String[] { "user2" }),
Arguments.of("Lustig Peter", new String[] { "user2" })
);
}
}
@Nested
class TestFindUsersByDeletedAndOrganisationsEinheitId {
......
......@@ -175,6 +175,20 @@ class UserResourceMapperTest {
assertThat(user.getKeycloakUserId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID_FALLBACK);
}
@Test
void shouldMapFullName() {
var user = toKopUser();
assertThat(user.getFullName()).isEqualTo(UserRepresentationTestFactory.FIRST_NAME + " " + UserRepresentationTestFactory.LAST_NAME);
}
@Test
void shouldMapFullNameReversed() {
var user = toKopUser();
assertThat(user.getFullNameReversed()).isEqualTo(UserRepresentationTestFactory.LAST_NAME + " " + UserRepresentationTestFactory.FIRST_NAME);
}
private User toKopUser() {
return toKopUser(UserResourceTestFactory.create());
}
......
......@@ -40,6 +40,8 @@ public class UserTestFactory {
public static final String FIRST_NAME = LoremIpsum.getInstance().getFirstName();
public static final String LAST_NAME = LoremIpsum.getInstance().getLastName();
public static final String FULL_NAME = FIRST_NAME + " " + LAST_NAME;
public static final String FULL_NAME_REVERSED = LAST_NAME + " " + FIRST_NAME;
public static final String USER_NAME = LoremIpsum.getInstance().getName();
public static final long LAST_SYNC_TIMESTAMP = 1001L;
public static final String EMAIL = LoremIpsum.getInstance().getEmail();
......@@ -57,6 +59,8 @@ public class UserTestFactory {
.keycloakUserId(KEYCLOAK_USER_ID)
.firstName(FIRST_NAME)
.lastName(LAST_NAME)
.fullName(FULL_NAME)
.fullNameReversed(FULL_NAME_REVERSED)
.username(USER_NAME)
.lastSyncTimestamp(LAST_SYNC_TIMESTAMP)
.email(EMAIL)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment