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.assertTrue;
25  import static org.junit.jupiter.api.Assertions.fail;
26  
27  import java.time.OffsetDateTime;
28  import java.util.ArrayList;
29  import java.util.HashSet;
30  import java.util.List;
31  import java.util.Set;
32  import java.util.UUID;
33  import org.apache.syncope.common.lib.types.AnyTypeKind;
34  import org.apache.syncope.common.lib.types.ExecStatus;
35  import org.apache.syncope.common.lib.types.IdMImplementationType;
36  import org.apache.syncope.common.lib.types.IdRepoImplementationType;
37  import org.apache.syncope.common.lib.types.ImplementationEngine;
38  import org.apache.syncope.common.lib.types.MatchingRule;
39  import org.apache.syncope.common.lib.types.PullMode;
40  import org.apache.syncope.common.lib.types.ResourceOperation;
41  import org.apache.syncope.common.lib.types.TaskType;
42  import org.apache.syncope.common.lib.types.UnmatchingRule;
43  import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
44  import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
45  import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
46  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
47  import org.apache.syncope.core.persistence.api.dao.TaskDAO;
48  import org.apache.syncope.core.persistence.api.dao.TaskExecDAO;
49  import org.apache.syncope.core.persistence.api.dao.UserDAO;
50  import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
51  import org.apache.syncope.core.persistence.api.entity.ExternalResource;
52  import org.apache.syncope.core.persistence.api.entity.Implementation;
53  import org.apache.syncope.core.persistence.api.entity.task.MacroTask;
54  import org.apache.syncope.core.persistence.api.entity.task.MacroTaskCommand;
55  import org.apache.syncope.core.persistence.api.entity.task.PropagationData;
56  import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
57  import org.apache.syncope.core.persistence.api.entity.task.PullTask;
58  import org.apache.syncope.core.persistence.api.entity.task.PushTask;
59  import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
60  import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
61  import org.apache.syncope.core.persistence.api.entity.task.TaskUtilsFactory;
62  import org.apache.syncope.core.persistence.api.entity.user.User;
63  import org.apache.syncope.core.persistence.jpa.AbstractTest;
64  import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
65  import org.identityconnectors.framework.common.objects.Attribute;
66  import org.identityconnectors.framework.common.objects.AttributeBuilder;
67  import org.junit.jupiter.api.Test;
68  import org.springframework.beans.factory.annotation.Autowired;
69  import org.springframework.transaction.annotation.Transactional;
70  
71  @Transactional("Master")
72  public class TaskTest extends AbstractTest {
73  
74      @Autowired
75      private TaskDAO taskDAO;
76  
77      @Autowired
78      private TaskExecDAO taskExecDAO;
79  
80      @Autowired
81      private ExternalResourceDAO resourceDAO;
82  
83      @Autowired
84      private UserDAO userDAO;
85  
86      @Autowired
87      private RealmDAO realmDAO;
88  
89      @Autowired
90      private ImplementationDAO implementationDAO;
91  
92      @Autowired
93      private TaskUtilsFactory taskUtilsFactory;
94  
95      @Test
96      public void read() {
97          PropagationTask task = taskDAO.find(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c");
98          assertNotNull(task);
99  
100         assertNotNull(task.getExecs());
101         assertFalse(task.getExecs().isEmpty());
102         assertEquals(1, task.getExecs().size());
103     }
104 
105     @Test
106     public void readMultipleOrderBy() {
107         List<OrderByClause> orderByClauses = new ArrayList<>();
108         OrderByClause clause1 = new OrderByClause();
109         clause1.setField("start");
110         OrderByClause clause2 = new OrderByClause();
111         clause2.setField("latestExecStatus");
112         OrderByClause clause3 = new OrderByClause();
113         clause3.setField("connObjectKey");
114         orderByClauses.add(clause1);
115         orderByClauses.add(clause2);
116         orderByClauses.add(clause3);
117         assertFalse(taskDAO.findAll(TaskType.PROPAGATION, null, null, null, null, -1, -1, orderByClauses).isEmpty());
118     }
119 
120     @Test
121     public void savePropagationTask() {
122         ExternalResource resource = resourceDAO.find("ws-target-resource-1");
123         assertNotNull(resource);
124 
125         User user = userDAO.findByUsername("verdi");
126         assertNotNull(user);
127 
128         PropagationTask task = entityFactory.newEntity(PropagationTask.class);
129         task.setResource(resource);
130         task.setAnyTypeKind(AnyTypeKind.USER);
131         task.setAnyType(AnyTypeKind.USER.name());
132         task.setOperation(ResourceOperation.CREATE);
133         task.setConnObjectKey("one@two.com");
134 
135         Set<Attribute> attributes = new HashSet<>();
136         attributes.add(AttributeBuilder.build("testAttribute", "testValue1", "testValue2"));
137         attributes.add(AttributeBuilder.buildPassword("password".toCharArray()));
138         task.setPropagationData(new PropagationData(attributes));
139 
140         task = taskDAO.save(task);
141         assertNotNull(task);
142 
143         PropagationTask actual = taskDAO.find(TaskType.PROPAGATION, task.getKey());
144         assertEquals(task, actual);
145 
146         entityManager().flush();
147 
148         assertTrue(taskDAO.<PropagationTask>findAll(
149                 TaskType.PROPAGATION, resource, null, null, null, -1, -1, List.of()).
150                 contains(task));
151     }
152 
153     @Test
154     public void addPropagationTaskExecution() {
155         PropagationTask task = taskDAO.find(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c");
156         assertNotNull(task);
157 
158         int executionNumber = task.getExecs().size();
159 
160         TaskExec<PropagationTask> execution = taskUtilsFactory.getInstance(TaskType.PROPAGATION).newTaskExec();
161         execution.setTask(task);
162         execution.setStatus(ExecStatus.CREATED.name());
163         execution.setStart(OffsetDateTime.now());
164         execution.setExecutor("admin");
165         task.add(execution);
166 
167         taskDAO.save(task);
168         entityManager().flush();
169 
170         task = taskDAO.find(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c");
171         assertNotNull(task);
172 
173         assertEquals(executionNumber + 1, task.getExecs().size());
174     }
175 
176     @Test
177     public void addPullTaskExecution() {
178         PullTask task = (PullTask) taskDAO.find(TaskType.PULL, "c41b9b71-9bfa-4f90-89f2-84787def4c5c");
179         assertNotNull(task);
180 
181         int executionNumber = task.getExecs().size();
182 
183         TaskExec<SchedTask> execution = taskUtilsFactory.getInstance(TaskType.PULL).newTaskExec();
184         execution.setStatus("Text-free status");
185         execution.setTask(task);
186         execution.setStart(OffsetDateTime.now());
187         execution.setMessage("A message");
188         execution.setExecutor("admin");
189         task.add(execution);
190 
191         taskDAO.save(task);
192         entityManager().flush();
193 
194         task = (PullTask) taskDAO.find(TaskType.PULL, "c41b9b71-9bfa-4f90-89f2-84787def4c5c");
195         assertNotNull(task);
196 
197         assertEquals(executionNumber + 1, task.getExecs().size());
198     }
199 
200     @Test
201     public void addPushTaskExecution() {
202         PushTask task = (PushTask) taskDAO.find(TaskType.PUSH, "af558be4-9d2f-4359-bf85-a554e6e90be1");
203         assertNotNull(task);
204 
205         int executionNumber = task.getExecs().size();
206 
207         TaskExec<SchedTask> execution = taskUtilsFactory.getInstance(TaskType.PUSH).newTaskExec();
208         execution.setStatus("Text-free status");
209         execution.setTask(task);
210         execution.setStart(OffsetDateTime.now());
211         execution.setMessage("A message");
212         execution.setExecutor("admin");
213         task.add(execution);
214 
215         taskDAO.save(task);
216         entityManager().flush();
217 
218         task = (PushTask) taskDAO.find(TaskType.PUSH, "af558be4-9d2f-4359-bf85-a554e6e90be1");
219         assertNotNull(task);
220 
221         assertEquals(executionNumber + 1, task.getExecs().size());
222     }
223 
224     @Test
225     public void deleteTask() {
226         taskDAO.delete(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c");
227 
228         entityManager().flush();
229 
230         assertTrue(taskDAO.find("1e697572-b896-484c-ae7f-0c8f63fcbc6c").isEmpty());
231         assertTrue(taskExecDAO.find("e58ca1c7-178a-4012-8a71-8aa14eaf0655").isEmpty());
232     }
233 
234     @Test
235     public void deleteTaskExecution() {
236         TaskExec<PropagationTask> execution =
237                 taskExecDAO.find(TaskType.PROPAGATION, "e58ca1c7-178a-4012-8a71-8aa14eaf0655");
238         int executionNumber = execution.getTask().getExecs().size();
239 
240         taskExecDAO.delete(TaskType.PROPAGATION, "e58ca1c7-178a-4012-8a71-8aa14eaf0655");
241 
242         entityManager().flush();
243 
244         assertTrue(taskExecDAO.find("e58ca1c7-178a-4012-8a71-8aa14eaf0655").isEmpty());
245 
246         PropagationTask task = taskDAO.find(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c");
247         assertEquals(task.getExecs().size(), executionNumber - 1);
248     }
249 
250     @Test
251     public void savePullTask() {
252         PullTask task = entityFactory.newEntity(PullTask.class);
253         task.setName("savePullTask");
254         task.setDescription("PullTask description");
255         task.setActive(true);
256         task.setPullMode(PullMode.FULL_RECONCILIATION);
257         task.setJobDelegate(implementationDAO.find("PullJobDelegate"));
258         task.setDestinationRealm(realmDAO.getRoot());
259         task.setCronExpression("BLA BLA");
260         task.setMatchingRule(MatchingRule.UPDATE);
261         task.setUnmatchingRule(UnmatchingRule.PROVISION);
262 
263         // now adding PullActions
264         Implementation pullActions = entityFactory.newEntity(Implementation.class);
265         pullActions.setKey("PullActions" + UUID.randomUUID().toString());
266         pullActions.setEngine(ImplementationEngine.JAVA);
267         pullActions.setType(IdMImplementationType.PULL_ACTIONS);
268         pullActions.setBody(PullActions.class.getName());
269         pullActions = implementationDAO.save(pullActions);
270         entityManager().flush();
271 
272         task.add(pullActions);
273 
274         // this save() fails because of an invalid Cron Expression
275         try {
276             taskDAO.save(task);
277             fail();
278         } catch (InvalidEntityException e) {
279             assertNotNull(e);
280         }
281         task.setCronExpression(null);
282 
283         // this save() fails because a PullTask requires a target resource
284         try {
285             taskDAO.save(task);
286             fail();
287         } catch (InvalidEntityException e) {
288             assertNotNull(e);
289         }
290         task.setResource(resourceDAO.find("ws-target-resource-1"));
291 
292         // this save() finally works
293         task = (PullTask) taskDAO.save(task);
294         assertNotNull(task);
295 
296         PullTask actual = (PullTask) taskDAO.find(TaskType.PULL, task.getKey());
297         assertEquals(task, actual);
298     }
299 
300     @Test
301     public void saveMacroTaskSameCommandMultipleOccurrencies() {
302         MacroTask task = entityFactory.newEntity(MacroTask.class);
303         task.setRealm(realmDAO.getRoot());
304         task.setJobDelegate(implementationDAO.find("MacroJobDelegate"));
305         task.setName("saveMacroTaskSameCommandMultipleOccurrencies");
306         task.setContinueOnError(true);
307 
308         Implementation command1 = entityFactory.newEntity(Implementation.class);
309         command1.setKey("command1");
310         command1.setType(IdRepoImplementationType.COMMAND);
311         command1.setEngine(ImplementationEngine.JAVA);
312         command1.setBody("clazz1");
313         command1 = implementationDAO.save(command1);
314         assertNotNull(command1);
315 
316         Implementation command2 = entityFactory.newEntity(Implementation.class);
317         command2.setKey("command2");
318         command2.setType(IdRepoImplementationType.COMMAND);
319         command2.setEngine(ImplementationEngine.JAVA);
320         command2.setBody("clazz2");
321         command2 = implementationDAO.save(command2);
322         assertNotNull(command2);
323 
324         MacroTaskCommand macroTaskCommand1 = entityFactory.newEntity(MacroTaskCommand.class);
325         macroTaskCommand1.setCommand(command1);
326         macroTaskCommand1.setMacroTask(task);
327         task.add(macroTaskCommand1);
328 
329         MacroTaskCommand macroTaskCommand2 = entityFactory.newEntity(MacroTaskCommand.class);
330         macroTaskCommand2.setCommand(command2);
331         macroTaskCommand2.setMacroTask(task);
332         task.add(macroTaskCommand2);
333 
334         MacroTaskCommand macroTaskCommand3 = entityFactory.newEntity(MacroTaskCommand.class);
335         macroTaskCommand3.setCommand(command1);
336         macroTaskCommand3.setMacroTask(task);
337         task.add(macroTaskCommand3);
338 
339         task = (MacroTask) taskDAO.save(task);
340         assertNotNull(task);
341         assertEquals(3, task.getCommands().size());
342         assertEquals(command1, task.getCommands().get(0).getCommand());
343         assertEquals(command2, task.getCommands().get(1).getCommand());
344         assertEquals(command1, task.getCommands().get(2).getCommand());
345 
346         MacroTask actual = (MacroTask) taskDAO.find(TaskType.MACRO, task.getKey());
347         assertEquals(task, actual);
348     }
349 
350     @Test
351     public void issueSYNCOPE144() {
352         ExternalResource resource = resourceDAO.find("ws-target-resource-1");
353         assertNotNull(resource);
354 
355         Implementation pullActions = entityFactory.newEntity(Implementation.class);
356         pullActions.setKey("syncope144");
357         pullActions.setEngine(ImplementationEngine.JAVA);
358         pullActions.setType(IdMImplementationType.PULL_ACTIONS);
359         pullActions.setBody(PullActions.class.getName());
360         pullActions = implementationDAO.save(pullActions);
361 
362         PullTask task = entityFactory.newEntity(PullTask.class);
363 
364         task.setResource(resource);
365         task.setName("issueSYNCOPE144");
366         task.setDescription("issueSYNCOPE144 Description");
367         task.setActive(true);
368         task.setPullMode(PullMode.FULL_RECONCILIATION);
369         task.add(pullActions);
370         task.setMatchingRule(MatchingRule.UPDATE);
371         task.setUnmatchingRule(UnmatchingRule.PROVISION);
372 
373         task = (PullTask) taskDAO.save(task);
374         assertNotNull(task);
375 
376         PullTask actual = (PullTask) taskDAO.find(TaskType.PULL, task.getKey());
377         assertEquals(task, actual);
378         assertEquals("issueSYNCOPE144", actual.getName());
379         assertEquals("issueSYNCOPE144 Description", actual.getDescription());
380 
381         actual.setName("issueSYNCOPE144_2");
382         actual.setDescription("issueSYNCOPE144 Description_2");
383 
384         actual = (PullTask) taskDAO.save(actual);
385         assertNotNull(actual);
386         assertEquals("issueSYNCOPE144_2", actual.getName());
387         assertEquals("issueSYNCOPE144 Description_2", actual.getDescription());
388     }
389 }