Skip to content

Commit d3a256f

Browse files
committed
Fixes #577
1 parent 2d4309a commit d3a256f

12 files changed

+344
-24
lines changed

server/src/main/java/invite/api/InvitationController.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import org.springframework.validation.annotation.Validated;
5252
import org.springframework.web.bind.annotation.*;
5353

54+
import java.net.URLDecoder;
55+
import java.nio.charset.Charset;
5456
import java.time.Instant;
5557
import java.util.*;
5658
import java.util.stream.Collectors;
@@ -444,18 +446,34 @@ public ResponseEntity<Page<Map<String, Object>>> search(@Parameter(hidden = true
444446

445447
Page<Map<String, Object>> invitationsPage;
446448
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.fromString(sortDirection), sort));
449+
boolean queryHasText = StringUtils.hasText(query);
450+
query = queryHasText ? URLDecoder.decode(query, Charset.defaultCharset()) : query;
451+
String parsedQuery = queryHasText ? FullSearchQueryParser.parse(query) : "";
452+
boolean noSearchTokens = parsedQuery.equals("*");
447453

448454
if (roleId == null) {
449455
UserPermissions.assertSuperUser(user);
450-
invitationsPage = StringUtils.hasText(query) ?
451-
invitationRepository.searchByStatusPageWithKeyword(Status.OPEN.name(), FullSearchQueryParser.parse(query), pageable) :
452-
invitationRepository.searchByStatusPage(Status.OPEN.name(), pageable);
456+
if (queryHasText && !noSearchTokens) {
457+
invitationsPage = invitationRepository.searchByStatusPageWithKeyword(Status.OPEN.name(), parsedQuery, pageable);
458+
} else if (noSearchTokens) {
459+
//Rare condition if users search on kb.nl, at@ex where all the parsed tokens are < 3 characters
460+
query = query.toUpperCase() + "%";
461+
invitationsPage = invitationRepository.searchByStatusPageWithStrictSearch(Status.OPEN.name(), query, pageable);
462+
} else {
463+
invitationsPage = invitationRepository.searchByStatusPage(Status.OPEN.name(), pageable);
464+
}
453465
} else {
454466
Role role = roleRepository.findById(roleId).orElseThrow(() -> new NotFoundException("Role not found"));
455467
UserPermissions.assertRoleAccess(user, role, Authority.INVITER);
456-
invitationsPage = StringUtils.hasText(query) ?
457-
invitationRepository.searchByStatusAndRoleWithKeywordPage(Status.OPEN.name(), role.getId(), FullSearchQueryParser.parse(query), pageable) :
458-
invitationRepository.searchByStatusAndRolePage(Status.OPEN.name(), role.getId(), pageable);
468+
if (queryHasText && !noSearchTokens) {
469+
invitationsPage = invitationRepository.searchByStatusAndRoleWithKeywordPage(Status.OPEN.name(), role.getId(), parsedQuery, pageable);
470+
} else if (noSearchTokens) {
471+
//Rare condition if users search on kb.nl, at@ex where all the parsed tokens are < 3 characters
472+
query = query.toUpperCase() + "%";
473+
invitationsPage = invitationRepository.searchByStatusAndRoleWithStrictSearch(Status.OPEN.name(), role.getId(), query, pageable);
474+
} else {
475+
invitationsPage = invitationRepository.searchByStatusAndRolePage(Status.OPEN.name(), role.getId(), pageable);
476+
}
459477
}
460478
if (invitationsPage.getTotalElements() == 0L) {
461479
return ResponseEntity.ok(invitationsPage);

server/src/main/java/invite/api/RoleController.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.springframework.validation.annotation.Validated;
3535
import org.springframework.web.bind.annotation.*;
3636

37+
import java.net.URLDecoder;
38+
import java.nio.charset.Charset;
3739
import java.sql.SQLTransactionRollbackException;
3840
import java.util.*;
3941
import java.util.stream.Collectors;
@@ -95,9 +97,19 @@ public ResponseEntity<Page<Role>> rolesByApplication(@Parameter(hidden = true) U
9597
rolesPage = roleRepository.searchByPage(pageable);
9698
} else {
9799
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.fromString(sortDirection), sort));
98-
rolesPage = StringUtils.hasText(query) ?
99-
roleRepository.searchByPageWithKeyword(FullSearchQueryParser.parse(query), pageable) :
100-
roleRepository.searchByPage(pageable);
100+
boolean queryHasText = StringUtils.hasText(query);
101+
query = queryHasText ? URLDecoder.decode(query, Charset.defaultCharset()) : query;
102+
String parsedQuery = queryHasText ? FullSearchQueryParser.parse(query) : "";
103+
boolean noSearchTokens = parsedQuery.equals("*");
104+
if (queryHasText && !noSearchTokens) {
105+
rolesPage = roleRepository.searchByPageWithKeyword(parsedQuery, pageable);
106+
} else if (noSearchTokens) {
107+
//Rare condition if users search on kb.nl, at@ex where all the parsed tokens are < 3 characters
108+
query = query.toUpperCase() + "%";
109+
rolesPage = roleRepository.searchByPageWithStrictSearch(query, pageable);
110+
} else {
111+
rolesPage = roleRepository.searchByPage(pageable);
112+
}
101113
}
102114
} else {
103115
UserPermissions.assertAuthority(user, Authority.INSTITUTION_ADMIN);

server/src/main/java/invite/api/UserController.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141
import org.springframework.web.servlet.view.RedirectView;
4242

4343
import java.net.InetAddress;
44+
import java.net.URLDecoder;
4445
import java.net.UnknownHostException;
46+
import java.nio.charset.Charset;
4547
import java.text.SimpleDateFormat;
4648
import java.util.*;
4749
import java.util.concurrent.atomic.AtomicReference;
@@ -148,9 +150,21 @@ public ResponseEntity<Page<Map<String, Object>>> search(@Parameter(hidden = true
148150

149151
UserPermissions.assertSuperUser(user);
150152
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.fromString(sortDirection), sort));
151-
Page<Map<String, Object>> usersPage = StringUtils.hasText(query) ?
152-
userRepository.searchByPageWithKeyword(FullSearchQueryParser.parse(query), pageable) :
153-
userRepository.searchByPage(pageable);
153+
154+
boolean queryHasText = StringUtils.hasText(query);
155+
query = queryHasText ? URLDecoder.decode(query, Charset.defaultCharset()) : query;
156+
String parsedQuery = queryHasText ? FullSearchQueryParser.parse(query) : "";
157+
boolean noSearchTokens = parsedQuery.equals("*");
158+
Page<Map<String, Object>> usersPage ;
159+
if (queryHasText && !noSearchTokens) {
160+
usersPage = userRepository.searchByPageWithKeyword(parsedQuery, pageable);
161+
} else if (noSearchTokens) {
162+
//Rare condition if users search on kb.nl, at@ex where all the parsed tokens are < 3 characters
163+
query = query.toUpperCase() + "%";
164+
usersPage = userRepository.searchByPageWithStrictMode(query, pageable);
165+
} else {
166+
usersPage = userRepository.searchByPage(pageable);
167+
}
154168
return ResponseEntity.ok(usersPage);
155169
}
156170

@@ -166,9 +180,21 @@ public ResponseEntity<Page<UserRoles>> searchByApplication(@Parameter(hidden = t
166180

167181
UserPermissions.assertInstitutionAdmin(user);
168182
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.fromString(sortDirection), sort));
169-
Page<Map<String, Object>> usersPage = StringUtils.hasText(query) ?
170-
userRepository.searchByPageRoleUsersWithKeyWord(user.getOrganizationGUID(), FullSearchQueryParser.parse(query), pageable) :
171-
userRepository.searchByPageRoleUsers(user.getOrganizationGUID(), pageable);
183+
boolean queryHasText = StringUtils.hasText(query);
184+
query = queryHasText ? URLDecoder.decode(query, Charset.defaultCharset()) : query;
185+
String parsedQuery = queryHasText ? FullSearchQueryParser.parse(query) : "";
186+
Page<Map<String, Object>> usersPage;
187+
String organizationGUID = user.getOrganizationGUID();
188+
boolean noSearchTokens = parsedQuery.equals("*");
189+
if (queryHasText && !noSearchTokens) {
190+
usersPage = userRepository.searchByPageRoleUsersWithKeyWord(organizationGUID, parsedQuery, pageable);
191+
} else if (noSearchTokens) {
192+
//Rare condition if users search on kb.nl, at@ex where all the parsed tokens are < 3 characters
193+
query = query.toUpperCase() + "%";
194+
usersPage = userRepository.searchByPageRoleUsersWithStrictSearch(organizationGUID, query, pageable);
195+
} else {
196+
usersPage = userRepository.searchByPageRoleUsers(organizationGUID, pageable);
197+
}
172198
List<Long> userIdentifiers = usersPage.getContent().stream().map(m -> (Long) m.get("id")).toList();
173199
List<Map<String, Object>> userRoles = userRepository.findUserRoles(userIdentifiers);
174200
List<UserRoles> userRoleList = this.userRoleFromQuery(usersPage, userRoles);

server/src/main/java/invite/api/UserRoleController.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,17 @@ public ResponseEntity<Page<?>> searchPaginated(@PathVariable("roleId") Long role
132132

133133
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.fromString(sortDirection), sort));
134134
Page<Map<String, Object>> page;
135-
boolean queryIsNotEmpty = StringUtils.hasText(query);
136-
query = queryIsNotEmpty ? URLDecoder.decode(query, Charset.defaultCharset()) : query;
137-
String parsedQuery = queryIsNotEmpty ? FullSearchQueryParser.parse(query) : "";
138-
if (queryIsNotEmpty && !parsedQuery.equals("*")) {
135+
boolean queryHasText = StringUtils.hasText(query);
136+
query = queryHasText ? URLDecoder.decode(query, Charset.defaultCharset()) : query;
137+
String parsedQuery = queryHasText ? FullSearchQueryParser.parse(query) : "";
138+
boolean noSearchTokens = parsedQuery.equals("*");
139+
if (queryHasText && !noSearchTokens) {
139140
page = guests ?
140141
userRoleRepository.searchGuestsByPageWithKeyword(roleId, parsedQuery, pageable) :
141142
userRoleRepository.searchNonGuestsByPageWithKeyword(roleId, parsedQuery, pageable);
142-
} else if ("*".equals(parsedQuery)) {
143+
} else if (noSearchTokens) {
143144
//Rare condition if users search on kb.nl, at@ex where all the parsed tokens are < 3 characters
145+
query = query.toUpperCase() + "%";
144146
page = guests ?
145147
userRoleRepository.searchGuestsByPageWithStrictSearch(roleId, query, pageable) :
146148
userRoleRepository.searchNonGuestsByPageWithStrictSearch(roleId, query, pageable);

server/src/main/java/invite/repository/InvitationRepository.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,24 @@ OR MATCH (u.given_name, u.family_name, u.email, u.schac_home_organization) again
6161
nativeQuery = true)
6262
Page<Map<String, Object>> searchByStatusPageWithKeyword(String status, String keyWord, Pageable pageable);
6363

64+
@Query(value = """
65+
SELECT i.id, i.email, i.remote_api_user, i.intended_authority,i.created_at, i.expiry_date,
66+
u.id as user_id, u.name, u.email as inviter_email
67+
FROM invitations i LEFT JOIN users u ON u.id = i.inviter_id
68+
WHERE i.status = ?1 AND
69+
(UPPER(i.email) LIKE ?2 or UPPER(u.schac_home_organization) LIKE ?2
70+
or UPPER(u.email) LIKE ?2)
71+
""",
72+
countQuery = """
73+
SELECT count(*) FROM invitations i LEFT JOIN users u ON u.id = i.inviter_id
74+
WHERE status = ?1 AND
75+
(UPPER(i.email) LIKE ?2 or UPPER(u.schac_home_organization) LIKE ?2
76+
or UPPER(u.email) LIKE ?2)
77+
""",
78+
queryRewriter = InvitationRepository.class,
79+
nativeQuery = true)
80+
Page<Map<String, Object>> searchByStatusPageWithStrictSearch(String status, String keyWord, Pageable pageable);
81+
6482
@Query(value = """
6583
SELECT i.id, i.email, i.remote_api_user, i.intended_authority,i.created_at, i.expiry_date,
6684
u.id as user_id, u.name, u.email as inviter_email
@@ -100,6 +118,28 @@ OR MATCH (u.given_name, u.family_name, u.email, u.schac_home_organization) again
100118
nativeQuery = true)
101119
Page<Map<String, Object>> searchByStatusAndRoleWithKeywordPage(String status, Long roleId, String keyWord, Pageable pageable);
102120

121+
@Query(value = """
122+
SELECT i.id, i.email, i.remote_api_user, i.intended_authority,i.created_at, i.expiry_date,
123+
u.id as user_id, u.name, u.email as inviter_email
124+
FROM invitations i LEFT JOIN users u ON u.id = i.inviter_id INNER JOIN invitation_roles ir ON ir.invitation_id = i.id
125+
INNER JOIN roles r ON r.id = ir.role_id
126+
WHERE i.status = ?1 AND r.id = ?2 AND
127+
(UPPER(i.email) LIKE ?3 or UPPER(u.schac_home_organization) LIKE ?3
128+
or UPPER(u.email) LIKE ?3)
129+
""",
130+
countQuery = """
131+
SELECT count(*) FROM invitations i
132+
INNER JOIN invitation_roles ir ON ir.invitation_id = i.id
133+
INNER JOIN roles r ON r.id = ir.role_id
134+
LEFT JOIN users u ON u.id = i.inviter_id
135+
WHERE status = ?1 and role_id = ?2 AND
136+
(UPPER(i.email) LIKE ?3 or UPPER(u.schac_home_organization) LIKE ?3
137+
or UPPER(u.email) LIKE ?3)
138+
""",
139+
queryRewriter = InvitationRepository.class,
140+
nativeQuery = true)
141+
Page<Map<String, Object>> searchByStatusAndRoleWithStrictSearch(String status, Long roleId, String keyWord, Pageable pageable);
142+
103143
@Query(value = """
104144
SELECT ir.invitation_id as id, r.name, r.id as role_id, a.manage_id
105145
FROM roles r INNER JOIN invitation_roles ir ON ir.role_id = r.id

server/src/main/java/invite/repository/RoleRepository.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ SELECT COUNT(r.id) FROM roles r WHERE MATCH (name, description) against (?1 IN B
4545
nativeQuery = true)
4646
Page<Role> searchByPageWithKeyword(String keyword, Pageable pageable);
4747

48+
@Query(value = """
49+
SELECT *,
50+
(SELECT COUNT(*) FROM user_roles ur WHERE ur.role_id=r.id) as userRoleCount
51+
FROM roles r WHERE
52+
UPPER(r.name) LIKE ?1 or UPPER(r.description) LIKE ?1
53+
""",
54+
countQuery = """
55+
SELECT COUNT(r.id) FROM roles r WHERE
56+
UPPER(r.name) LIKE ?1 or UPPER(r.description) LIKE ?1
57+
""",
58+
queryRewriter = RoleRepository.class,
59+
nativeQuery = true)
60+
Page<Role> searchByPageWithStrictSearch(String keyword, Pageable pageable);
4861

4962
@Query(value = """
5063
SELECT *,

server/src/main/java/invite/repository/UserRepository.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ FROM users u WHERE MATCH (given_name, family_name, email, schac_home_organizatio
5555
nativeQuery = true)
5656
Page<Map<String, Object>> searchByPageWithKeyword(String keyWord, Pageable pageable);
5757

58+
@Query(value = """
59+
SELECT u.id, u.name, u.email, u.schac_home_organization, u.super_user, u.institution_admin,
60+
u.created_at as createdAt, u.last_activity as lastActivity,
61+
(SELECT GROUP_CONCAT(DISTINCT ur.authority) FROM user_roles ur WHERE ur.user_id = u.id) AS authority
62+
FROM users u WHERE
63+
UPPER(u.email) LIKE ?1 or UPPER(u.schac_home_organization) LIKE ?1
64+
""",
65+
countQuery = "SELECT count(*) FROM users WHERE " +
66+
"UPPER(u.email) LIKE ?1 or UPPER(u.schac_home_organization) LIKE ?1",
67+
queryRewriter = UserRepository.class,
68+
nativeQuery = true)
69+
Page<Map<String, Object>> searchByPageWithStrictMode(String keyWord, Pageable pageable);
70+
5871
@Query(value = """
5972
SELECT distinct(u.id), u.email, u.name, u.schac_home_organization, u.created_at, u.last_activity
6073
FROM users u
@@ -78,6 +91,18 @@ SELECT distinct(u.id), u.email, u.name, u.schac_home_organization, u.created_at,
7891
nativeQuery = true)
7992
Page<Map<String, Object>> searchByPageRoleUsersWithKeyWord(String organisationGUID, String query, Pageable pageable);
8093

94+
@Query(value = """
95+
SELECT distinct(u.id), u.email, u.name, u.schac_home_organization, u.created_at, u.last_activity
96+
FROM users u
97+
INNER JOIN user_roles ur ON ur.user_id = u.id
98+
INNER JOIN roles r ON r.id = ur.role_id
99+
WHERE r.organization_guid = ?1 AND
100+
(UPPER(u.email) LIKE ?2 or UPPER(u.schac_home_organization) LIKE ?2)
101+
""",
102+
queryRewriter = UserRepository.class,
103+
nativeQuery = true)
104+
Page<Map<String, Object>> searchByPageRoleUsersWithStrictSearch(String organisationGUID, String query, Pageable pageable);
105+
81106
@Query(value = """
82107
SELECT ur.user_id, ur.authority, ur.end_date, r.name, r.id
83108
FROM user_roles ur INNER JOIN roles r ON r.id = ur.role_id

server/src/main/java/invite/repository/UserRoleRepository.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,12 @@ AND MATCH (u.given_name, u.family_name, u.email, u.schac_home_organization) AGAI
116116
INNER JOIN roles r on r.id = ur.role_id
117117
INNER JOIN users u on u.id = ur.user_id WHERE ur.role_id = ?1
118118
AND ur.authority <> 'GUEST' AND
119-
(u.email LIKE ?2 or u.schac_home_organization LIKE ?2)
119+
(UPPER(u.email) LIKE ?2 or UPPER(u.schac_home_organization) LIKE ?2)
120120
""",
121121
countQuery = """
122122
SELECT COUNT(ur.id) FROM user_roles ur INNER JOIN users u on u.id = ur.user_id
123123
WHERE ur.role_id = ?1 AND ur.authority <> 'GUEST'
124-
AND (u.email LIKE ?2 or u.schac_home_organization LIKE ?2)
124+
AND (UPPER(u.email) LIKE ?2 or UPPER(u.schac_home_organization) LIKE ?2)
125125
""",
126126
queryRewriter = UserRoleRepository.class,
127127
nativeQuery = true)
@@ -134,12 +134,12 @@ SELECT COUNT(ur.id) FROM user_roles ur INNER JOIN users u on u.id = ur.user_id
134134
INNER JOIN roles r on r.id = ur.role_id
135135
INNER JOIN users u on u.id = ur.user_id WHERE ur.role_id = ?1
136136
AND (ur.authority = 'GUEST' OR ur.guest_role_included ) AND
137-
(u.email LIKE ?2 or u.schac_home_organization LIKE ?2)
137+
(UPPER(u.email) LIKE ?2 or UPPER(u.schac_home_organization) LIKE ?2)
138138
""",
139139
countQuery = """
140140
SELECT COUNT(ur.id) FROM user_roles ur INNER JOIN users u on u.id = ur.user_id
141141
WHERE ur.role_id = ?1 AND (ur.authority = 'GUEST' OR ur.guest_role_included )
142-
AND (u.email LIKE ?2 or u.schac_home_organization LIKE ?2)
142+
AND (UPPER(u.email) LIKE ?2 or UPPER(u.schac_home_organization) LIKE ?2)
143143
""",
144144
queryRewriter = UserRoleRepository.class,
145145
nativeQuery = true)

0 commit comments

Comments
 (0)