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.outer;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  import static org.junit.jupiter.api.Assertions.fail;
25  
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.List;
29  import java.util.Set;
30  import org.apache.syncope.common.lib.SyncopeClientException;
31  import org.apache.syncope.common.lib.SyncopeConstants;
32  import org.apache.syncope.common.lib.types.AnyTypeKind;
33  import org.apache.syncope.common.lib.types.ClientExceptionType;
34  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
35  import org.apache.syncope.core.persistence.api.attrvalue.validation.PlainAttrValidationManager;
36  import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
37  import org.apache.syncope.core.persistence.api.dao.GroupDAO;
38  import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
39  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
40  import org.apache.syncope.core.persistence.api.dao.RoleDAO;
41  import org.apache.syncope.core.persistence.api.dao.UserDAO;
42  import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
43  import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
44  import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
45  import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
46  import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
47  import org.apache.syncope.core.persistence.api.entity.Role;
48  import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
49  import org.apache.syncope.core.persistence.api.entity.group.Group;
50  import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership;
51  import org.apache.syncope.core.persistence.api.entity.user.UMembership;
52  import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
53  import org.apache.syncope.core.persistence.api.entity.user.User;
54  import org.apache.syncope.core.persistence.jpa.AbstractTest;
55  import org.apache.syncope.core.provisioning.api.utils.RealmUtils;
56  import org.junit.jupiter.api.Test;
57  import org.springframework.beans.factory.annotation.Autowired;
58  import org.springframework.transaction.annotation.Transactional;
59  
60  @Transactional("Master")
61  public class AnySearchTest extends AbstractTest {
62  
63      @Autowired
64      private UserDAO userDAO;
65  
66      @Autowired
67      private GroupDAO groupDAO;
68  
69      @Autowired
70      private AnySearchDAO searchDAO;
71  
72      @Autowired
73      private RealmDAO realmDAO;
74  
75      @Autowired
76      private RoleDAO roleDAO;
77  
78      @Autowired
79      private PlainSchemaDAO plainSchemaDAO;
80  
81      @Autowired
82      private PlainAttrValidationManager validator;
83  
84      @Test
85      public void searchByDynMembership() {
86          // 1. create role with dynamic membership
87          Role role = entityFactory.newEntity(Role.class);
88          role.setKey("new");
89          role.add(realmDAO.getRoot());
90          role.add(realmDAO.findByFullPath("/even/two"));
91          role.getEntitlements().add(IdRepoEntitlement.AUDIT_LIST);
92          role.getEntitlements().add(IdRepoEntitlement.AUDIT_SET);
93  
94          DynRoleMembership dynMembership = entityFactory.newEntity(DynRoleMembership.class);
95          dynMembership.setFIQLCond("cool==true");
96          dynMembership.setRole(role);
97  
98          role.setDynMembership(dynMembership);
99  
100         role = roleDAO.saveAndRefreshDynMemberships(role);
101         assertNotNull(role);
102 
103         entityManager().flush();
104 
105         // 2. search user by this dynamic role
106         RoleCond roleCond = new RoleCond();
107         roleCond.setRole(role.getKey());
108 
109         List<User> users = searchDAO.search(SearchCond.getLeaf(roleCond), AnyTypeKind.USER);
110         assertNotNull(users);
111         assertEquals(1, users.size());
112         assertEquals("c9b2dec2-00a7-4855-97c0-d854842b4b24", users.get(0).getKey());
113     }
114 
115     @Test
116     public void searchAsGroupOwner() {
117         // 1. define rossini as member of director
118         User rossini = userDAO.findByUsername("rossini");
119         assertNotNull(rossini);
120 
121         Group group = groupDAO.findByName("director");
122         assertNotNull(group);
123 
124         UMembership membership = entityFactory.newEntity(UMembership.class);
125         membership.setLeftEnd(rossini);
126         membership.setRightEnd(group);
127         rossini.add(membership);
128 
129         userDAO.save(rossini);
130         assertNotNull(rossini);
131 
132         entityManager().flush();
133 
134         // 2. search all users with root realm entitlements: all users are returned, including rossini
135         AnyCond anyCond = new AnyCond(AttrCond.Type.ISNOTNULL);
136         anyCond.setSchema("id");
137 
138         List<User> users = searchDAO.search(
139                 realmDAO.getRoot(), true,
140                 Set.of(SyncopeConstants.ROOT_REALM),
141                 SearchCond.getLeaf(anyCond), 1, 100, Collections.emptyList(), AnyTypeKind.USER);
142         assertNotNull(users);
143         assertTrue(users.stream().anyMatch(user -> rossini.getKey().equals(user.getKey())));
144 
145         // 3. search all users with director owner's entitlements: only rossini is returned
146         users = searchDAO.search(
147                 group.getRealm(), true,
148                 Set.of(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey())),
149                 SearchCond.getLeaf(anyCond), 1, 100, Collections.emptyList(), AnyTypeKind.USER);
150         assertNotNull(users);
151         assertEquals(1, users.size());
152         assertEquals(rossini.getKey(), users.get(0).getKey());
153     }
154 
155     @Test
156     public void issueSYNCOPE95() {
157         groupDAO.findAll(1, 100).forEach(group -> groupDAO.delete(group.getKey()));
158         entityManager().flush();
159 
160         AttrCond coolLeafCond = new AttrCond(AttrCond.Type.EQ);
161         coolLeafCond.setSchema("cool");
162         coolLeafCond.setExpression("true");
163 
164         SearchCond cond = SearchCond.getLeaf(coolLeafCond);
165         assertTrue(cond.isValid());
166 
167         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
168         assertNotNull(users);
169         assertEquals(1, users.size());
170 
171         assertEquals("c9b2dec2-00a7-4855-97c0-d854842b4b24", users.get(0).getKey());
172     }
173 
174     @Test
175     public void issueSYNCOPE1417() {
176         AnyCond usernameLeafCond = new AnyCond(AnyCond.Type.EQ);
177         usernameLeafCond.setSchema("username");
178         usernameLeafCond.setExpression("rossini");
179         AttrCond idRightCond = new AttrCond(AttrCond.Type.LIKE);
180         idRightCond.setSchema("fullname");
181         idRightCond.setExpression("Giuseppe V%");
182         SearchCond searchCondition = SearchCond.getOr(
183                 SearchCond.getLeaf(usernameLeafCond), SearchCond.getLeaf(idRightCond));
184 
185         List<OrderByClause> orderByClauses = new ArrayList<>();
186         OrderByClause orderByClause = new OrderByClause();
187         orderByClause.setField("surname");
188         orderByClause.setDirection(OrderByClause.Direction.DESC);
189         orderByClauses.add(orderByClause);
190         orderByClause = new OrderByClause();
191         orderByClause.setField("firstname");
192         orderByClause.setDirection(OrderByClause.Direction.ASC);
193         orderByClauses.add(orderByClause);
194 
195         try {
196             searchDAO.search(searchCondition, orderByClauses, AnyTypeKind.USER);
197             fail();
198         } catch (SyncopeClientException e) {
199             assertEquals(ClientExceptionType.InvalidSearchParameters, e.getType());
200         }
201     }
202 
203     @Test
204     public void issueSYNCOPE1512() {
205         Group group = groupDAO.findByName("root");
206         assertNotNull(group);
207 
208         // non unique
209         GPlainAttr title = entityFactory.newEntity(GPlainAttr.class);
210         title.setOwner(group);
211         title.setSchema(plainSchemaDAO.find("title"));
212         title.add(validator, "syncope's group", anyUtilsFactory.getInstance(AnyTypeKind.GROUP));
213         group.add(title);
214 
215         // unique
216         GPlainAttr originalName = entityFactory.newEntity(GPlainAttr.class);
217         originalName.setOwner(group);
218         originalName.setSchema(plainSchemaDAO.find("originalName"));
219         originalName.add(validator, "syncope's group", anyUtilsFactory.getInstance(AnyTypeKind.GROUP));
220         group.add(originalName);
221 
222         groupDAO.save(group);
223 
224         entityManager().flush();
225 
226         AttrCond titleCond = new AttrCond(AttrCond.Type.EQ);
227         titleCond.setSchema("title");
228         titleCond.setExpression("syncope's group");
229 
230         List<Group> matching = searchDAO.search(SearchCond.getLeaf(titleCond), AnyTypeKind.GROUP);
231         assertEquals(1, matching.size());
232         assertEquals(group.getKey(), matching.get(0).getKey());
233 
234         AttrCond originalNameCond = new AttrCond(AttrCond.Type.EQ);
235         originalNameCond.setSchema("originalName");
236         originalNameCond.setExpression("syncope's group");
237 
238         matching = searchDAO.search(SearchCond.getLeaf(originalNameCond), AnyTypeKind.GROUP);
239         assertEquals(1, matching.size());
240         assertEquals(group.getKey(), matching.get(0).getKey());
241     }
242 
243     @Test
244     public void issueSYNCOPE1790() {
245         // 0. search by email
246         AttrCond emailCond = new AttrCond(AttrCond.Type.EQ);
247         emailCond.setSchema("email");
248         emailCond.setExpression("verdi@syncope.org");
249 
250         SearchCond cond = SearchCond.getLeaf(emailCond);
251         assertTrue(cond.isValid());
252 
253         List<User> users = searchDAO.search(cond, AnyTypeKind.USER);
254         assertNotNull(users);
255         assertEquals(1, users.size());
256         assertEquals("verdi", users.get(0).getUsername());
257 
258         // 1. set rossini's email address for conditions as per SYNCOPE-1790
259         User rossini = userDAO.findByUsername("rossini");
260         assertNotNull(rossini);
261 
262         UPlainAttr mail = entityFactory.newEntity(UPlainAttr.class);
263         mail.setOwner(rossini);
264         mail.setSchema(plainSchemaDAO.find("email"));
265         mail.add(validator, "bisverdi@syncope.org", anyUtilsFactory.getInstance(AnyTypeKind.USER));
266         rossini.add(mail);
267 
268         userDAO.save(rossini);
269         entityManager().flush();
270 
271         rossini = userDAO.findByUsername("rossini");
272         assertEquals(
273                 "bisverdi@syncope.org",
274                 rossini.getPlainAttr("email").map(a -> a.getValuesAsStrings().get(0)).orElseThrow());
275 
276         // 2. search again
277         users = searchDAO.search(cond, AnyTypeKind.USER);
278         assertNotNull(users);
279         assertEquals(1, users.size());
280         assertEquals("verdi", users.get(0).getUsername());
281     }
282 }