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.fit.core;
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.assertNotEquals;
24  import static org.junit.jupiter.api.Assertions.assertNotNull;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  import static org.junit.jupiter.api.Assertions.fail;
27  
28  import java.util.ArrayList;
29  import java.util.List;
30  import java.util.Set;
31  import java.util.stream.Collectors;
32  import java.util.stream.Stream;
33  import javax.ws.rs.NotFoundException;
34  import javax.ws.rs.core.Response;
35  import org.apache.commons.lang3.RandomStringUtils;
36  import org.apache.syncope.client.lib.SyncopeClient;
37  import org.apache.syncope.client.lib.batch.BatchRequest;
38  import org.apache.syncope.common.lib.Attr;
39  import org.apache.syncope.common.lib.SyncopeClientException;
40  import org.apache.syncope.common.lib.SyncopeConstants;
41  import org.apache.syncope.common.lib.request.AnyObjectCR;
42  import org.apache.syncope.common.lib.request.AnyObjectUR;
43  import org.apache.syncope.common.lib.request.AttrPatch;
44  import org.apache.syncope.common.lib.request.GroupCR;
45  import org.apache.syncope.common.lib.request.MembershipUR;
46  import org.apache.syncope.common.lib.request.UserCR;
47  import org.apache.syncope.common.lib.request.UserUR;
48  import org.apache.syncope.common.lib.to.AnyObjectTO;
49  import org.apache.syncope.common.lib.to.AnyTypeTO;
50  import org.apache.syncope.common.lib.to.GroupTO;
51  import org.apache.syncope.common.lib.to.MembershipTO;
52  import org.apache.syncope.common.lib.to.PagedConnObjectResult;
53  import org.apache.syncope.common.lib.to.PagedResult;
54  import org.apache.syncope.common.lib.to.RealmTO;
55  import org.apache.syncope.common.lib.to.RoleTO;
56  import org.apache.syncope.common.lib.to.UserTO;
57  import org.apache.syncope.common.lib.types.AnyTypeKind;
58  import org.apache.syncope.common.lib.types.ClientExceptionType;
59  import org.apache.syncope.common.rest.api.RESTHeaders;
60  import org.apache.syncope.common.rest.api.beans.AnyQuery;
61  import org.apache.syncope.common.rest.api.beans.ConnObjectTOQuery;
62  import org.apache.syncope.common.rest.api.service.GroupService;
63  import org.apache.syncope.common.rest.api.service.RoleService;
64  import org.apache.syncope.fit.AbstractITCase;
65  import org.identityconnectors.framework.common.objects.Name;
66  import org.junit.jupiter.api.Assertions;
67  import org.junit.jupiter.api.Test;
68  
69  public class SearchITCase extends AbstractITCase {
70  
71      @Test
72      public void searchUser() {
73          // LIKE
74          PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
75                  new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
76                          fiql(SyncopeClient.getUserSearchConditionBuilder().
77                                  is("fullname").equalTo("*o*").and("fullname").equalTo("*i*").query()).build());
78          assertNotNull(matchingUsers);
79          assertFalse(matchingUsers.getResult().isEmpty());
80          matchingUsers.getResult().stream().forEach(Assertions::assertNotNull);
81  
82          // ISNULL
83          matchingUsers = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
84                  fiql(SyncopeClient.getUserSearchConditionBuilder().isNull("loginDate").query()).build());
85          assertNotNull(matchingUsers);
86          assertFalse(matchingUsers.getResult().isEmpty());
87      }
88  
89      @Test
90      public void searchUserIgnoreCase() {
91          PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
92                  new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
93                          fiql(SyncopeClient.getUserSearchConditionBuilder().
94                                  is("username").equalToIgnoreCase("RoSsINI").and("key").lessThan(2).query()).build());
95          assertNotNull(matchingUsers);
96          assertEquals(1, matchingUsers.getResult().size());
97          assertEquals("rossini", matchingUsers.getResult().get(0).getUsername());
98  
99          matchingUsers = USER_SERVICE.search(
100                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
101                         fiql("fullname=~*oSsINi").page(1).size(2).build());
102         assertNotNull(matchingUsers);
103         assertEquals(1, matchingUsers.getResult().size());
104         assertEquals("rossini", matchingUsers.getResult().get(0).getUsername());
105 
106         matchingUsers = USER_SERVICE.search(
107                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
108                         fiql("fullname=~*ino*rossini*").page(1).size(2).build());
109         assertNotNull(matchingUsers);
110         assertEquals(1, matchingUsers.getResult().size());
111         assertEquals("rossini", matchingUsers.getResult().get(0).getUsername());
112     }
113 
114     @Test
115     public void searchByUsernameAndKey() {
116         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
117                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
118                         fiql(SyncopeClient.getUserSearchConditionBuilder().
119                                 is("username").equalTo("rossini").and("key").lessThan(2).query()).build());
120         assertNotNull(matchingUsers);
121         assertEquals(1, matchingUsers.getResult().size());
122         assertEquals("rossini", matchingUsers.getResult().get(0).getUsername());
123     }
124 
125     @Test
126     public void searchByGroupNameAndKey() {
127         PagedResult<GroupTO> groups = GROUP_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
128                 fiql(SyncopeClient.getGroupSearchConditionBuilder().
129                         is("name").equalTo("root").and("key").equalTo("37d15e4c-cdc1-460b-a591-8505c8133806").
130                         query()).build());
131         assertNotNull(groups);
132         assertEquals(1, groups.getResult().size());
133         assertEquals("root", groups.getResult().iterator().next().getName());
134         assertEquals("37d15e4c-cdc1-460b-a591-8505c8133806", groups.getResult().iterator().next().getKey());
135     }
136 
137     @Test
138     public void searchByGroup() {
139         PagedResult<UserTO> matchingChild = USER_SERVICE.search(
140                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
141                         fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups("child").query()).
142                         build());
143         assertTrue(matchingChild.getResult().stream().anyMatch(user -> "verdi".equals(user.getUsername())));
144 
145         PagedResult<UserTO> matchingOtherChild = USER_SERVICE.search(
146                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
147                         fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups("otherchild").query()).
148                         build());
149         assertTrue(matchingOtherChild.getResult().stream().anyMatch(user -> "rossini".equals(user.getUsername())));
150 
151         Set<String> union = Stream.concat(
152                 matchingChild.getResult().stream().map(UserTO::getUsername),
153                 matchingOtherChild.getResult().stream().map(UserTO::getUsername)).
154                 collect(Collectors.toSet());
155 
156         PagedResult<UserTO> matchingStar = USER_SERVICE.search(
157                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
158                         fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups("*child").query()).
159                         build());
160         assertTrue(matchingStar.getResult().stream().anyMatch(user -> "verdi".equals(user.getUsername())));
161         assertTrue(matchingStar.getResult().stream().anyMatch(user -> "rossini".equals(user.getUsername())));
162         assertEquals(union, matchingStar.getResult().stream().map(UserTO::getUsername).collect(Collectors.toSet()));
163 
164         matchingStar = USER_SERVICE.search(
165                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).recursive(false).
166                         fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups("*child").query()).
167                         build());
168         assertTrue(matchingStar.getResult().stream().anyMatch(user -> "verdi".equals(user.getUsername())));
169         assertTrue(matchingStar.getResult().stream().noneMatch(user -> "rossini".equals(user.getUsername())));
170     }
171 
172     @Test
173     public void searchByDynGroup() {
174         GroupCR groupCR = GroupITCase.getBasicSample("dynMembership");
175         groupCR.setUDynMembershipCond("cool==true");
176         GroupTO group = createGroup(groupCR).getEntity();
177         assertNotNull(group);
178 
179         if (IS_EXT_SEARCH_ENABLED) {
180             try {
181                 Thread.sleep(2000);
182             } catch (InterruptedException ex) {
183                 // ignore
184             }
185         }
186 
187         PagedResult<GroupTO> matchingGroups = GROUP_SERVICE.search(
188                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
189                         fiql(SyncopeClient.getGroupSearchConditionBuilder().
190                                 is("creationContext").equalTo("REST").query()).
191                         build());
192         assertNotNull(matchingGroups);
193         assertTrue(matchingGroups.getTotalCount() > 0);
194 
195         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
196                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
197                         fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups(group.getKey()).query()).
198                         build());
199         assertNotNull(matchingUsers);
200         assertFalse(matchingUsers.getResult().isEmpty());
201         assertTrue(matchingUsers.getResult().stream().
202                 anyMatch(user -> "c9b2dec2-00a7-4855-97c0-d854842b4b24".equals(user.getKey())));
203     }
204 
205     @Test
206     public void searchByRole() {
207         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
208                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
209                         fiql(SyncopeClient.getUserSearchConditionBuilder().inRoles("Other").query()).
210                         build());
211         assertNotNull(matchingUsers);
212         assertFalse(matchingUsers.getResult().isEmpty());
213 
214         assertTrue(matchingUsers.getResult().stream().anyMatch(user -> "rossini".equals(user.getUsername())));
215     }
216 
217     @Test
218     public void searchByPrivilege() {
219         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
220                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
221                         fiql(SyncopeClient.getUserSearchConditionBuilder().withPrivileges("postMighty").query()).
222                         build());
223         assertNotNull(matchingUsers);
224         assertFalse(matchingUsers.getResult().isEmpty());
225 
226         assertTrue(matchingUsers.getResult().stream().anyMatch(user -> "rossini".equals(user.getUsername())));
227     }
228 
229     @Test
230     public void searchByDynRole() {
231         RoleTO role = RoleITCase.getSampleRoleTO("dynMembership");
232         role.setDynMembershipCond("cool==true");
233         Response response = ROLE_SERVICE.create(role);
234         role = getObject(response.getLocation(), RoleService.class, RoleTO.class);
235         assertNotNull(role);
236 
237         if (IS_EXT_SEARCH_ENABLED) {
238             try {
239                 Thread.sleep(2000);
240             } catch (InterruptedException ex) {
241                 // ignore
242             }
243         }
244 
245         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
246                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
247                         fiql(SyncopeClient.getUserSearchConditionBuilder().inRoles(role.getKey()).query()).
248                         build());
249         assertNotNull(matchingUsers);
250         assertFalse(matchingUsers.getResult().isEmpty());
251 
252         assertTrue(matchingUsers.getResult().stream().
253                 anyMatch(user -> "c9b2dec2-00a7-4855-97c0-d854842b4b24".equals(user.getKey())));
254     }
255 
256     @Test
257     public void searchByAuxClass() {
258         PagedResult<GroupTO> matchingGroups = GROUP_SERVICE.search(
259                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
260                         fiql(SyncopeClient.getGroupSearchConditionBuilder().
261                                 hasAuxClasses("csv").query()).
262                         build());
263         assertNotNull(matchingGroups);
264         assertFalse(matchingGroups.getResult().isEmpty());
265 
266         assertTrue(matchingGroups.getResult().stream().
267                 anyMatch(group -> "0626100b-a4ba-4e00-9971-86fad52a6216".equals(group.getKey())));
268         assertTrue(matchingGroups.getResult().stream().
269                 anyMatch(group -> "ba9ed509-b1f5-48ab-a334-c8530a6422dc".equals(group.getKey())));
270     }
271 
272     @Test
273     public void searchByResource() {
274         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
275                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
276                         fiql(SyncopeClient.getUserSearchConditionBuilder().
277                                 hasResources(RESOURCE_NAME_MAPPINGS2).query()).
278                         build());
279         assertNotNull(matchingUsers);
280         assertFalse(matchingUsers.getResult().isEmpty());
281 
282         assertTrue(matchingUsers.getResult().stream().
283                 anyMatch(user -> "74cd8ece-715a-44a4-a736-e17b46c4e7e6".equals(user.getKey())));
284     }
285 
286     @Test
287     public void paginatedSearch() {
288         // LIKE
289         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
290                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
291                         fiql(SyncopeClient.getUserSearchConditionBuilder().
292                                 is("fullname").equalTo("*o*").and("fullname").equalTo("*i*").query()).page(1).size(2).
293                         build());
294         assertNotNull(matchingUsers);
295 
296         assertFalse(matchingUsers.getResult().isEmpty());
297         for (UserTO user : matchingUsers.getResult()) {
298             assertNotNull(user);
299         }
300 
301         // ISNULL
302         matchingUsers = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
303                 fiql(SyncopeClient.getUserSearchConditionBuilder().isNull("loginDate").query()).page(2).size(2).
304                 build());
305         assertNotNull(matchingUsers);
306         assertEquals(2, matchingUsers.getPage());
307         assertFalse(matchingUsers.getResult().isEmpty());
308     }
309 
310     @Test
311     public void searchByRealm() {
312         PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
313                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("realm").
314                         equalTo("c5b75db1-fce7-470f-b780-3b9934d82a9d").query()).build());
315         assertTrue(users.getResult().stream().anyMatch(user -> "rossini".equals(user.getUsername())));
316 
317         users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
318                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("realm").equalTo("/even").query()).build());
319         assertTrue(users.getResult().stream().anyMatch(user -> "rossini".equals(user.getUsername())));
320     }
321 
322     @Test
323     public void searchByBooleanAnyCond() {
324         PagedResult<GroupTO> groups = GROUP_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
325                 fiql(SyncopeClient.getGroupSearchConditionBuilder().is("show").equalTo("true").query()).build());
326         assertNotNull(groups);
327         assertFalse(groups.getResult().isEmpty());
328     }
329 
330     @Test
331     public void searchByDate() {
332         if (IS_EXT_SEARCH_ENABLED) {
333             try {
334                 Thread.sleep(2000);
335             } catch (InterruptedException ex) {
336                 // ignore
337             }
338         }
339 
340         PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
341                 fiql(SyncopeClient.getUserSearchConditionBuilder().
342                         is("lastLoginDate").lexicalNotBefore("2016-03-02 15:21:22").
343                         and("username").equalTo("bellini").query()).
344                 build());
345         assertNotNull(users);
346         assertEquals(1, users.getTotalCount());
347         assertEquals(1, users.getResult().size());
348 
349         // SYNCOPE-1321
350         PagedResult<UserTO> issueSYNCOPE1321 = USER_SERVICE.search(new AnyQuery.Builder().
351                 realm(SyncopeConstants.ROOT_REALM).
352                 fiql(SyncopeClient.getUserSearchConditionBuilder().
353                         is("lastLoginDate").lexicalNotBefore("2016-03-02T15:21:22+0300").
354                         and("username").equalTo("bellini").query()).
355                 build());
356         assertEquals(users, issueSYNCOPE1321);
357     }
358 
359     @Test
360     public void searchByRelationshipAnyCond() {
361         PagedResult<GroupTO> groups = GROUP_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
362                 fiql(SyncopeClient.getGroupSearchConditionBuilder().
363                         is("userOwner").equalTo("823074dc-d280-436d-a7dd-07399fae48ec").query()).build());
364         assertNotNull(groups);
365         assertEquals(1, groups.getResult().size());
366         assertEquals(
367                 "ebf97068-aa4b-4a85-9f01-680e8c4cf227",
368                 groups.getResult().iterator().next().getKey());
369     }
370 
371     @Test
372     public void nested() {
373         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
374                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
375                         fiql("((fullname==*o*,fullname==*i*);$resources!=ws-target-resource-1)").
376                         page(1).size(2).build());
377         assertNotNull(matchingUsers);
378 
379         assertFalse(matchingUsers.getResult().isEmpty());
380         matchingUsers.getResult().forEach(Assertions::assertNotNull);
381     }
382 
383     @Test
384     public void searchByType() {
385         PagedResult<AnyObjectTO> matching = ANY_OBJECT_SERVICE.search(new AnyQuery.Builder().realm(
386                 SyncopeConstants.ROOT_REALM).
387                 fiql(SyncopeClient.getAnyObjectSearchConditionBuilder(PRINTER).query()).build());
388         assertNotNull(matching);
389 
390         assertFalse(matching.getResult().isEmpty());
391         for (AnyObjectTO printer : matching.getResult()) {
392             assertNotNull(printer);
393         }
394 
395         matching = ANY_OBJECT_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
396                 fiql(SyncopeClient.getAnyObjectSearchConditionBuilder("UNEXISTING").query()).build());
397         assertNotNull(matching);
398 
399         assertTrue(matching.getResult().isEmpty());
400     }
401 
402     @Test
403     public void searchByRelationship() {
404         PagedResult<AnyObjectTO> anyObjects = ANY_OBJECT_SERVICE.search(new AnyQuery.Builder().realm(
405                 SyncopeConstants.ROOT_REALM).
406                 fiql(SyncopeClient.getAnyObjectSearchConditionBuilder(PRINTER).
407                         inRelationships("Canon MF 8030cn").query()).
408                 build());
409         assertNotNull(anyObjects);
410         assertTrue(anyObjects.getResult().stream().
411                 anyMatch(anyObject -> "fc6dbc3a-6c07-4965-8781-921e7401a4a5".equals(anyObject.getKey())));
412 
413         PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
414                 fiql(SyncopeClient.getUserSearchConditionBuilder().inRelationships("HP LJ 1300n").query()).
415                 build());
416         assertNotNull(users);
417         assertTrue(users.getResult().stream().
418                 anyMatch(user -> "c9b2dec2-00a7-4855-97c0-d854842b4b24".equals(user.getKey())));
419     }
420 
421     @Test
422     public void searchByRelationshipType() {
423         PagedResult<AnyObjectTO> anyObjects = ANY_OBJECT_SERVICE.search(new AnyQuery.Builder().realm(
424                 SyncopeConstants.ROOT_REALM).
425                 fiql(SyncopeClient.getAnyObjectSearchConditionBuilder(PRINTER).
426                         inRelationshipTypes("neighborhood").query()).
427                 build());
428         assertNotNull(anyObjects);
429         assertTrue(anyObjects.getResult().stream().
430                 anyMatch(anyObject -> "fc6dbc3a-6c07-4965-8781-921e7401a4a5".equals(anyObject.getKey())));
431         assertTrue(anyObjects.getResult().stream().
432                 anyMatch(anyObject -> "8559d14d-58c2-46eb-a2d4-a7d35161e8f8".equals(anyObject.getKey())));
433 
434         PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
435                 fiql(SyncopeClient.getUserSearchConditionBuilder().inRelationshipTypes("neighborhood").query()).
436                 build());
437         assertNotNull(users);
438         assertTrue(users.getResult().stream().
439                 anyMatch(user -> "c9b2dec2-00a7-4855-97c0-d854842b4b24".equals(user.getKey())));
440     }
441 
442     @Test
443     public void searchBySecurityAnswer() {
444         String securityAnswer = RandomStringUtils.randomAlphanumeric(10);
445         UserCR userCR = UserITCase.getUniqueSample("securityAnswer@syncope.apache.org");
446         userCR.setSecurityQuestion("887028ea-66fc-41e7-b397-620d7ea6dfbb");
447         userCR.setSecurityAnswer(securityAnswer);
448 
449         UserTO userTO = createUser(userCR).getEntity();
450         assertNotNull(userTO.getSecurityQuestion());
451 
452         try {
453             USER_SERVICE.search(
454                     new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
455                             fiql(SyncopeClient.getUserSearchConditionBuilder().
456                                     is("securityAnswer").equalTo(securityAnswer).query()).build());
457             fail();
458         } catch (SyncopeClientException e) {
459             assertEquals(ClientExceptionType.InvalidSearchParameters, e.getType());
460         }
461     }
462 
463     @Test
464     public void member() {
465         PagedResult<GroupTO> groups = GROUP_SERVICE.search(new AnyQuery.Builder().realm("/").
466                 fiql(SyncopeClient.getGroupSearchConditionBuilder().withMembers("rossini").query()).
467                 build());
468         assertNotNull(groups);
469 
470         assertTrue(groups.getResult().stream().anyMatch(group -> "root".equals(group.getName())));
471         assertTrue(groups.getResult().stream().anyMatch(group -> "otherchild".equals(group.getName())));
472 
473         AnyObjectCR anyObjectCR = new AnyObjectCR.Builder(SyncopeConstants.ROOT_REALM, PRINTER, getUUIDString()).
474                 membership(new MembershipTO.Builder("29f96485-729e-4d31-88a1-6fc60e4677f3").build()).
475                 build();
476         String printer = createAnyObject(anyObjectCR).getEntity().getKey();
477 
478         if (IS_EXT_SEARCH_ENABLED) {
479             try {
480                 Thread.sleep(2000);
481             } catch (InterruptedException ex) {
482                 // ignore
483             }
484         }
485 
486         groups = GROUP_SERVICE.search(new AnyQuery.Builder().realm("/").
487                 fiql(SyncopeClient.getGroupSearchConditionBuilder().withMembers(printer).query()).
488                 build());
489         assertTrue(groups.getResult().stream().
490                 anyMatch(group -> "29f96485-729e-4d31-88a1-6fc60e4677f3".equals(group.getKey())));
491     }
492 
493     @Test
494     public void orderBy() {
495         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
496                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).fiql(
497                         SyncopeClient.getUserSearchConditionBuilder().is("userId").equalTo("*@apache.org").query()).
498                         orderBy(SyncopeClient.getOrderByClauseBuilder().asc("status").desc("firstname").build()).
499                         build());
500         assertNotNull(matchingUsers);
501 
502         assertFalse(matchingUsers.getResult().isEmpty());
503         matchingUsers.getResult().forEach(Assertions::assertNotNull);
504     }
505 
506     @Test
507     public void searchConnObjectsBrowsePagedResult() {
508         List<String> groupKeys = new ArrayList<>();
509         for (int i = 0; i < 11; i++) {
510             GroupCR groupCR = GroupITCase.getSample("group");
511             groupCR.getResources().add(RESOURCE_NAME_LDAP);
512             GroupTO group = createGroup(groupCR).getEntity();
513             groupKeys.add(group.getKey());
514         }
515 
516         ConnObjectTOQuery.Builder builder = new ConnObjectTOQuery.Builder().size(10);
517 
518         try {
519             PagedConnObjectResult matches = RESOURCE_SERVICE.searchConnObjects(
520                     RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), builder.build());
521             assertNotNull(matches);
522 
523             // the test LDAP server sometimes does not return the expected cookie
524             if (matches.getPagedResultsCookie() != null) {
525                 int firstRound = matches.getResult().size();
526 
527                 builder.pagedResultsCookie(matches.getPagedResultsCookie());
528                 matches = RESOURCE_SERVICE.searchConnObjects(
529                         RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), builder.build());
530                 assertNotNull(matches);
531                 int secondRound = matches.getResult().size();
532 
533                 assertTrue(firstRound + secondRound >= groupKeys.size());
534             }
535         } finally {
536             BatchRequest batchRequest = ADMIN_CLIENT.batch();
537             GroupService batchGroupService = batchRequest.getService(GroupService.class);
538             groupKeys.forEach(batchGroupService::delete);
539             batchRequest.commit();
540         }
541     }
542 
543     @Test
544     public void searchConnObjectsWithFilter() {
545         PagedConnObjectResult matches = RESOURCE_SERVICE.searchConnObjects(
546                 RESOURCE_NAME_LDAP,
547                 AnyTypeKind.USER.name(),
548                 new ConnObjectTOQuery.Builder().size(100).fiql(
549                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
550                                 is("givenName").equalTo("pullFromLDAP").query()).build());
551         assertTrue(matches.getResult().stream().
552                 anyMatch(connObject -> connObject.getAttr("givenName").get().getValues().contains("pullFromLDAP")));
553 
554         matches = RESOURCE_SERVICE.searchConnObjects(
555                 RESOURCE_NAME_LDAP,
556                 AnyTypeKind.USER.name(),
557                 new ConnObjectTOQuery.Builder().size(100).fiql(
558                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
559                                 is("mail").equalTo("pullFromLDAP*").query()).build());
560         assertTrue(matches.getResult().stream().
561                 anyMatch(connObject -> connObject.getAttr("cn").get().getValues().contains("pullFromLDAP")));
562 
563         matches = RESOURCE_SERVICE.searchConnObjects(
564                 RESOURCE_NAME_LDAP,
565                 AnyTypeKind.USER.name(),
566                 new ConnObjectTOQuery.Builder().size(100).fiql(
567                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
568                                 is("mail").equalTo("*@syncope.apache.org").query()).build());
569         assertTrue(matches.getResult().stream().
570                 anyMatch(connObject -> connObject.getAttr("cn").get().getValues().contains("pullFromLDAP")));
571 
572         matches = RESOURCE_SERVICE.searchConnObjects(
573                 RESOURCE_NAME_LDAP,
574                 AnyTypeKind.USER.name(),
575                 new ConnObjectTOQuery.Builder().size(100).fiql(
576                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
577                                 is("givenName").equalToIgnoreCase("pullfromldap").query()).build());
578         assertTrue(matches.getResult().stream().
579                 anyMatch(connObject -> connObject.getAttr("givenName").get().getValues().contains("pullFromLDAP")));
580 
581         matches = RESOURCE_SERVICE.searchConnObjects(
582                 RESOURCE_NAME_LDAP,
583                 AnyTypeKind.USER.name(),
584                 new ConnObjectTOQuery.Builder().size(100).fiql(
585                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
586                                 is(Name.NAME).equalTo("uid=pullFromLDAP%252Cou=people%252Co=isp").query()).build());
587         assertTrue(matches.getResult().stream().
588                 anyMatch(connObject -> connObject.getAttr("cn").get().getValues().contains("pullFromLDAP")));
589 
590         matches = RESOURCE_SERVICE.searchConnObjects(
591                 RESOURCE_NAME_LDAP,
592                 AnyTypeKind.USER.name(),
593                 new ConnObjectTOQuery.Builder().size(100).fiql(
594                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
595                                 is("givenName").notEqualTo("pullFromLDAP").query()).build());
596         assertFalse(matches.getResult().stream().
597                 anyMatch(connObject -> connObject.getAttr("givenName").get().getValues().contains("pullFromLDAP")));
598 
599         matches = RESOURCE_SERVICE.searchConnObjects(
600                 RESOURCE_NAME_LDAP,
601                 AnyTypeKind.USER.name(),
602                 new ConnObjectTOQuery.Builder().size(100).fiql(
603                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
604                                 is("homePhone").notNullValue().query()).build());
605         assertTrue(matches.getResult().isEmpty());
606 
607         matches = RESOURCE_SERVICE.searchConnObjects(
608                 RESOURCE_NAME_LDAP,
609                 AnyTypeKind.USER.name(),
610                 new ConnObjectTOQuery.Builder().size(100).fiql(
611                         SyncopeClient.getConnObjectTOFiqlSearchConditionBuilder().
612                                 is("homePhone").nullValue().query()).build());
613         assertTrue(matches.getResult().stream().
614                 anyMatch(connObject -> connObject.getAttr("homePhone").isEmpty()));
615     }
616 
617     @Test
618     public void changePwdDate() {
619         int users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
620                 fiql("status!~suspended;changePwdDate==$null").build()).
621                 getTotalCount();
622         assertTrue(users > 0);
623     }
624 
625     @Test
626     public void issueSYNCOPE768() {
627         int usersWithNullable = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
628                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("ctype").nullValue().query()).build()).
629                 getTotalCount();
630         assertTrue(usersWithNullable > 0);
631 
632         int nonOrdered = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
633                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").notNullValue().query()).build()).
634                 getTotalCount();
635         assertTrue(nonOrdered > 0);
636 
637         int orderedByNullable = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
638                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").notNullValue().query()).
639                 orderBy(SyncopeClient.getOrderByClauseBuilder().asc("ctype").build()).build()).
640                 getTotalCount();
641         assertEquals(nonOrdered, orderedByNullable);
642     }
643 
644     @Test
645     public void issueSYNCOPE929() {
646         PagedResult<UserTO> matchingUsers = USER_SERVICE.search(
647                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
648                         fiql("(surname==Rossini,gender==M);surname==Bellini").build());
649 
650         assertNotNull(matchingUsers);
651 
652         assertFalse(matchingUsers.getResult().isEmpty());
653         matchingUsers.getResult().forEach(user -> assertTrue(user.getUsername().startsWith("bellini")));
654     }
655 
656     @Test
657     public void issueSYNCOPE980() {
658         AnyTypeTO service = new AnyTypeTO();
659         service.setKey("SERVICE");
660         service.setKind(AnyTypeKind.ANY_OBJECT);
661         Response response = ANY_TYPE_SERVICE.create(service);
662         assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatusInfo().getStatusCode());
663 
664         String serviceKey = null;
665         try {
666             AnyObjectCR anyObjectCR = new AnyObjectCR.Builder(SyncopeConstants.ROOT_REALM, service.getKey(), "one").
667                     membership(new MembershipTO.Builder("29f96485-729e-4d31-88a1-6fc60e4677f3").build()).
668                     build();
669             serviceKey = createAnyObject(anyObjectCR).getEntity().getKey();
670 
671             AnyObjectUR anyObjectUR = new AnyObjectUR.Builder("fc6dbc3a-6c07-4965-8781-921e7401a4a5").
672                     membership(new MembershipUR.Builder("29f96485-729e-4d31-88a1-6fc60e4677f3").build()).
673                     build();
674             updateAnyObject(anyObjectUR);
675 
676             if (IS_EXT_SEARCH_ENABLED) {
677                 try {
678                     Thread.sleep(2000);
679                 } catch (InterruptedException ex) {
680                     // ignore
681                 }
682             }
683 
684             PagedResult<AnyObjectTO> matching = ANY_OBJECT_SERVICE.search(new AnyQuery.Builder().fiql(
685                     SyncopeClient.getAnyObjectSearchConditionBuilder(service.getKey()).
686                             inGroups("29f96485-729e-4d31-88a1-6fc60e4677f3").
687                             query()).build());
688             assertEquals(1, matching.getSize());
689             assertEquals(serviceKey, matching.getResult().get(0).getKey());
690         } finally {
691             if (serviceKey != null) {
692                 ANY_OBJECT_SERVICE.delete(serviceKey);
693             }
694             ANY_TYPE_SERVICE.delete(service.getKey());
695         }
696     }
697 
698     @Test
699     public void issueSYNCOPE983() {
700         PagedResult<UserTO> users = USER_SERVICE.search(
701                 new AnyQuery.Builder().
702                         fiql(SyncopeClient.getUserSearchConditionBuilder().is("surname").equalTo("*o*").query()).
703                         orderBy(SyncopeClient.getOrderByClauseBuilder().asc("surname").desc("username").build()).
704                         build());
705         assertNotEquals(0, users.getTotalCount());
706     }
707 
708     @Test
709     public void issueSYNCOPE1223() {
710         UserUR req = new UserUR();
711         req.setKey("vivaldi");
712         req.getPlainAttrs().add(new AttrPatch.Builder(attr("ctype", "ou=sample,o=isp")).build());
713         USER_SERVICE.update(req);
714 
715         if (IS_EXT_SEARCH_ENABLED) {
716             try {
717                 Thread.sleep(2000);
718             } catch (InterruptedException ex) {
719                 // ignore
720             }
721         }
722 
723         try {
724             PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().fiql(
725                     SyncopeClient.getUserSearchConditionBuilder().is("ctype").equalTo("ou=sample%252Co=isp").query()).
726                     build());
727             assertEquals(1, users.getTotalCount());
728             assertEquals("vivaldi", users.getResult().get(0).getUsername());
729         } finally {
730             req.getPlainAttrs().clear();
731             req.getPlainAttrs().add(new AttrPatch.Builder(attr("ctype", "F")).build());
732             USER_SERVICE.update(req);
733         }
734     }
735 
736     @Test
737     public void issueSYNCOPE1304() {
738         PagedResult<GroupTO> groups = GROUP_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
739                 orderBy("userOwner DESC").build());
740         assertNotNull(groups);
741         assertFalse(groups.getResult().isEmpty());
742     }
743 
744     @Test
745     public void issueSYNCOPE1416() {
746         // check the search for attributes of type different from stringvalue
747         PagedResult<UserTO> issueSYNCOPE1416 = USER_SERVICE.search(new AnyQuery.Builder().
748                 realm(SyncopeConstants.ROOT_REALM).
749                 fiql(SyncopeClient.getUserSearchConditionBuilder().
750                         is("loginDate").lexicalNotBefore("2009-05-26").
751                         and("username").equalTo("rossini").query()).
752                 orderBy(SyncopeClient.getOrderByClauseBuilder().asc("loginDate").build()).
753                 build());
754         assertEquals(1, issueSYNCOPE1416.getSize());
755         assertEquals("rossini", issueSYNCOPE1416.getResult().get(0).getUsername());
756 
757         // search by attribute with unique constraint
758         issueSYNCOPE1416 = USER_SERVICE.search(new AnyQuery.Builder().
759                 realm(SyncopeConstants.ROOT_REALM).
760                 fiql(SyncopeClient.getUserSearchConditionBuilder().isNotNull("fullname").query()).
761                 orderBy(SyncopeClient.getOrderByClauseBuilder().asc("loginDate").build()).
762                 build());
763         // some identities could have been imported by pull tasks executions
764         assertTrue(issueSYNCOPE1416.getSize() >= 5);
765 
766         issueSYNCOPE1416 = USER_SERVICE.search(new AnyQuery.Builder().
767                 realm(SyncopeConstants.ROOT_REALM).
768                 fiql(SyncopeClient.getUserSearchConditionBuilder().isNull("fullname").query()).
769                 orderBy(SyncopeClient.getOrderByClauseBuilder().asc("loginDate").build()).
770                 build());
771         assertEquals(0, issueSYNCOPE1416.getSize());
772     }
773 
774     @Test
775     public void issueSYNCOPE1417() {
776         try {
777             USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
778                     fiql(SyncopeClient.getUserSearchConditionBuilder().is("userId").equalTo("*@apache.org").query()).
779                     orderBy(SyncopeClient.getOrderByClauseBuilder().asc("surname").desc("firstname").build()).build());
780             if (!IS_EXT_SEARCH_ENABLED) {
781                 fail();
782             }
783         } catch (SyncopeClientException e) {
784             assertEquals(ClientExceptionType.InvalidSearchParameters, e.getType());
785         }
786     }
787 
788     @Test
789     public void issueSYNCOPE1419() {
790         UserTO rossini = USER_SERVICE.read("rossini");
791         assertNotNull(rossini);
792 
793         UserUR req = new UserUR();
794         req.setKey(rossini.getKey());
795         req.getPlainAttrs().add(new AttrPatch.Builder(
796                 new Attr.Builder("loginDate").value("2009-05-26").build()).build());
797         rossini = updateUser(req).getEntity();
798         assertNotNull(rossini);
799         assertEquals("2009-05-26", rossini.getPlainAttr("loginDate").get().getValues().get(0));
800 
801         PagedResult<UserTO> total = USER_SERVICE.search(
802                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).page(1).size(1).build());
803 
804         PagedResult<UserTO> matching = USER_SERVICE.search(
805                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
806                         fiql(SyncopeClient.getUserSearchConditionBuilder().
807                                 is("loginDate").equalTo("2009-05-26").query()).page(1).size(1).build());
808         assertTrue(matching.getSize() > 0);
809 
810         PagedResult<UserTO> unmatching = USER_SERVICE.search(
811                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
812                         fiql(SyncopeClient.getUserSearchConditionBuilder().
813                                 is("loginDate").notEqualTo("2009-05-26").query()).page(1).size(1).build());
814         assertTrue(unmatching.getSize() > 0);
815 
816         assertEquals(total.getTotalCount(), matching.getTotalCount() + unmatching.getTotalCount());
817     }
818 
819     @Test
820     public void issueSYNCOPE1648() {
821         PagedResult<UserTO> matching = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
822                 fiql(SyncopeClient.getUserSearchConditionBuilder().
823                         is("username").notEqualTo("verdi").query()).build());
824         assertTrue(matching.getResult().stream().noneMatch(user -> "verdi".equals(user.getUsername())));
825     }
826 
827     @Test
828     public void issueSYNCOPE1663() {
829         PagedResult<UserTO> matching1 = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
830                 fiql("lastChangeDate=ge=2022-01-25T17:00:06Z").build());
831         assertNotNull(matching1);
832         assertFalse(matching1.getResult().isEmpty());
833 
834         PagedResult<UserTO> matching2 = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
835                 fiql("lastChangeDate=ge=2022-01-25T17:00:06+0000").build());
836         assertNotNull(matching2);
837         assertFalse(matching2.getResult().isEmpty());
838     }
839 
840     @Test
841     public void issueSYNCOPE1727() {
842         RealmTO realm = new RealmTO();
843         realm.setName("syncope1727");
844 
845         // 1. create Realm
846         Response response = REALM_SERVICE.create("/even/two", realm);
847         realm = getRealm(response.getHeaderString(RESTHeaders.RESOURCE_KEY)).
848                 orElseThrow(() -> new NotFoundException());
849         assertNotNull(realm.getKey());
850         assertEquals("syncope1727", realm.getName());
851         assertEquals("/even/two/syncope1727", realm.getFullPath());
852         assertEquals(realm.getParent(), getRealm("/even/two").get().getKey());
853 
854         // 2. create user
855         UserCR userCR = UserITCase.getUniqueSample("syncope1727@syncope.apache.org");
856         userCR.setRealm(realm.getFullPath());
857         UserTO user = createUser(userCR).getEntity();
858 
859         // 3. search for user
860         if (IS_EXT_SEARCH_ENABLED) {
861             try {
862                 Thread.sleep(2000);
863             } catch (InterruptedException ex) {
864                 // ignore
865             }
866         }
867 
868         PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
869                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("realm").
870                         equalTo(realm.getKey()).query()).build());
871         assertEquals(1, users.getResult().size());
872         assertEquals(user.getKey(), users.getResult().get(0).getKey());
873 
874         // 4. update parent Realm
875         realm.setParent(getRealm("/odd").get().getKey());
876         REALM_SERVICE.update(realm);
877         realm = getRealm("/odd/syncope1727").get();
878 
879         // 5. search again for user
880         users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
881                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("realm").
882                         equalTo(realm.getKey()).query()).build());
883         assertEquals(1, users.getResult().size());
884         assertEquals(user.getKey(), users.getResult().get(0).getKey());
885     }
886 
887     @Test
888     public void issueSYNCOPE1779() {
889         // 1. create user with underscore
890         UserTO userWithUnderscore = createUser(UserITCase.getSample("syncope1779_test@syncope.apache.org")).getEntity();
891         // 2 create second user without underscore
892         createUser(UserITCase.getSample("syncope1779test@syncope.apache.org")).getEntity();
893 
894         // 3. search for user
895         if (IS_EXT_SEARCH_ENABLED) {
896             try {
897                 Thread.sleep(2000);
898             } catch (InterruptedException ex) {
899                 // ignore
900             }
901         }
902 
903         // Search by username
904         PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
905                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("syncope1779_*").
906                         and().is("firstname").equalTo("syncope1779_*").
907                         and().is("userId").equalTo("syncope1779_*").query()).
908                 build());
909         assertEquals(1, users.getResult().size());
910         assertEquals(userWithUnderscore.getKey(), users.getResult().get(0).getKey());
911         // Search also by attribute
912         users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
913                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("syncope1779_*").query()).
914                 build());
915         assertEquals(1, users.getResult().size());
916         assertEquals(userWithUnderscore.getKey(), users.getResult().get(0).getKey());
917         // search for both
918         users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
919                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("syncope1779*").query()).
920                 build());
921         assertEquals(2, users.getResult().size());
922 
923         users.getResult().forEach(u -> USER_SERVICE.delete(u.getKey()));
924 
925         // 4. create any object with underscore
926         AnyObjectTO printer = createAnyObject(
927                 new AnyObjectCR.Builder(SyncopeConstants.ROOT_REALM, PRINTER, "_syncope1779").build()).getEntity();
928 
929         // 5. search for printer
930         if (IS_EXT_SEARCH_ENABLED) {
931             try {
932                 Thread.sleep(2000);
933             } catch (InterruptedException ex) {
934                 // ignore
935             }
936         }
937 
938         PagedResult<AnyObjectTO> printers = ANY_OBJECT_SERVICE.search(
939                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
940                         fiql("$type==PRINTER;name==_syncope1779").
941                         build());
942         assertEquals(1, printers.getResult().size());
943         assertEquals(printer.getKey(), printers.getResult().get(0).getKey());
944 
945         printers.getResult().forEach(u -> ANY_OBJECT_SERVICE.delete(u.getKey()));
946     }
947 
948     @Test
949     public void issueSYNCOPE1790() {
950         // 0. search by email verdi@syncope.org
951         PagedResult<UserTO> users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
952                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("verdi@syncope.org").query()).
953                 build());
954         int before = users.getTotalCount();
955         assertTrue(before > 0);
956         assertFalse(users.getResult().isEmpty());
957         assertTrue(users.getResult().stream().
958                 allMatch(u -> "verdi@syncope.org".equals(u.getPlainAttr("email").orElseThrow().getValues().get(0))));
959 
960         // 1. create user with similar email
961         UserTO user = createUser(UserITCase.getSample("bisverdi@syncope.org")).getEntity();
962         assertNotNull(user);
963 
964         // 2. search again
965         if (IS_EXT_SEARCH_ENABLED) {
966             try {
967                 Thread.sleep(2000);
968             } catch (InterruptedException ex) {
969                 // ignore
970             }
971         }
972 
973         users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
974                 fiql(SyncopeClient.getUserSearchConditionBuilder().is("email").equalTo("verdi@syncope.org").query()).
975                 build());
976         assertEquals(before, users.getTotalCount());
977         assertFalse(users.getResult().isEmpty());
978         assertTrue(users.getResult().stream().
979                 allMatch(u -> "verdi@syncope.org".equals(u.getPlainAttr("email").orElseThrow().getValues().get(0))));
980         assertTrue(users.getResult().stream().noneMatch(u -> user.getKey().equals(u.getKey())));
981     }
982 }