View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.core.persistence.jpa.inner;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import java.text.ParseException;
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  import java.util.HashSet;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Optional;
33  import java.util.Set;
34  import java.util.stream.Collectors;
35  import java.util.stream.Stream;
36  import org.apache.syncope.common.lib.SyncopeConstants;
37  import org.apache.syncope.common.lib.types.AnyTypeKind;
38  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
39  import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
40  import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
41  import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
42  import org.apache.syncope.core.persistence.api.dao.GroupDAO;
43  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
44  import org.apache.syncope.core.persistence.api.dao.RoleDAO;
45  import org.apache.syncope.core.persistence.api.dao.UserDAO;
46  import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
47  import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
48  import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
49  import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
50  import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
51  import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
52  import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
53  import org.apache.syncope.core.persistence.api.dao.search.PrivilegeCond;
54  import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
55  import org.apache.syncope.core.persistence.api.dao.search.ResourceCond;
56  import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
57  import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
58  import org.apache.syncope.core.persistence.api.entity.AnyType;
59  import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
60  import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
61  import org.apache.syncope.core.persistence.api.entity.group.Group;
62  import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
63  import org.apache.syncope.core.persistence.api.entity.user.User;
64  import org.apache.syncope.core.persistence.jpa.AbstractTest;
65  import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
66  import org.apache.syncope.core.provisioning.api.utils.RealmUtils;
67  import org.apache.syncope.core.spring.security.AuthContextUtils;
68  import org.apache.syncope.core.spring.security.AuthDataAccessor;
69  import org.apache.syncope.core.spring.security.SyncopeAuthenticationDetails;
70  import org.apache.syncope.core.spring.security.SyncopeGrantedAuthority;
71  import org.junit.jupiter.api.BeforeEach;
72  import org.junit.jupiter.api.Test;
73  import org.springframework.beans.factory.annotation.Autowired;
74  import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
75  import org.springframework.security.core.context.SecurityContextHolder;
76  import org.springframework.transaction.annotation.Transactional;
77  
78  @Transactional("Master")
79  public class AnySearchTest extends AbstractTest {
80  
81      private static final String LOGIN_DATE_VALUE = "2009-05-26";
82  
83      @Autowired
84      private UserDAO userDAO;
85  
86      @Autowired
87      private AnyObjectDAO anyObjectDAO;
88  
89      @Autowired
90      private GroupDAO groupDAO;
91  
92      @Autowired
93      private AnySearchDAO searchDAO;
94  
95      @Autowired
96      private AnyTypeDAO anyTypeDAO;
97  
98      @Autowired
99      private RealmDAO realmDAO;
100 
101     @Autowired
102     private RoleDAO roleDAO;
103 
104     @BeforeEach
105     public void adjustLoginDateForLocalSystem() throws ParseException {
106         User rossini = userDAO.findByUsername("rossini");
107 
108         UPlainAttr loginDate = rossini.getPlainAttr("loginDate").get();
109         loginDate.getValues().get(0).setDateValue(FormatUtils.parseDate(LOGIN_DATE_VALUE, "yyyy-MM-dd"));
110 
111         userDAO.save(rossini);
112     }
113 
114     @Test
115     public void searchWithLikeCondition() {
116         AttrCond fullnameLeafCond = new AttrCond(AttrCond.Type.LIKE);
117         fullnameLeafCond.setSchema("fullname");
118         fullnameLeafCond.setExpression("%o%");
119 
120         MembershipCond groupCond = new MembershipCond();
121         groupCond.setGroup("root");
122 
123         AttrCond loginDateCond = new AttrCond(AttrCond.Type.EQ);
124         loginDateCond.setSchema("loginDate");
125         loginDateCond.setExpression(LOGIN_DATE_VALUE);
126 
127         SearchCond subCond = SearchCond.getAnd(
128                 SearchCond.getLeaf(fullnameLeafCond), SearchCond.getLeaf(groupCond));
129 
130         assertTrue(subCond.isValid());
131 
132         SearchCond cond = SearchCond.getAnd(subCond, SearchCond.getLeaf(loginDateCond));
133 
134         assertTrue(cond.isValid());
135 
136         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
137         assertNotNull(users);
138         assertEquals(1, users.size());
139     }
140 
141     @Test
142     public void searchCaseInsensitiveWithLikeCondition() {
143         AttrCond fullnameLeafCond = new AttrCond(AttrCond.Type.ILIKE);
144         fullnameLeafCond.setSchema("fullname");
145         fullnameLeafCond.setExpression("%O%");
146 
147         MembershipCond groupCond = new MembershipCond();
148         groupCond.setGroup("root");
149 
150         AttrCond loginDateCond = new AttrCond(AttrCond.Type.EQ);
151         loginDateCond.setSchema("loginDate");
152         loginDateCond.setExpression(LOGIN_DATE_VALUE);
153 
154         SearchCond subCond = SearchCond.getAnd(
155                 SearchCond.getLeaf(fullnameLeafCond), SearchCond.getLeaf(groupCond));
156 
157         assertTrue(subCond.isValid());
158 
159         SearchCond cond = SearchCond.getAnd(subCond, SearchCond.getLeaf(loginDateCond));
160 
161         assertTrue(cond.isValid());
162 
163         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
164         assertNotNull(users);
165         assertEquals(1, users.size());
166     }
167 
168     @Test
169     public void searchWithNotAttrCond() {
170         AttrCond fullnameLeafCond = new AttrCond(AttrCond.Type.EQ);
171         fullnameLeafCond.setSchema("fullname");
172         fullnameLeafCond.setExpression("Giuseppe Verdi");
173 
174         SearchCond cond = SearchCond.getNotLeaf(fullnameLeafCond);
175         assertTrue(cond.isValid());
176 
177         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
178         assertNotNull(users);
179         assertEquals(4, users.size());
180 
181         Set<String> ids = users.stream().map(User::getKey).collect(Collectors.toSet());
182         assertTrue(ids.contains("1417acbe-cbf6-4277-9372-e75e04f97000"));
183         assertTrue(ids.contains("b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee"));
184     }
185 
186     @Test
187     public void searchWithNotAnyCond() {
188         AnyCond usernameLeafCond = new AnyCond(AttrCond.Type.EQ);
189         usernameLeafCond.setSchema("username");
190         usernameLeafCond.setExpression("verdi");
191 
192         SearchCond cond = SearchCond.getNotLeaf(usernameLeafCond);
193         assertTrue(cond.isValid());
194 
195         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
196         assertNotNull(users);
197         assertEquals(4, users.size());
198 
199         assertTrue(users.stream().noneMatch(user -> "verdi".equals(user.getUsername())));
200     }
201 
202     @Test
203     public void searchCaseInsensitiveWithNotCondition() {
204         AttrCond fullnameLeafCond = new AttrCond(AttrCond.Type.IEQ);
205         fullnameLeafCond.setSchema("fullname");
206         fullnameLeafCond.setExpression("giuseppe verdi");
207 
208         SearchCond cond = SearchCond.getNotLeaf(fullnameLeafCond);
209         assertTrue(cond.isValid());
210 
211         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
212         assertNotNull(users);
213         assertEquals(4, users.size());
214 
215         Set<String> ids = users.stream().map(User::getKey).collect(Collectors.toSet());
216         assertTrue(ids.contains("1417acbe-cbf6-4277-9372-e75e04f97000"));
217         assertTrue(ids.contains("b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee"));
218     }
219 
220     @Test
221     public void searchByBoolean() {
222         AttrCond coolLeafCond = new AttrCond(AttrCond.Type.EQ);
223         coolLeafCond.setSchema("cool");
224         coolLeafCond.setExpression("true");
225 
226         SearchCond cond = SearchCond.getLeaf(coolLeafCond);
227         assertTrue(cond.isValid());
228 
229         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
230         assertNotNull(users);
231         assertEquals(1, users.size());
232 
233         assertEquals("c9b2dec2-00a7-4855-97c0-d854842b4b24", users.get(0).getKey());
234     }
235 
236     @Test
237     public void searchByRealm() {
238         AnyCond anyCond = new AnyCond(AttrCond.Type.EQ);
239         anyCond.setSchema("realm");
240         anyCond.setExpression("c5b75db1-fce7-470f-b780-3b9934d82a9d");
241 
242         List<User> users = searchDAO.search(SearchCond.getLeaf(anyCond), AnyTypeKind.USER);
243         assertNotNull(users);
244         assertEquals(1, users.size());
245         assertEquals("rossini", users.get(0).getUsername());
246 
247         anyCond.setExpression("/even");
248         users = searchDAO.search(SearchCond.getLeaf(anyCond), AnyTypeKind.USER);
249         assertNotNull(users);
250         assertEquals(1, users.size());
251         assertEquals("rossini", users.get(0).getUsername());
252     }
253 
254     @Test
255     public void searchByPageAndSize() {
256         AttrCond fullnameLeafCond = new AttrCond(AttrCond.Type.LIKE);
257         fullnameLeafCond.setSchema("fullname");
258         fullnameLeafCond.setExpression("%o%");
259 
260         MembershipCond groupCond = new MembershipCond();
261         groupCond.setGroup("root");
262 
263         AttrCond loginDateCond = new AttrCond(AttrCond.Type.EQ);
264         loginDateCond.setSchema("loginDate");
265         loginDateCond.setExpression(LOGIN_DATE_VALUE);
266 
267         SearchCond subCond = SearchCond.getAnd(
268                 SearchCond.getLeaf(fullnameLeafCond), SearchCond.getLeaf(groupCond));
269 
270         assertTrue(subCond.isValid());
271 
272         SearchCond cond = SearchCond.getAnd(subCond, SearchCond.getLeaf(loginDateCond));
273 
274         assertTrue(cond.isValid());
275 
276         int count = searchDAO.count(
277                 realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, cond, AnyTypeKind.USER);
278         assertEquals(1, count);
279 
280         List<User> users = searchDAO.search(
281                 realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, cond, 1, 2, List.of(), AnyTypeKind.USER);
282         assertNotNull(users);
283         assertEquals(1, users.size());
284 
285         users = searchDAO.search(
286                 realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, cond, 2, 2, List.of(), AnyTypeKind.USER);
287         assertNotNull(users);
288         assertTrue(users.isEmpty());
289     }
290 
291     @Test
292     public void searchByGroup() {
293         MembershipCond groupCond = new MembershipCond();
294         groupCond.setGroup("child");
295 
296         List<User> matchingChild = searchDAO.search(SearchCond.getLeaf(groupCond), AnyTypeKind.USER);
297         assertNotNull(matchingChild);
298         assertTrue(matchingChild.stream().anyMatch(user -> "verdi".equals(user.getUsername())));
299 
300         groupCond.setGroup("otherchild");
301 
302         List<User> matchingOtherChild = searchDAO.search(SearchCond.getLeaf(groupCond), AnyTypeKind.USER);
303         assertNotNull(matchingOtherChild);
304         assertTrue(matchingOtherChild.stream().anyMatch(user -> "rossini".equals(user.getUsername())));
305 
306         Set<String> union = Stream.concat(
307                 matchingChild.stream().map(User::getUsername),
308                 matchingOtherChild.stream().map(User::getUsername)).
309                 collect(Collectors.toSet());
310 
311         groupCond.setGroup("%child");
312 
313         List<User> matchingStar = searchDAO.search(SearchCond.getLeaf(groupCond), AnyTypeKind.USER);
314         assertNotNull(matchingStar);
315         assertTrue(matchingStar.stream().anyMatch(user -> "verdi".equals(user.getUsername())));
316         assertTrue(matchingStar.stream().anyMatch(user -> "rossini".equals(user.getUsername())));
317         assertEquals(union, matchingStar.stream().map(User::getUsername).collect(Collectors.toSet()));
318 
319         matchingStar = searchDAO.search(realmDAO.getRoot(), false, SyncopeConstants.FULL_ADMIN_REALMS,
320                 SearchCond.getLeaf(groupCond), -1, -1, List.of(), AnyTypeKind.USER);
321         assertNotNull(matchingStar);
322         assertTrue(matchingStar.stream().anyMatch(user -> "verdi".equals(user.getUsername())));
323         assertTrue(matchingStar.stream().noneMatch(user -> "rossini".equals(user.getUsername())));
324     }
325 
326     @Test
327     public void searchByRole() {
328         RoleCond roleCond = new RoleCond();
329         roleCond.setRole("Other");
330 
331         List<User> users = searchDAO.search(SearchCond.getLeaf(roleCond), AnyTypeKind.USER);
332         assertNotNull(users);
333         assertEquals(1, users.size());
334     }
335 
336     @Test
337     public void searchByPrivilege() {
338         PrivilegeCond privilegeCond = new PrivilegeCond();
339         privilegeCond.setPrivilege("postMighty");
340 
341         List<User> users = searchDAO.search(SearchCond.getLeaf(privilegeCond), AnyTypeKind.USER);
342         assertNotNull(users);
343         assertEquals(1, users.size());
344     }
345 
346     @Test
347     public void searchByIsNull() {
348         AttrCond coolLeafCond = new AttrCond(AttrCond.Type.ISNULL);
349         coolLeafCond.setSchema("cool");
350 
351         List<User> users = searchDAO.search(SearchCond.getLeaf(coolLeafCond), AnyTypeKind.USER);
352         assertNotNull(users);
353         assertEquals(4, users.size());
354 
355         coolLeafCond = new AttrCond(AttrCond.Type.ISNOTNULL);
356         coolLeafCond.setSchema("cool");
357 
358         users = searchDAO.search(SearchCond.getLeaf(coolLeafCond), AnyTypeKind.USER);
359         assertNotNull(users);
360         assertEquals(1, users.size());
361     }
362 
363     @Test
364     public void searchByAuxClass() {
365         AuxClassCond ac = new AuxClassCond();
366         ac.setAuxClass("csv");
367 
368         List<Group> groups = searchDAO.search(SearchCond.getLeaf(ac), AnyTypeKind.GROUP);
369         assertNotNull(groups);
370         assertEquals(2, groups.size());
371     }
372 
373     @Test
374     public void searchByResource() {
375         ResourceCond ws2 = new ResourceCond();
376         ws2.setResource("ws-target-resource-2");
377 
378         ResourceCond ws1 = new ResourceCond();
379         ws1.setResource("ws-target-resource-list-mappings-2");
380 
381         SearchCond searchCondition = SearchCond.getAnd(SearchCond.getNotLeaf(ws2), SearchCond.getLeaf(ws1));
382         assertTrue(searchCondition.isValid());
383 
384         List<User> users = searchDAO.search(searchCondition, AnyTypeKind.USER);
385         assertNotNull(users);
386         assertEquals(1, users.size());
387     }
388 
389     @Test
390     public void searchByBooleanAnyCond() {
391         AttrCond booleanCond = new AttrCond(AnyCond.Type.EQ);
392         booleanCond.setSchema("show");
393         booleanCond.setExpression("true");
394 
395         List<Group> matchingGroups = searchDAO.search(SearchCond.getLeaf(booleanCond), AnyTypeKind.GROUP);
396         assertNotNull(matchingGroups);
397         assertFalse(matchingGroups.isEmpty());
398     }
399 
400     @Test
401     public void searchByUsernameAndKey() {
402         AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.LIKE);
403         usernameLeafCond.setSchema("username");
404         usernameLeafCond.setExpression("%ini");
405 
406         AnyCond idRightCond = new AnyCond(AnyCond.Type.LT);
407         idRightCond.setSchema("key");
408         idRightCond.setExpression("2");
409 
410         SearchCond searchCondition = SearchCond.getAnd(
411                 SearchCond.getLeaf(usernameLeafCond),
412                 SearchCond.getLeaf(idRightCond));
413 
414         List<User> matching = searchDAO.search(searchCondition, AnyTypeKind.USER);
415         assertNotNull(matching);
416         assertEquals(1, matching.size());
417         assertEquals("rossini", matching.iterator().next().getUsername());
418         assertEquals("1417acbe-cbf6-4277-9372-e75e04f97000", matching.iterator().next().getKey());
419     }
420 
421     @Test
422     public void searchByGroupNameAndKey() {
423         AnyCond groupNameLeafCond = new AnyCond(AnyCond.Type.EQ);
424         groupNameLeafCond.setSchema("name");
425         groupNameLeafCond.setExpression("root");
426 
427         AnyCond idRightCond = new AnyCond(AnyCond.Type.EQ);
428         idRightCond.setSchema("key");
429         idRightCond.setExpression("37d15e4c-cdc1-460b-a591-8505c8133806");
430 
431         SearchCond searchCondition = SearchCond.getAnd(
432                 SearchCond.getLeaf(groupNameLeafCond),
433                 SearchCond.getLeaf(idRightCond));
434 
435         assertTrue(searchCondition.isValid());
436 
437         List<Group> matching = searchDAO.search(searchCondition, AnyTypeKind.GROUP);
438         assertNotNull(matching);
439         assertEquals(1, matching.size());
440         assertEquals("root", matching.iterator().next().getName());
441         assertEquals("37d15e4c-cdc1-460b-a591-8505c8133806", matching.iterator().next().getKey());
442     }
443 
444     @Test
445     public void searchByUsernameAndFullname() {
446         AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.EQ);
447         usernameLeafCond.setSchema("username");
448         usernameLeafCond.setExpression("rossini");
449 
450         AttrCond idRightCond = new AttrCond(AttrCond.Type.LIKE);
451         idRightCond.setSchema("fullname");
452         idRightCond.setExpression("Giuseppe V%");
453 
454         SearchCond searchCondition = SearchCond.getOr(
455                 SearchCond.getLeaf(usernameLeafCond),
456                 SearchCond.getLeaf(idRightCond));
457 
458         List<User> matchingUsers = searchDAO.search(searchCondition, AnyTypeKind.USER);
459         assertNotNull(matchingUsers);
460         assertEquals(2, matchingUsers.size());
461     }
462 
463     @Test
464     public void searchByUsernameAndFullnameIgnoreCase() {
465         AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.IEQ);
466         usernameLeafCond.setSchema("username");
467         usernameLeafCond.setExpression("RoSsini");
468 
469         AttrCond idRightCond = new AttrCond(AttrCond.Type.ILIKE);
470         idRightCond.setSchema("fullname");
471         idRightCond.setExpression("gIuseppe v%");
472 
473         SearchCond searchCondition = SearchCond.getOr(
474                 SearchCond.getLeaf(usernameLeafCond),
475                 SearchCond.getLeaf(idRightCond));
476 
477         List<User> matchingUsers = searchDAO.search(searchCondition, AnyTypeKind.USER);
478         assertNotNull(matchingUsers);
479         assertEquals(2, matchingUsers.size());
480     }
481 
482     @Test
483     public void searchByKey() {
484         AnyCond idLeafCond = new AnyCond(AnyCond.Type.EQ);
485         idLeafCond.setSchema("key");
486         idLeafCond.setExpression("74cd8ece-715a-44a4-a736-e17b46c4e7e6");
487 
488         SearchCond searchCondition = SearchCond.getLeaf(idLeafCond);
489         assertTrue(searchCondition.isValid());
490 
491         List<User> users = searchDAO.search(searchCondition, AnyTypeKind.USER);
492         assertNotNull(users);
493         assertEquals(1, users.size());
494         assertEquals("74cd8ece-715a-44a4-a736-e17b46c4e7e6", users.iterator().next().getKey());
495     }
496 
497     @Test
498     public void searchByType() {
499         AnyTypeCond tcond = new AnyTypeCond();
500         tcond.setAnyTypeKey("PRINTER");
501 
502         SearchCond searchCondition = SearchCond.getLeaf(tcond);
503         assertTrue(searchCondition.isValid());
504 
505         List<AnyObject> printers = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
506         assertNotNull(printers);
507         assertEquals(3, printers.size());
508 
509         tcond.setAnyTypeKey("UNEXISTING");
510         printers = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
511         assertNotNull(printers);
512         assertTrue(printers.isEmpty());
513     }
514 
515     @Test
516     public void searchByRelationshipType() {
517         // 1. first search for printers involved in "neighborhood" relationship
518         RelationshipTypeCond relationshipTypeCond = new RelationshipTypeCond();
519         relationshipTypeCond.setRelationshipTypeKey("neighborhood");
520 
521         AnyTypeCond tcond = new AnyTypeCond();
522         tcond.setAnyTypeKey("PRINTER");
523 
524         SearchCond searchCondition = SearchCond.getAnd(
525                 SearchCond.getLeaf(relationshipTypeCond), SearchCond.getLeaf(tcond));
526         assertTrue(searchCondition.isValid());
527 
528         List<AnyObject> anyObjects = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
529         assertNotNull(anyObjects);
530         assertEquals(2, anyObjects.size());
531         assertTrue(anyObjects.stream().anyMatch(any -> "fc6dbc3a-6c07-4965-8781-921e7401a4a5".equals(any.getKey())));
532         assertTrue(anyObjects.stream().anyMatch(any -> "8559d14d-58c2-46eb-a2d4-a7d35161e8f8".equals(any.getKey())));
533 
534         // 2. search for users involved in "neighborhood" relationship
535         searchCondition = SearchCond.getLeaf(relationshipTypeCond);
536         List<User> users = searchDAO.search(searchCondition, AnyTypeKind.USER);
537         assertNotNull(users);
538         assertEquals(1, users.size());
539         assertTrue(users.stream().anyMatch(any -> "c9b2dec2-00a7-4855-97c0-d854842b4b24".equals(any.getKey())));
540     }
541 
542     @Test
543     public void searchByAnyCondDate() {
544         AnyCond creationDateCond = new AnyCond(AnyCond.Type.EQ);
545         creationDateCond.setSchema("creationDate");
546         creationDateCond.setExpression("2021-04-15 12:45:00");
547 
548         SearchCond searchCondition = SearchCond.getLeaf(creationDateCond);
549         assertTrue(searchCondition.isValid());
550 
551         List<AnyObject> anyObjects = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
552         assertNotNull(anyObjects);
553         assertEquals(1, anyObjects.size());
554         assertEquals("9e1d130c-d6a3-48b1-98b3-182477ed0688", anyObjects.iterator().next().getKey());
555     }
556 
557     @Test
558     public void searchByAttrCondDate() {
559         AttrCond loginDateCond = new AttrCond(AnyCond.Type.LT);
560         loginDateCond.setSchema("loginDate");
561         loginDateCond.setExpression("2009-05-27");
562 
563         SearchCond searchCondition = SearchCond.getLeaf(loginDateCond);
564         assertTrue(searchCondition.isValid());
565 
566         List<User> users = searchDAO.search(searchCondition, AnyTypeKind.USER);
567         assertNotNull(users);
568         assertEquals(1, users.size());
569         assertEquals("1417acbe-cbf6-4277-9372-e75e04f97000", users.iterator().next().getKey());
570     }
571 
572     @Test
573     public void userOrderBy() {
574         AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.EQ);
575         usernameLeafCond.setSchema("username");
576         usernameLeafCond.setExpression("rossini");
577         AttrCond idRightCond = new AttrCond(AttrCond.Type.LIKE);
578         idRightCond.setSchema("fullname");
579         idRightCond.setExpression("Giuseppe V%");
580         SearchCond searchCondition = SearchCond.getOr(
581                 SearchCond.getLeaf(usernameLeafCond), SearchCond.getLeaf(idRightCond));
582 
583         List<OrderByClause> orderByClauses = new ArrayList<>();
584         OrderByClause orderByClause = new OrderByClause();
585         orderByClause.setField("username");
586         orderByClause.setDirection(OrderByClause.Direction.DESC);
587         orderByClauses.add(orderByClause);
588         orderByClause = new OrderByClause();
589         orderByClause.setField("fullname");
590         orderByClause.setDirection(OrderByClause.Direction.ASC);
591         orderByClauses.add(orderByClause);
592 
593         List<User> users = searchDAO.search(searchCondition, orderByClauses, AnyTypeKind.USER);
594         assertEquals(
595                 searchDAO.count(
596                         realmDAO.getRoot(), true,
597                         SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
598                 users.size());
599     }
600 
601     @Test
602     public void groupOrderBy() {
603         AnyCond idLeafCond = new AnyCond(AnyCond.Type.LIKE);
604         idLeafCond.setSchema("name");
605         idLeafCond.setExpression("%r");
606         SearchCond searchCondition = SearchCond.getLeaf(idLeafCond);
607         assertTrue(searchCondition.isValid());
608 
609         OrderByClause orderByClause = new OrderByClause();
610         orderByClause.setField("name");
611 
612         List<Group> groups = searchDAO.search(
613                 searchCondition, List.of(orderByClause), AnyTypeKind.GROUP);
614         assertEquals(
615                 searchDAO.count(
616                         realmDAO.getRoot(), true,
617                         SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.GROUP),
618                 groups.size());
619     }
620 
621     @Test
622     public void member() {
623         MemberCond memberCond = new MemberCond();
624         memberCond.setMember("1417acbe-cbf6-4277-9372-e75e04f97000");
625         SearchCond searchCondition = SearchCond.getLeaf(memberCond);
626         assertTrue(searchCondition.isValid());
627 
628         List<Group> groups = searchDAO.search(searchCondition, AnyTypeKind.GROUP);
629         assertEquals(2, groups.size());
630         assertTrue(groups.contains(groupDAO.findByName("root")));
631         assertTrue(groups.contains(groupDAO.findByName("otherchild")));
632     }
633 
634     @Test
635     public void asGroupOwner() {
636         // prepare authentication
637         Map<String, Set<String>> entForRealms = new HashMap<>();
638         roleDAO.find(AuthDataAccessor.GROUP_OWNER_ROLE).getEntitlements().forEach(entitlement -> {
639             Set<String> realms = Optional.ofNullable(entForRealms.get(entitlement)).orElseGet(() -> {
640                 Set<String> r = new HashSet<>();
641                 entForRealms.put(entitlement, r);
642                 return r;
643             });
644 
645             realms.add(RealmUtils.getGroupOwnerRealm(
646                     SyncopeConstants.ROOT_REALM, "37d15e4c-cdc1-460b-a591-8505c8133806"));
647         });
648 
649         Set<SyncopeGrantedAuthority> authorities = new HashSet<>();
650         entForRealms.forEach((key, value) -> {
651             SyncopeGrantedAuthority authority = new SyncopeGrantedAuthority(key);
652             authority.addRealms(value);
653             authorities.add(authority);
654         });
655 
656         UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
657                 new org.springframework.security.core.userdetails.User(
658                         "poorGroupOwner", "FAKE_PASSWORD", authorities), "FAKE_PASSWORD", authorities);
659         auth.setDetails(new SyncopeAuthenticationDetails(SyncopeConstants.MASTER_DOMAIN, null));
660 
661         SecurityContextHolder.getContext().setAuthentication(auth);
662         try {
663             // test count() and search()
664             Set<String> authRealms = RealmUtils.getEffective(
665                     AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.GROUP_SEARCH),
666                     SyncopeConstants.ROOT_REALM);
667 
668             assertEquals(
669                     1,
670                     searchDAO.count(
671                             realmDAO.getRoot(), true, authRealms, groupDAO.getAllMatchingCond(), AnyTypeKind.GROUP));
672 
673             List<Group> groups = searchDAO.search(
674                     realmDAO.getRoot(),
675                     true,
676                     authRealms,
677                     groupDAO.getAllMatchingCond(),
678                     1,
679                     10,
680                     List.of(),
681                     AnyTypeKind.GROUP);
682             assertEquals(1, groups.size());
683             assertEquals("37d15e4c-cdc1-460b-a591-8505c8133806", groups.get(0).getKey());
684         } finally {
685             SecurityContextHolder.getContext().setAuthentication(null);
686         }
687     }
688 
689     @Test
690     public void changePwdDate() {
691         AnyCond statusCond = new AnyCond(AttrCond.Type.IEQ);
692         statusCond.setSchema("status");
693         statusCond.setExpression("suspended");
694 
695         AnyCond changePwdDateCond = new AnyCond(AttrCond.Type.ISNULL);
696         changePwdDateCond.setSchema("changePwdDate");
697 
698         SearchCond cond = SearchCond.getAnd(SearchCond.getNotLeaf(statusCond), SearchCond.getLeaf(changePwdDateCond));
699         assertTrue(cond.isValid());
700 
701         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
702         assertNotNull(users);
703         assertEquals(5, users.size());
704     }
705 
706     @Test
707     public void issue202() {
708         ResourceCond ws2 = new ResourceCond();
709         ws2.setResource("ws-target-resource-2");
710 
711         ResourceCond ws1 = new ResourceCond();
712         ws1.setResource("ws-target-resource-list-mappings-1");
713 
714         SearchCond searchCondition =
715                 SearchCond.getAnd(SearchCond.getNotLeaf(ws2), SearchCond.getNotLeaf(ws1));
716         assertTrue(searchCondition.isValid());
717 
718         List<User> users = searchDAO.search(searchCondition, AnyTypeKind.USER);
719         assertNotNull(users);
720         assertEquals(2, users.size());
721         assertTrue(users.stream().anyMatch(user -> "c9b2dec2-00a7-4855-97c0-d854842b4b24".equals(user.getKey())));
722     }
723 
724     @Test
725     public void issue242() {
726         AnyCond cond = new AnyCond(AttrCond.Type.LIKE);
727         cond.setSchema("key");
728         cond.setExpression("test%");
729 
730         SearchCond searchCondition = SearchCond.getLeaf(cond);
731         assertTrue(searchCondition.isValid());
732 
733         List<User> users = searchDAO.search(searchCondition, AnyTypeKind.USER);
734         assertNotNull(users);
735         assertTrue(users.isEmpty());
736     }
737 
738     @Test
739     public void issueSYNCOPE46() {
740         AnyCond cond = new AnyCond(AttrCond.Type.LIKE);
741         cond.setSchema("username");
742         cond.setExpression("%ossin%");
743 
744         SearchCond searchCondition = SearchCond.getLeaf(cond);
745         assertTrue(searchCondition.isValid());
746 
747         List<User> users = searchDAO.search(searchCondition, AnyTypeKind.USER);
748         assertNotNull(users);
749         assertEquals(1, users.size());
750     }
751 
752     @Test
753     public void issueSYNCOPE433() {
754         AttrCond isNullCond = new AttrCond(AttrCond.Type.ISNULL);
755         isNullCond.setSchema("loginDate");
756 
757         AnyCond likeCond = new AnyCond(AttrCond.Type.LIKE);
758         likeCond.setSchema("username");
759         likeCond.setExpression("%ossin%");
760 
761         SearchCond searchCond = SearchCond.getOr(
762                 SearchCond.getLeaf(isNullCond), SearchCond.getLeaf(likeCond));
763 
764         int count = searchDAO.count(
765                 realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, searchCond, AnyTypeKind.USER);
766         assertTrue(count > 0);
767     }
768 
769     @Test
770     public void issueSYNCOPE929() {
771         AttrCond rossiniCond = new AttrCond(AttrCond.Type.EQ);
772         rossiniCond.setSchema("surname");
773         rossiniCond.setExpression("Rossini");
774 
775         AttrCond genderCond = new AttrCond(AttrCond.Type.EQ);
776         genderCond.setSchema("gender");
777         genderCond.setExpression("M");
778 
779         SearchCond orCond = SearchCond.getOr(SearchCond.getLeaf(rossiniCond), SearchCond.getLeaf(genderCond));
780 
781         AttrCond belliniCond = new AttrCond(AttrCond.Type.EQ);
782         belliniCond.setSchema("surname");
783         belliniCond.setExpression("Bellini");
784 
785         SearchCond searchCond = SearchCond.getAnd(orCond, SearchCond.getLeaf(belliniCond));
786 
787         List<User> users = searchDAO.search(searchCond, AnyTypeKind.USER);
788         assertNotNull(users);
789         assertEquals(1, users.size());
790     }
791 
792     @Test
793     public void issueSYNCOPE980() {
794         AnyType service = entityFactory.newEntity(AnyType.class);
795         service.setKey("SERVICE");
796         service.setKind(AnyTypeKind.ANY_OBJECT);
797         service = anyTypeDAO.save(service);
798 
799         Group citizen = groupDAO.findByName("citizen");
800         assertNotNull(citizen);
801 
802         AnyObject anyObject = entityFactory.newEntity(AnyObject.class);
803         anyObject.setName("one");
804         anyObject.setType(service);
805         anyObject.setRealm(realmDAO.findByFullPath(SyncopeConstants.ROOT_REALM));
806 
807         AMembership membership = entityFactory.newEntity(AMembership.class);
808         membership.setRightEnd(citizen);
809         membership.setLeftEnd(anyObject);
810 
811         anyObject.add(membership);
812         anyObjectDAO.save(anyObject);
813 
814         anyObject = anyObjectDAO.find("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
815         membership = entityFactory.newEntity(AMembership.class);
816         membership.setRightEnd(citizen);
817         membership.setLeftEnd(anyObject);
818         anyObject.add(membership);
819         anyObjectDAO.save(anyObject);
820 
821         entityManager().flush();
822 
823         MembershipCond groupCond = new MembershipCond();
824         groupCond.setGroup("citizen");
825 
826         SearchCond searchCondition = SearchCond.getLeaf(groupCond);
827 
828         List<AnyObject> matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
829         assertEquals(2, matching.size());
830 
831         AnyTypeCond anyTypeCond = new AnyTypeCond();
832         anyTypeCond.setAnyTypeKey(service.getKey());
833 
834         searchCondition = SearchCond.getAnd(SearchCond.getLeaf(groupCond), SearchCond.getLeaf(anyTypeCond));
835 
836         matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
837         assertEquals(1, matching.size());
838     }
839 
840     @Test
841     public void issueSYNCOPE983() {
842         AttrCond fullnameLeafCond = new AttrCond(AttrCond.Type.LIKE);
843         fullnameLeafCond.setSchema("surname");
844         fullnameLeafCond.setExpression("%o%");
845 
846         List<OrderByClause> orderByClauses = new ArrayList<>();
847         OrderByClause orderByClause = new OrderByClause();
848         orderByClause.setField("surname");
849         orderByClause.setDirection(OrderByClause.Direction.ASC);
850         orderByClauses.add(orderByClause);
851         orderByClause = new OrderByClause();
852         orderByClause.setField("username");
853         orderByClause.setDirection(OrderByClause.Direction.DESC);
854         orderByClauses.add(orderByClause);
855 
856         List<User> users = searchDAO.search(
857                 realmDAO.getRoot(),
858                 true,
859                 SyncopeConstants.FULL_ADMIN_REALMS,
860                 SearchCond.getLeaf(fullnameLeafCond),
861                 -1,
862                 -1,
863                 orderByClauses,
864                 AnyTypeKind.USER);
865         assertFalse(users.isEmpty());
866     }
867 
868     @Test
869     public void issueSYNCOPE1416() {
870         AttrCond idLeftCond = new AttrCond(AttrCond.Type.ISNOTNULL);
871         idLeftCond.setSchema("surname");
872 
873         AttrCond idRightCond = new AttrCond(AttrCond.Type.ISNOTNULL);
874         idRightCond.setSchema("firstname");
875 
876         SearchCond searchCondition = SearchCond.getAnd(SearchCond.getLeaf(idLeftCond), SearchCond.getLeaf(idRightCond));
877 
878         List<OrderByClause> orderByClauses = new ArrayList<>();
879         OrderByClause orderByClause = new OrderByClause();
880         orderByClause.setField("ctype");
881         orderByClause.setDirection(OrderByClause.Direction.ASC);
882         orderByClauses.add(orderByClause);
883 
884         List<User> users = searchDAO.search(searchCondition, orderByClauses, AnyTypeKind.USER);
885         assertEquals(searchDAO.count(
886                 realmDAO.getRoot(), true, SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, AnyTypeKind.USER),
887                 users.size());
888 
889         // search by attribute with unique constraint
890         AttrCond fullnameCond = new AttrCond(AttrCond.Type.ISNOTNULL);
891         fullnameCond.setSchema("fullname");
892 
893         SearchCond cond = SearchCond.getLeaf(fullnameCond);
894         assertTrue(cond.isValid());
895 
896         users = searchDAO.search(cond, AnyTypeKind.USER);
897         assertEquals(5, users.size());
898 
899         fullnameCond = new AttrCond(AttrCond.Type.ISNULL);
900         fullnameCond.setSchema("fullname");
901 
902         cond = SearchCond.getLeaf(fullnameCond);
903         assertTrue(cond.isValid());
904 
905         users = searchDAO.search(cond, AnyTypeKind.USER);
906         assertTrue(users.isEmpty());
907     }
908 
909     @Test
910     public void issueSYNCOPE1419() {
911         AttrCond loginDateCond = new AttrCond(AttrCond.Type.EQ);
912         loginDateCond.setSchema("loginDate");
913         loginDateCond.setExpression(LOGIN_DATE_VALUE);
914 
915         SearchCond cond = SearchCond.getNotLeaf(loginDateCond);
916         assertTrue(cond.isValid());
917 
918         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
919         assertNotNull(users);
920         assertEquals(4, users.size());
921     }
922 }