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.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNull;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.time.OffsetDateTime;
28  import java.util.List;
29  import java.util.Objects;
30  import java.util.UUID;
31  import org.apache.syncope.common.lib.types.CipherAlgorithm;
32  import org.apache.syncope.core.persistence.api.attrvalue.validation.PlainAttrValidationManager;
33  import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
34  import org.apache.syncope.core.persistence.api.dao.ApplicationDAO;
35  import org.apache.syncope.core.persistence.api.dao.DelegationDAO;
36  import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
37  import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
38  import org.apache.syncope.core.persistence.api.dao.GroupDAO;
39  import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
40  import org.apache.syncope.core.persistence.api.dao.RelationshipTypeDAO;
41  import org.apache.syncope.core.persistence.api.dao.RoleDAO;
42  import org.apache.syncope.core.persistence.api.dao.UserDAO;
43  import org.apache.syncope.core.persistence.api.entity.AnyUtils;
44  import org.apache.syncope.core.persistence.api.entity.Delegation;
45  import org.apache.syncope.core.persistence.api.entity.DerSchema;
46  import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
47  import org.apache.syncope.core.persistence.api.entity.Role;
48  import org.apache.syncope.core.persistence.api.entity.user.LAPlainAttr;
49  import org.apache.syncope.core.persistence.api.entity.user.LinkedAccount;
50  import org.apache.syncope.core.persistence.api.entity.user.UMembership;
51  import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
52  import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
53  import org.apache.syncope.core.persistence.api.entity.user.URelationship;
54  import org.apache.syncope.core.persistence.api.entity.user.User;
55  import org.apache.syncope.core.persistence.jpa.AbstractTest;
56  import org.apache.syncope.core.persistence.jpa.entity.user.JPALAPlainAttr;
57  import org.apache.syncope.core.persistence.jpa.entity.user.JPALAPlainAttrValue;
58  import org.apache.syncope.core.persistence.jpa.entity.user.JPALinkedAccount;
59  import org.junit.jupiter.api.Tag;
60  import org.junit.jupiter.api.Test;
61  import org.springframework.beans.factory.annotation.Autowired;
62  import org.springframework.transaction.annotation.Transactional;
63  
64  @Transactional("Master")
65  public class UserTest extends AbstractTest {
66  
67      @Autowired
68      private RelationshipTypeDAO relationshipTypeDAO;
69  
70      @Autowired
71      private AnyObjectDAO anyObjectDAO;
72  
73      @Autowired
74      private UserDAO userDAO;
75  
76      @Autowired
77      private GroupDAO groupDAO;
78  
79      @Autowired
80      private PlainSchemaDAO plainSchemaDAO;
81  
82      @Autowired
83      private DerSchemaDAO derSchemaDAO;
84  
85      @Autowired
86      private ExternalResourceDAO resourceDAO;
87  
88      @Autowired
89      private ApplicationDAO applicationDAO;
90  
91      @Autowired
92      private DelegationDAO delegationDAO;
93  
94      @Autowired
95      private RoleDAO roleDAO;
96  
97      @Autowired
98      private PlainAttrValidationManager validator;
99  
100     @Test
101     public void delete() {
102         List<UMembership> memberships = groupDAO.findUMemberships(groupDAO.findByName("managingDirector"));
103         assertFalse(memberships.isEmpty());
104 
105         userDAO.delete("c9b2dec2-00a7-4855-97c0-d854842b4b24");
106 
107         entityManager().flush();
108 
109         assertNull(userDAO.findByUsername("bellini"));
110         assertNull(findPlainAttr(UUID.randomUUID().toString(), UPlainAttr.class));
111         assertNull(findPlainAttrValue(UUID.randomUUID().toString(), UPlainAttrValue.class));
112         assertNotNull(plainSchemaDAO.find("loginDate"));
113 
114         memberships = groupDAO.findUMemberships(groupDAO.findByName("managingDirector"));
115         assertTrue(memberships.isEmpty());
116     }
117 
118     @Test
119     public void ships() {
120         User user = userDAO.findByUsername("bellini");
121         assertNotNull(user);
122         assertEquals(1, user.getMemberships().size());
123         assertEquals("bf825fe1-7320-4a54-bd64-143b5c18ab97", user.getMemberships().get(0).getRightEnd().getKey());
124 
125         user.remove(user.getMemberships().get(0));
126 
127         UMembership newM = entityFactory.newEntity(UMembership.class);
128         newM.setLeftEnd(user);
129         newM.setRightEnd(groupDAO.find("ba9ed509-b1f5-48ab-a334-c8530a6422dc"));
130         user.add(newM);
131 
132         userDAO.save(user);
133 
134         entityManager().flush();
135 
136         user = userDAO.findByUsername("bellini");
137         assertEquals(1, user.getMemberships().size());
138         assertEquals(
139                 "ba9ed509-b1f5-48ab-a334-c8530a6422dc",
140                 user.getMemberships().get(0).getRightEnd().getKey());
141         assertEquals(1, user.getRelationships().size());
142         assertEquals(
143                 "fc6dbc3a-6c07-4965-8781-921e7401a4a5",
144                 user.getRelationships().get(0).getRightEnd().getKey());
145 
146         user.getRelationships().remove(0);
147 
148         URelationship newR = entityFactory.newEntity(URelationship.class);
149         newR.setType(relationshipTypeDAO.find("neighborhood"));
150         newR.setLeftEnd(user);
151         newR.setRightEnd(anyObjectDAO.find("8559d14d-58c2-46eb-a2d4-a7d35161e8f8"));
152         user.add(newR);
153 
154         userDAO.save(user);
155 
156         entityManager().flush();
157 
158         user = userDAO.findByUsername("bellini");
159         assertEquals(1, user.getRelationships().size());
160         assertEquals("8559d14d-58c2-46eb-a2d4-a7d35161e8f8", user.getRelationships().get(0).getRightEnd().getKey());
161     }
162 
163     private LinkedAccount newLinkedAccount(final String connObjectKeyValue) {
164         User user = userDAO.findByUsername("vivaldi");
165         user.getLinkedAccounts().stream().filter(Objects::nonNull).forEach(account -> account.setOwner(null));
166         user.getLinkedAccounts().clear();
167         entityManager().flush();
168 
169         LinkedAccount account = entityFactory.newEntity(LinkedAccount.class);
170         account.setOwner(user);
171         user.add(account);
172 
173         account.setConnObjectKeyValue(connObjectKeyValue);
174         account.setResource(resourceDAO.find("resource-ldap"));
175         account.add(applicationDAO.findPrivilege("getMighty"));
176 
177         account.setUsername(UUID.randomUUID().toString());
178         account.setCipherAlgorithm(CipherAlgorithm.AES);
179         account.setPassword("Password123");
180 
181         AnyUtils anyUtils = anyUtilsFactory.getLinkedAccountInstance();
182         LAPlainAttr attr = anyUtils.newPlainAttr();
183         attr.setOwner(user);
184         attr.setAccount(account);
185         account.add(attr);
186         attr.setSchema(plainSchemaDAO.find("obscure"));
187         attr.add(validator, "testvalue", anyUtils);
188 
189         user = userDAO.save(user);
190         entityManager().flush();
191 
192         assertEquals(1, user.getLinkedAccounts().size());
193 
194         return user.getLinkedAccounts().get(0);
195     }
196 
197     @Test
198     public void findLinkedAccount() {
199         LinkedAccount account = newLinkedAccount("findLinkedAccount");
200         assertNotNull(account.getKey());
201         assertEquals(1, account.getPlainAttrs().size());
202         assertTrue(account.getPlainAttr("obscure").isPresent());
203         assertEquals(account.getOwner(), account.getPlainAttr("obscure").get().getOwner());
204 
205         assertTrue(userDAO.linkedAccountExists(account.getOwner().getKey(), account.getConnObjectKeyValue()));
206 
207         List<LinkedAccount> accounts = userDAO.findLinkedAccountsByResource(resourceDAO.find("resource-ldap"));
208         assertEquals(1, accounts.size());
209         assertEquals(account, accounts.get(0));
210 
211         accounts = userDAO.findLinkedAccountsByPrivilege(applicationDAO.findPrivilege("getMighty"));
212         assertEquals(1, accounts.size());
213         assertEquals(account, accounts.get(0));
214     }
215 
216     @Tag("plainAttrTable")
217     @Test
218     public void deleteLinkedAccountUserCascade() {
219         LinkedAccount account = newLinkedAccount("deleteLinkedAccountUserCascade");
220         assertNotNull(account.getKey());
221 
222         LAPlainAttr plainAttr = account.getPlainAttrs().get(0);
223         assertNotNull(entityManager().find(JPALAPlainAttr.class, plainAttr.getKey()));
224 
225         PlainAttrValue plainAttrValue = account.getPlainAttrs().get(0).getValues().get(0);
226         assertNotNull(entityManager().find(JPALAPlainAttrValue.class, plainAttrValue.getKey()));
227 
228         LinkedAccount found = entityManager().find(JPALinkedAccount.class, account.getKey());
229         assertEquals(account, found);
230 
231         userDAO.delete(account.getOwner());
232         entityManager().flush();
233 
234         assertNull(entityManager().find(JPALinkedAccount.class, account.getKey()));
235         assertNull(entityManager().find(JPALAPlainAttr.class, plainAttr.getKey()));
236         assertNull(entityManager().find(JPALAPlainAttrValue.class, plainAttrValue.getKey()));
237     }
238 
239     @Test
240     public void deleteLinkedAccountResourceCascade() {
241         LinkedAccount account = newLinkedAccount("deleteLinkedAccountResourceCascade");
242         assertNotNull(account.getKey());
243 
244         LinkedAccount found = entityManager().find(JPALinkedAccount.class, account.getKey());
245         assertEquals(account, found);
246 
247         resourceDAO.delete(account.getResource().getKey());
248         entityManager().flush();
249 
250         assertNull(entityManager().find(JPALinkedAccount.class, account.getKey()));
251     }
252 
253     @Test
254     public void deleteCascadeOnDelegations() {
255         User bellini = userDAO.findByUsername("bellini");
256         User rossini = userDAO.findByUsername("rossini");
257 
258         Role reviewer = roleDAO.find("User reviewer");
259 
260         Delegation delegation = entityFactory.newEntity(Delegation.class);
261         delegation.setDelegating(bellini);
262         delegation.setDelegated(rossini);
263         delegation.setStart(OffsetDateTime.now());
264         delegation.add(reviewer);
265         delegation = delegationDAO.save(delegation);
266 
267         entityManager().flush();
268 
269         delegation = delegationDAO.find(delegation.getKey());
270 
271         assertEquals(List.of(delegation), delegationDAO.findByDelegating(bellini));
272         assertEquals(List.of(delegation), delegationDAO.findByDelegated(rossini));
273 
274         userDAO.delete(rossini.getKey());
275 
276         entityManager().flush();
277 
278         assertNull(delegationDAO.find(delegation.getKey()));
279     }
280 
281     /**
282      * Search by derived attribute.
283      */
284     @Test
285     public void issueSYNCOPE800() {
286         // create derived attribute (literal as prefix)
287         DerSchema prefix = entityFactory.newEntity(DerSchema.class);
288         prefix.setKey("kprefix");
289         prefix.setExpression("'k' + firstname");
290 
291         derSchemaDAO.save(prefix);
292         entityManager().flush();
293 
294         // create derived attribute (literal as suffix)
295         DerSchema suffix = entityFactory.newEntity(DerSchema.class);
296         suffix.setKey("ksuffix");
297         suffix.setExpression("firstname + 'k'");
298 
299         derSchemaDAO.save(suffix);
300         entityManager().flush();
301 
302         // add derived attributes to user
303         User owner = userDAO.findByUsername("vivaldi");
304         assertNotNull(owner);
305 
306         String firstname = owner.getPlainAttr("firstname").get().getValuesAsStrings().iterator().next();
307         assertNotNull(firstname);
308 
309         // search by ksuffix derived attribute
310         List<User> list = userDAO.findByDerAttrValue(derSchemaDAO.find("ksuffix"), firstname + 'k', false);
311         assertEquals(1, list.size());
312 
313         // search by kprefix derived attribute
314         list = userDAO.findByDerAttrValue(derSchemaDAO.find("kprefix"), 'k' + firstname, false);
315         assertEquals(1, list.size());
316     }
317 }