1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.fit.core;
20
21 import static org.awaitility.Awaitility.await;
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import static org.junit.jupiter.api.Assertions.assertFalse;
24 import static org.junit.jupiter.api.Assertions.assertNotEquals;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26 import static org.junit.jupiter.api.Assertions.assertNull;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.junit.jupiter.api.Assertions.fail;
29
30 import java.io.IOException;
31 import java.text.ParseException;
32 import java.time.LocalDate;
33 import java.time.OffsetDateTime;
34 import java.time.ZoneOffset;
35 import java.time.format.DateTimeFormatter;
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Optional;
41 import java.util.Set;
42 import java.util.concurrent.TimeUnit;
43 import javax.ws.rs.core.GenericType;
44 import javax.ws.rs.core.Response;
45 import javax.xml.ws.WebServiceException;
46 import org.apache.commons.lang3.SerializationUtils;
47 import org.apache.commons.lang3.StringUtils;
48 import org.apache.syncope.client.lib.SyncopeClient;
49 import org.apache.syncope.client.lib.batch.BatchRequest;
50 import org.apache.syncope.common.lib.Attr;
51 import org.apache.syncope.common.lib.SyncopeClientException;
52 import org.apache.syncope.common.lib.SyncopeConstants;
53 import org.apache.syncope.common.lib.policy.PropagationPolicyTO;
54 import org.apache.syncope.common.lib.request.AnyObjectCR;
55 import org.apache.syncope.common.lib.request.AnyObjectUR;
56 import org.apache.syncope.common.lib.request.AttrPatch;
57 import org.apache.syncope.common.lib.request.GroupCR;
58 import org.apache.syncope.common.lib.request.GroupUR;
59 import org.apache.syncope.common.lib.request.MembershipUR;
60 import org.apache.syncope.common.lib.request.ResourceDR;
61 import org.apache.syncope.common.lib.request.UserCR;
62 import org.apache.syncope.common.lib.request.UserUR;
63 import org.apache.syncope.common.lib.to.AnyObjectTO;
64 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
65 import org.apache.syncope.common.lib.to.ConnObject;
66 import org.apache.syncope.common.lib.to.ExecTO;
67 import org.apache.syncope.common.lib.to.GroupTO;
68 import org.apache.syncope.common.lib.to.ImplementationTO;
69 import org.apache.syncope.common.lib.to.Item;
70 import org.apache.syncope.common.lib.to.MembershipTO;
71 import org.apache.syncope.common.lib.to.PagedResult;
72 import org.apache.syncope.common.lib.to.PlainSchemaTO;
73 import org.apache.syncope.common.lib.to.PropagationTaskTO;
74 import org.apache.syncope.common.lib.to.Provision;
75 import org.apache.syncope.common.lib.to.ProvisioningResult;
76 import org.apache.syncope.common.lib.to.ReconStatus;
77 import org.apache.syncope.common.lib.to.RelationshipTO;
78 import org.apache.syncope.common.lib.to.ResourceTO;
79 import org.apache.syncope.common.lib.to.TaskTO;
80 import org.apache.syncope.common.lib.to.UserTO;
81 import org.apache.syncope.common.lib.types.AnyTypeKind;
82 import org.apache.syncope.common.lib.types.AttrSchemaType;
83 import org.apache.syncope.common.lib.types.ExecStatus;
84 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
85 import org.apache.syncope.common.lib.types.ImplementationEngine;
86 import org.apache.syncope.common.lib.types.MappingPurpose;
87 import org.apache.syncope.common.lib.types.PatchOperation;
88 import org.apache.syncope.common.lib.types.PolicyType;
89 import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
90 import org.apache.syncope.common.lib.types.ResourceOperation;
91 import org.apache.syncope.common.lib.types.SchemaType;
92 import org.apache.syncope.common.lib.types.TaskType;
93 import org.apache.syncope.common.rest.api.RESTHeaders;
94 import org.apache.syncope.common.rest.api.beans.ExecQuery;
95 import org.apache.syncope.common.rest.api.beans.ExecSpecs;
96 import org.apache.syncope.common.rest.api.beans.ReconQuery;
97 import org.apache.syncope.common.rest.api.beans.TaskQuery;
98 import org.apache.syncope.common.rest.api.service.TaskService;
99 import org.apache.syncope.core.persistence.api.entity.task.PropagationData;
100 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
101 import org.apache.syncope.fit.core.reference.DateToDateItemTransformer;
102 import org.apache.syncope.fit.core.reference.DateToLongItemTransformer;
103 import org.identityconnectors.framework.common.objects.Attribute;
104 import org.identityconnectors.framework.common.objects.AttributeUtil;
105 import org.identityconnectors.framework.common.objects.Name;
106 import org.identityconnectors.framework.common.objects.OperationalAttributes;
107 import org.junit.jupiter.api.BeforeAll;
108 import org.junit.jupiter.api.Test;
109 import org.springframework.dao.DataAccessException;
110 import org.springframework.jdbc.core.JdbcTemplate;
111
112 public class PropagationTaskITCase extends AbstractTaskITCase {
113
114 @BeforeAll
115 public static void testItemTransformersSetup() {
116 ImplementationTO dateToLong = null;
117 ImplementationTO dateToDate = null;
118 try {
119 dateToLong = IMPLEMENTATION_SERVICE.read(
120 IdRepoImplementationType.ITEM_TRANSFORMER, DateToLongItemTransformer.class.getSimpleName());
121 dateToDate = IMPLEMENTATION_SERVICE.read(
122 IdRepoImplementationType.ITEM_TRANSFORMER, DateToDateItemTransformer.class.getSimpleName());
123 } catch (SyncopeClientException e) {
124 if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
125 dateToLong = new ImplementationTO();
126 dateToLong.setKey(DateToLongItemTransformer.class.getSimpleName());
127 dateToLong.setEngine(ImplementationEngine.JAVA);
128 dateToLong.setType(IdRepoImplementationType.ITEM_TRANSFORMER);
129 dateToLong.setBody(DateToLongItemTransformer.class.getName());
130 Response response = IMPLEMENTATION_SERVICE.create(dateToLong);
131 dateToLong = IMPLEMENTATION_SERVICE.read(
132 dateToLong.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY));
133 assertNotNull(dateToLong);
134
135 dateToDate = new ImplementationTO();
136 dateToDate.setKey(DateToDateItemTransformer.class.getSimpleName());
137 dateToDate.setEngine(ImplementationEngine.JAVA);
138 dateToDate.setType(IdRepoImplementationType.ITEM_TRANSFORMER);
139 dateToDate.setBody(DateToDateItemTransformer.class.getName());
140 response = IMPLEMENTATION_SERVICE.create(dateToDate);
141 dateToDate = IMPLEMENTATION_SERVICE.read(
142 dateToDate.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY));
143 assertNotNull(dateToDate);
144 }
145 }
146 assertNotNull(dateToLong);
147 assertNotNull(dateToDate);
148 }
149
150 @Test
151 public void paginatedList() {
152 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(
153 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(2).build());
154 assertNotNull(tasks);
155 assertEquals(2, tasks.getResult().size());
156
157 for (TaskTO task : tasks.getResult()) {
158 assertNotNull(task);
159 }
160
161 tasks = TASK_SERVICE.search(
162 new TaskQuery.Builder(TaskType.PROPAGATION).page(2).size(2).build());
163 assertNotNull(tasks);
164 assertEquals(2, tasks.getPage());
165 assertEquals(2, tasks.getResult().size());
166
167 for (TaskTO task : tasks.getResult()) {
168 assertNotNull(task);
169 }
170
171 tasks = TASK_SERVICE.search(
172 new TaskQuery.Builder(TaskType.PROPAGATION).page(1000).size(2).build());
173 assertNotNull(tasks);
174 assertTrue(tasks.getResult().isEmpty());
175 }
176
177 @Test
178 public void read() {
179 PropagationTaskTO taskTO = TASK_SERVICE.read(
180 TaskType.PROPAGATION, "316285cc-ae52-4ea2-a33b-7355e189ac3f", true);
181 assertNotNull(taskTO);
182 assertNotNull(taskTO.getExecutions());
183 assertTrue(taskTO.getExecutions().isEmpty());
184 }
185
186 @Test
187 public void batch() throws IOException {
188
189 UserCR userCR = UserITCase.getUniqueSample("taskBatch@apache.org");
190 userCR.getResources().add(RESOURCE_NAME_TESTDB);
191 UserTO userTO = createUser(userCR).getEntity();
192
193 List<PropagationTaskTO> tasks = new ArrayList<>(
194 TASK_SERVICE.<PropagationTaskTO>search(new TaskQuery.Builder(TaskType.PROPAGATION).
195 anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build()).
196 getResult());
197 assertFalse(tasks.isEmpty());
198
199 BatchRequest batchRequest = ADMIN_CLIENT.batch();
200
201 TaskService batchTaskService = batchRequest.getService(TaskService.class);
202 tasks.forEach(task -> batchTaskService.delete(TaskType.PROPAGATION, task.getKey()));
203
204 Response response = batchRequest.commit().getResponse();
205 parseBatchResponse(response);
206
207 assertFalse(TASK_SERVICE.search(
208 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(100).build()).
209 getResult().containsAll(tasks));
210 }
211
212 @Test
213 public void propagationJEXLTransformer() {
214
215 ResourceTO resource = RESOURCE_SERVICE.read(RESOURCE_NAME_DBSCRIPTED);
216 ResourceTO originalResource = SerializationUtils.clone(resource);
217 Provision provision = resource.getProvision(PRINTER).get();
218 assertNotNull(provision);
219
220 Optional<Item> mappingItem = provision.getMapping().getItems().stream().
221 filter(item -> "location".equals(item.getIntAttrName())).findFirst();
222 assertTrue(mappingItem.isPresent());
223 assertTrue(mappingItem.get().getTransformers().isEmpty());
224
225 String suffix = getUUIDString();
226 mappingItem.get().setPropagationJEXLTransformer("value + '" + suffix + '\'');
227
228 try {
229 RESOURCE_SERVICE.update(resource);
230
231
232 AnyObjectCR anyObjectCR = AnyObjectITCase.getSample("propagationJEXLTransformer");
233 String originalLocation = anyObjectCR.getPlainAttr("location").get().getValues().get(0);
234 assertFalse(originalLocation.endsWith(suffix));
235
236 AnyObjectTO anyObjectTO = createAnyObject(anyObjectCR).getEntity();
237 assertNotNull(anyObjectTO);
238
239
240
241 ConnObject connObjectTO = RESOURCE_SERVICE.
242 readConnObject(RESOURCE_NAME_DBSCRIPTED, anyObjectTO.getType(), anyObjectTO.getKey());
243 assertFalse(anyObjectTO.getPlainAttr("location").get().getValues().get(0).endsWith(suffix));
244 assertTrue(connObjectTO.getAttr("LOCATION").get().getValues().get(0).endsWith(suffix));
245 } finally {
246 RESOURCE_SERVICE.update(originalResource);
247 }
248 }
249
250 @Test
251 public void privileges() {
252 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
253 ldap.setKey("ldapWithPrivileges");
254
255 Provision provision = ldap.getProvision(AnyTypeKind.USER.name()).orElse(null);
256 provision.getMapping().getItems().removeIf(item -> "mail".equals(item.getIntAttrName()));
257 provision.getVirSchemas().clear();
258
259 ldap.getProvisions().clear();
260 ldap.getProvisions().add(provision);
261
262 Item item = new Item();
263 item.setIntAttrName("privileges[mightyApp]");
264 item.setExtAttrName("businessCategory");
265 item.setPurpose(MappingPurpose.PROPAGATION);
266
267 provision.getMapping().add(item);
268
269 ldap = createResource(ldap);
270
271 try {
272 UserCR userCR = UserITCase.getUniqueSample("privilege@syncope.apache.org");
273 userCR.getResources().add(ldap.getKey());
274 userCR.getRoles().add("Other");
275
276 ProvisioningResult<UserTO> result = createUser(userCR);
277 assertEquals(1, result.getPropagationStatuses().size());
278 assertNotNull(result.getPropagationStatuses().get(0).getAfterObj());
279
280 Attr businessCategory =
281 result.getPropagationStatuses().get(0).getAfterObj().getAttr("businessCategory").orElse(null);
282 assertNotNull(businessCategory);
283 assertEquals(1, businessCategory.getValues().size());
284 assertEquals("postMighty", businessCategory.getValues().get(0));
285 } finally {
286 RESOURCE_SERVICE.delete(ldap.getKey());
287 }
288 }
289
290 @Test
291 public void purgePropagations() {
292 try {
293 TASK_SERVICE.purgePropagations(null, null, null);
294 fail();
295 } catch (WebServiceException e) {
296 assertNotNull(e);
297 }
298
299 OffsetDateTime oneWeekAgo = OffsetDateTime.now().minusWeeks(1);
300 Response response = TASK_SERVICE.purgePropagations(
301 oneWeekAgo,
302 List.of(ExecStatus.SUCCESS),
303 List.of(RESOURCE_NAME_WS1));
304 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
305
306 List<PropagationTaskTO> deleted = response.readEntity(new GenericType<List<PropagationTaskTO>>() {
307 });
308 assertNotNull(deleted);
309
310 assertEquals(1, deleted.size());
311 assertTrue(deleted.stream().allMatch(d -> RESOURCE_NAME_WS1.equals(d.getResource())));
312
313 assertFalse(TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION)
314 .anyTypeKind(AnyTypeKind.USER)
315 .page(0).size(10)
316 .build()).getResult().isEmpty());
317
318 response = TASK_SERVICE.purgePropagations(oneWeekAgo, List.of(ExecStatus.SUCCESS), List.of());
319 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
320
321 deleted = response.readEntity(new GenericType<List<PropagationTaskTO>>() {
322 });
323 assertNotNull(deleted);
324 }
325
326 @Test
327 public void propagationPolicyRetry() throws InterruptedException {
328 SyncopeClient.nullPriorityAsync(ANY_OBJECT_SERVICE, true);
329
330 JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
331 jdbcTemplate.execute("ALTER TABLE TESTPRINTER ADD COLUMN MAND_VALUE VARCHAR(1)");
332 jdbcTemplate.execute("UPDATE TESTPRINTER SET MAND_VALUE='C'");
333 jdbcTemplate.execute("ALTER TABLE TESTPRINTER ALTER COLUMN MAND_VALUE VARCHAR(1) NOT NULL");
334 try {
335 String entityKey = createAnyObject(AnyObjectITCase.getSample("propagationPolicy")).getEntity().getKey();
336
337 Thread.sleep(1000);
338 jdbcTemplate.execute("ALTER TABLE TESTPRINTER DROP COLUMN MAND_VALUE");
339
340 PagedResult<PropagationTaskTO> propagations = await().atMost(MAX_WAIT_SECONDS, TimeUnit.SECONDS).until(
341 () -> TASK_SERVICE.search(
342 new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_DBSCRIPTED).
343 anyTypeKind(AnyTypeKind.ANY_OBJECT).entityKey(entityKey).build()),
344 p -> p.getTotalCount() > 0);
345
346 propagations.getResult().get(0).getExecutions().stream().
347 anyMatch(e -> ExecStatus.FAILURE.name().equals(e.getStatus()));
348 propagations.getResult().get(0).getExecutions().stream().
349 anyMatch(e -> ExecStatus.SUCCESS.name().equals(e.getStatus()));
350 } finally {
351 SyncopeClient.nullPriorityAsync(ANY_OBJECT_SERVICE, false);
352
353 try {
354 jdbcTemplate.execute("ALTER TABLE TESTPRINTER DROP COLUMN MAND_VALUE");
355 } catch (DataAccessException e) {
356
357 }
358 }
359 }
360
361 private static String propagationPolicyOptimizeKey() {
362 return POLICY_SERVICE.list(PolicyType.PROPAGATION).stream().
363 filter(p -> "optimize".equals(p.getName())).
364 findFirst().
365 orElseGet(() -> {
366 PropagationPolicyTO policy = new PropagationPolicyTO();
367 policy.setName("optimize");
368 policy.setFetchAroundProvisioning(false);
369 policy.setUpdateDelta(true);
370 return createPolicy(PolicyType.PROPAGATION, policy);
371 }).getKey();
372 }
373
374 @Test
375 public void propagationPolicyOptimizeToLDAP() {
376 String policyKey = propagationPolicyOptimizeKey();
377
378 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
379 assertNull(ldap.getPropagationPolicy());
380
381 ldap.setPropagationPolicy(policyKey);
382 RESOURCE_SERVICE.update(ldap);
383
384 try {
385
386 GroupTO group1 = createGroup(GroupITCase.getSample("propagationPolicyOptimizeToLDAP")).getEntity();
387 GroupTO group2 = createGroup(GroupITCase.getSample("propagationPolicyOptimizeToLDAP")).getEntity();
388
389
390 UserCR userCR = UserITCase.getUniqueSample("propagationPolicyOptimizeToLDAP@syncope.apache.org");
391 userCR.getAuxClasses().add("minimal group");
392 userCR.getPlainAttrs().add(attr("title", "title1"));
393 userCR.getMemberships().add(new MembershipTO.Builder(group1.getKey()).build());
394 ProvisioningResult<UserTO> created = createUser(userCR);
395 assertEquals(RESOURCE_NAME_LDAP, created.getPropagationStatuses().get(0).getResource());
396 assertEquals(ExecStatus.SUCCESS, created.getPropagationStatuses().get(0).getStatus());
397
398
399 ReconStatus status = RECONCILIATION_SERVICE.status(
400 new ReconQuery.Builder(AnyTypeKind.USER.name(), RESOURCE_NAME_LDAP).
401 anyKey(created.getEntity().getKey()).moreAttrsToGet("ldapGroups").build());
402 assertEquals(List.of("title1"), status.getOnResource().getAttr("title").get().getValues());
403 assertEquals(
404 List.of("cn=" + group1.getName() + ",ou=groups,o=isp"),
405 status.getOnResource().getAttr("ldapGroups").get().getValues());
406
407
408 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
409 resource(RESOURCE_NAME_LDAP).
410 anyTypeKind(AnyTypeKind.USER).entityKey(created.getEntity().getKey()).build());
411 assertEquals(1, tasks.getSize());
412
413 PropagationData data = POJOHelper.deserialize(
414 tasks.getResult().get(0).getPropagationData(), PropagationData.class);
415 assertNull(data.getAttributeDeltas());
416
417 TASK_SERVICE.delete(TaskType.PROPAGATION, tasks.getResult().get(0).getKey());
418
419
420 UserUR userUR = new UserUR.Builder(created.getEntity().getKey()).plainAttr(new AttrPatch.Builder(
421 new Attr.Builder("title").values("title1", "title2").build()).build()).
422 membership(new MembershipUR.Builder(group2.getKey()).build()).
423 build();
424 ProvisioningResult<UserTO> updated = updateUser(userUR);
425 assertEquals(RESOURCE_NAME_LDAP, updated.getPropagationStatuses().get(0).getResource());
426 assertEquals(ExecStatus.SUCCESS, updated.getPropagationStatuses().get(0).getStatus());
427
428
429 status = RECONCILIATION_SERVICE.status(
430 new ReconQuery.Builder(AnyTypeKind.USER.name(), RESOURCE_NAME_LDAP).
431 anyKey(created.getEntity().getKey()).moreAttrsToGet("ldapGroups").build());
432 assertEquals(
433 Set.of("title1", "title2"),
434 new HashSet<>(status.getOnResource().getAttr("title").get().getValues()));
435 assertEquals(
436 Set.of("cn=" + group1.getName() + ",ou=groups,o=isp",
437 "cn=" + group2.getName() + ",ou=groups,o=isp"),
438 new HashSet<>(status.getOnResource().getAttr("ldapGroups").get().getValues()));
439
440
441 tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
442 resource(RESOURCE_NAME_LDAP).
443 anyTypeKind(AnyTypeKind.USER).entityKey(created.getEntity().getKey()).build());
444 assertEquals(1, tasks.getSize());
445
446 data = POJOHelper.deserialize(tasks.getResult().get(0).getPropagationData(), PropagationData.class);
447 assertNotNull(data.getAttributeDeltas());
448
449 TASK_SERVICE.delete(TaskType.PROPAGATION, tasks.getResult().get(0).getKey());
450 } finally {
451 ldap.setPropagationPolicy(null);
452 RESOURCE_SERVICE.update(ldap);
453 }
454 }
455
456 @Test
457 public void propagationPolicyOptimizeToScriptedDB() {
458 String policyKey = propagationPolicyOptimizeKey();
459
460 ResourceTO db = RESOURCE_SERVICE.read(RESOURCE_NAME_DBSCRIPTED);
461 String beforePolicyKey = db.getPropagationPolicy();
462 assertNotNull(beforePolicyKey);
463
464 db.setPropagationPolicy(policyKey);
465
466
467 PlainSchemaTO paperformat = new PlainSchemaTO();
468 paperformat.setKey("paperformat");
469 paperformat.setMultivalue(true);
470 SCHEMA_SERVICE.create(SchemaType.PLAIN, paperformat);
471
472 AnyTypeClassTO printer = ANY_TYPE_CLASS_SERVICE.read("minimal printer");
473 printer.getPlainSchemas().add(paperformat.getKey());
474 ANY_TYPE_CLASS_SERVICE.update(printer);
475
476 Item paperformatItem = new Item();
477 paperformatItem.setPurpose(MappingPurpose.PROPAGATION);
478 paperformatItem.setIntAttrName("paperformat");
479 paperformatItem.setExtAttrName("paperformat");
480 db.getProvision(PRINTER).get().getMapping().add(paperformatItem);
481 RESOURCE_SERVICE.update(db);
482
483 ProvisioningResult<AnyObjectTO> created = null;
484 try {
485
486 created = createAnyObject(AnyObjectITCase.getSample("ppOptimizeToDB"));
487 assertEquals(RESOURCE_NAME_DBSCRIPTED, created.getPropagationStatuses().get(0).getResource());
488 assertEquals(ExecStatus.SUCCESS, created.getPropagationStatuses().get(0).getStatus());
489
490
491 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
492 resource(RESOURCE_NAME_DBSCRIPTED).
493 anyTypeKind(AnyTypeKind.ANY_OBJECT).entityKey(created.getEntity().getKey()).build());
494 assertEquals(1, tasks.getSize());
495
496 PropagationData data = POJOHelper.deserialize(
497 tasks.getResult().get(0).getPropagationData(), PropagationData.class);
498 assertNull(data.getAttributeDeltas());
499
500 TASK_SERVICE.delete(TaskType.PROPAGATION, tasks.getResult().get(0).getKey());
501
502
503 AnyObjectUR req = new AnyObjectUR.Builder(created.getEntity().getKey()).plainAttr(new AttrPatch.Builder(
504 new Attr.Builder("paperformat").values("format1", "format2").build()).build()).
505 build();
506 ProvisioningResult<AnyObjectTO> updated = updateAnyObject(req);
507 assertEquals(RESOURCE_NAME_DBSCRIPTED, updated.getPropagationStatuses().get(0).getResource());
508 assertEquals(ExecStatus.SUCCESS, updated.getPropagationStatuses().get(0).getStatus());
509
510
511 JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
512 List<String> values = queryForList(jdbcTemplate,
513 MAX_WAIT_SECONDS,
514 "SELECT paper_format FROM testPRINTER_PAPERFORMAT WHERE printer_id=?",
515 String.class,
516 created.getEntity().getKey());
517 assertEquals(Set.of("format1", "format2"), new HashSet<>(values));
518
519
520 tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
521 resource(RESOURCE_NAME_DBSCRIPTED).
522 anyTypeKind(AnyTypeKind.ANY_OBJECT).entityKey(created.getEntity().getKey()).build());
523 assertEquals(1, tasks.getSize());
524
525 data = POJOHelper.deserialize(tasks.getResult().get(0).getPropagationData(), PropagationData.class);
526 assertNotNull(data.getAttributeDeltas());
527
528 TASK_SERVICE.delete(TaskType.PROPAGATION, tasks.getResult().get(0).getKey());
529
530
531 req = new AnyObjectUR.Builder(created.getEntity().getKey()).plainAttr(new AttrPatch.Builder(
532 new Attr.Builder("paperformat").values("format1", "format3").build()).build()).
533 build();
534 updated = updateAnyObject(req);
535 assertEquals(RESOURCE_NAME_DBSCRIPTED, updated.getPropagationStatuses().get(0).getResource());
536 assertEquals(ExecStatus.SUCCESS, updated.getPropagationStatuses().get(0).getStatus());
537
538
539 values = queryForList(jdbcTemplate,
540 MAX_WAIT_SECONDS,
541 "SELECT paper_format FROM testPRINTER_PAPERFORMAT WHERE printer_id=?",
542 String.class,
543 created.getEntity().getKey());
544 assertEquals(Set.of("format1", "format3"), new HashSet<>(values));
545
546
547 tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
548 resource(RESOURCE_NAME_DBSCRIPTED).
549 anyTypeKind(AnyTypeKind.ANY_OBJECT).entityKey(created.getEntity().getKey()).build());
550 assertEquals(1, tasks.getSize());
551
552 data = POJOHelper.deserialize(tasks.getResult().get(0).getPropagationData(), PropagationData.class);
553 assertNotNull(data.getAttributeDeltas());
554
555 TASK_SERVICE.delete(TaskType.PROPAGATION, tasks.getResult().get(0).getKey());
556 } finally {
557 Optional.ofNullable(created).map(c -> c.getEntity().getKey()).ifPresent(ANY_OBJECT_SERVICE::delete);
558
559 SCHEMA_SERVICE.delete(SchemaType.PLAIN, "paperformat");
560
561 db.setPropagationPolicy(beforePolicyKey);
562 db.getProvision(PRINTER).ifPresent(provision -> provision.getMapping().
563 getItems().removeIf(item -> "paperformat".equals(item.getIntAttrName())));
564 RESOURCE_SERVICE.update(db);
565 }
566 }
567
568 @Test
569 public void issueSYNCOPE741() {
570 for (int i = 0; i < 3; i++) {
571 TASK_SERVICE.execute(new ExecSpecs.Builder().
572 key("1e697572-b896-484c-ae7f-0c8f63fcbc6c").build());
573 TASK_SERVICE.execute(new ExecSpecs.Builder().
574 key("316285cc-ae52-4ea2-a33b-7355e189ac3f").build());
575 }
576 try {
577 Thread.sleep(3000);
578 } catch (InterruptedException e) {
579
580 }
581
582
583 PagedResult<TaskTO> tasks = TASK_SERVICE.search(
584 new TaskQuery.Builder(TaskType.PROPAGATION).
585 page(1).size(2).orderBy("operation DESC").details(false).build());
586 for (TaskTO item : tasks.getResult()) {
587 assertTrue(item.getExecutions().isEmpty());
588 }
589
590 tasks = TASK_SERVICE.search(
591 new TaskQuery.Builder(TaskType.PROPAGATION).
592 page(1).size(2).orderBy("operation DESC").details(true).build());
593 for (TaskTO item : tasks.getResult()) {
594 assertFalse(item.getExecutions().isEmpty());
595 }
596
597
598 PropagationTaskTO task = TASK_SERVICE.read(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c", false);
599 assertNotNull(task);
600 assertEquals("1e697572-b896-484c-ae7f-0c8f63fcbc6c", task.getKey());
601 assertTrue(task.getExecutions().isEmpty());
602
603 task = TASK_SERVICE.read(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c", true);
604 assertNotNull(task);
605 assertEquals("1e697572-b896-484c-ae7f-0c8f63fcbc6c", task.getKey());
606 assertFalse(task.getExecutions().isEmpty());
607
608
609 PagedResult<ExecTO> execs = TASK_SERVICE.listExecutions(new ExecQuery.Builder().
610 key("1e697572-b896-484c-ae7f-0c8f63fcbc6c").
611 before(OffsetDateTime.now().plusSeconds(30)).
612 page(1).size(2).build());
613 assertTrue(execs.getTotalCount() >= execs.getResult().size());
614 }
615
616 @Test
617 public void issueSYNCOPE1288() {
618
619 UserCR userCR = UserITCase.getUniqueSample("xxxyyy@xxx.xxx");
620 userCR.getResources().add(RESOURCE_NAME_LDAP);
621
622 UserTO userTO = createUser(userCR).getEntity();
623 assertNotNull(userTO);
624
625
626 for (int i = 0; i < 9; i++) {
627 UserUR userUR = new UserUR();
628 userUR.setKey(userTO.getKey());
629 userUR.getPlainAttrs().add(new AttrPatch.Builder(new Attr.Builder("userId").value(
630 "test" + getUUIDString() + i + "@test.com").build()).
631 operation(PatchOperation.ADD_REPLACE).
632 build());
633
634 USER_SERVICE.update(userUR);
635 }
636
637
638 PagedResult<TaskTO> unorderedTasks = TASK_SERVICE.search(
639 new TaskQuery.Builder(TaskType.PROPAGATION).
640 resource(RESOURCE_NAME_LDAP).
641 entityKey(userTO.getKey()).
642 anyTypeKind(AnyTypeKind.USER).
643 page(1).
644 size(10).
645 build());
646 Collections.sort(unorderedTasks.getResult(), (t1, t2) -> t1.getStart().compareTo(t2.getStart()));
647 assertNotNull(unorderedTasks);
648 assertFalse(unorderedTasks.getResult().isEmpty());
649 assertEquals(10, unorderedTasks.getResult().size());
650
651 PagedResult<TaskTO> orderedTasks = TASK_SERVICE.search(
652 new TaskQuery.Builder(TaskType.PROPAGATION).
653 resource(RESOURCE_NAME_LDAP).
654 entityKey(userTO.getKey()).
655 anyTypeKind(AnyTypeKind.USER).
656 page(1).
657 size(10).
658 orderBy("start").
659 build());
660 assertNotNull(orderedTasks);
661 assertFalse(orderedTasks.getResult().isEmpty());
662 assertEquals(10, orderedTasks.getResult().size());
663
664 assertTrue(orderedTasks.getResult().equals(unorderedTasks.getResult()));
665
666
667 Collections.reverse(unorderedTasks.getResult());
668 orderedTasks = TASK_SERVICE.search(
669 new TaskQuery.Builder(TaskType.PROPAGATION).
670 resource(RESOURCE_NAME_LDAP).
671 entityKey(userTO.getKey()).
672 anyTypeKind(AnyTypeKind.USER).
673 page(1).
674 size(10).
675 orderBy("start DESC").
676 build());
677
678 assertTrue(orderedTasks.getResult().equals(unorderedTasks.getResult()));
679 }
680
681 @Test
682 public void issueSYNCOPE1430() throws ParseException {
683 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
684 try {
685
686 Provision provision = ldap.getProvision(AnyTypeKind.USER.name()).orElse(null);
687 assertNotNull(provision);
688 provision.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName()));
689 provision.getVirSchemas().clear();
690
691
692 Item loginDateForJexlAsLong = new Item();
693 loginDateForJexlAsLong.setPurpose(MappingPurpose.PROPAGATION);
694 loginDateForJexlAsLong.setIntAttrName("loginDate");
695 loginDateForJexlAsLong.setExtAttrName("employeeNumber");
696 loginDateForJexlAsLong.setPropagationJEXLTransformer("value.toInstant().toEpochMilli()");
697 provision.getMapping().add(loginDateForJexlAsLong);
698
699
700 Item loginDateForJexlAsString = new Item();
701 loginDateForJexlAsString.setPurpose(MappingPurpose.PROPAGATION);
702 loginDateForJexlAsString.setIntAttrName("loginDate");
703 loginDateForJexlAsString.setExtAttrName("street");
704 loginDateForJexlAsString.setPropagationJEXLTransformer(
705 "value.toInstant().toString().split(\"T\")[0].replace(\"-\", \"\")");
706 provision.getMapping().add(loginDateForJexlAsString);
707
708
709 Item loginDateForJavaToLong = new Item();
710 loginDateForJavaToLong.setPurpose(MappingPurpose.PROPAGATION);
711 loginDateForJavaToLong.setIntAttrName("loginDate");
712 loginDateForJavaToLong.setExtAttrName("st");
713 loginDateForJavaToLong.getTransformers().add(DateToLongItemTransformer.class.getSimpleName());
714 provision.getMapping().add(loginDateForJavaToLong);
715
716
717 Item loginDateForJavaToDate = new Item();
718 loginDateForJavaToDate.setPurpose(MappingPurpose.PROPAGATION);
719 loginDateForJavaToDate.setIntAttrName("loginDate");
720 loginDateForJavaToDate.setExtAttrName("carLicense");
721 loginDateForJavaToDate.getTransformers().add(DateToDateItemTransformer.class.getSimpleName());
722 provision.getMapping().add(loginDateForJavaToDate);
723
724 ldap.getProvisions().clear();
725 ldap.getProvisions().add(provision);
726 ldap.setKey(RESOURCE_NAME_LDAP + "1430" + getUUIDString());
727 RESOURCE_SERVICE.create(ldap);
728
729
730 UserCR createReq = UserITCase.getUniqueSample("syncope1430@syncope.apache.org");
731 createReq.getResources().clear();
732 createReq.getResources().add(ldap.getKey());
733 createReq.getPlainAttrs().removeIf(attr -> "loginDate".equals(attr.getSchema()));
734 createReq.getPlainAttrs().add(attr("loginDate", "2019-01-29"));
735 UserTO user = createUser(createReq).getEntity();
736
737
738 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
739 resource(user.getResources().iterator().next()).
740 anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
741 assertEquals(1, tasks.getSize());
742
743 Set<Attribute> propagationAttrs = new HashSet<>();
744 if (StringUtils.isNotBlank(tasks.getResult().get(0).getPropagationData())) {
745 propagationAttrs.addAll(POJOHelper.deserialize(
746 tasks.getResult().get(0).getPropagationData(), PropagationData.class).getAttributes());
747 }
748
749 OffsetDateTime loginDate = LocalDate.parse(user.getPlainAttr("loginDate").get().getValues().get(0)).
750 atStartOfDay(ZoneOffset.UTC).toOffsetDateTime();
751
752 Attribute employeeNumber = AttributeUtil.find("employeeNumber", propagationAttrs);
753 assertNotNull(employeeNumber);
754 assertEquals(loginDate.toInstant().toEpochMilli(), employeeNumber.getValue().get(0));
755
756 Attribute street = AttributeUtil.find("street", propagationAttrs);
757 assertNotNull(street);
758 assertEquals(loginDate.toInstant().toString().split("T")[0].replace("-", ""), street.getValue().get(0));
759
760 Attribute st = AttributeUtil.find("st", propagationAttrs);
761 assertNotNull(st);
762 assertEquals(loginDate.toInstant().toEpochMilli(), st.getValue().get(0));
763
764 Attribute carLicense = AttributeUtil.find("carLicense", propagationAttrs);
765 assertNotNull(carLicense);
766 assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.format(loginDate.plusDays(1)), carLicense.getValue().get(0));
767 } finally {
768 try {
769 RESOURCE_SERVICE.delete(ldap.getKey());
770 } catch (Exception ignore) {
771
772 }
773 }
774 }
775
776 @Test
777 public void issueSYNCOPE1473() throws ParseException {
778
779 PlainSchemaTO schemaTO = new PlainSchemaTO();
780 schemaTO.setKey("ldapGroups" + getUUIDString());
781 schemaTO.setType(AttrSchemaType.String);
782 schemaTO.setMultivalue(true);
783 schemaTO.setReadonly(true);
784 schemaTO.setAnyTypeClass("minimal user");
785
786 schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
787 assertNotNull(schemaTO);
788
789 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
790 UserTO userTO = null;
791 try {
792
793 Provision provisionGroup =
794 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null));
795 assertNotNull(provisionGroup);
796 provisionGroup.getVirSchemas().clear();
797
798 Provision provisionUser =
799 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null));
800 assertNotNull(provisionUser);
801 provisionUser.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName()));
802 provisionUser.getVirSchemas().clear();
803
804 Item ldapGroups = new Item();
805 ldapGroups.setPurpose(MappingPurpose.PROPAGATION);
806 ldapGroups.setIntAttrName(schemaTO.getKey());
807 ldapGroups.setExtAttrName("ldapGroups");
808 provisionUser.getMapping().add(ldapGroups);
809
810 ldap.getProvisions().clear();
811 ldap.getProvisions().add(provisionUser);
812 ldap.getProvisions().add(provisionGroup);
813 ldap.setKey(RESOURCE_NAME_LDAP + "1473" + getUUIDString());
814 RESOURCE_SERVICE.create(ldap);
815
816
817 GroupCR groupCR = new GroupCR();
818 groupCR.setName("SYNCOPEGROUP1473-" + getUUIDString());
819 groupCR.setRealm(SyncopeConstants.ROOT_REALM);
820 groupCR.getResources().add(ldap.getKey());
821
822 GroupTO groupTO = createGroup(groupCR).getEntity();
823 assertNotNull(groupCR);
824
825
826 UserCR userCR = UserITCase.getUniqueSample("syncope1473@syncope.apache.org");
827 userCR.getResources().clear();
828 userCR.getResources().add(ldap.getKey());
829 userCR.getMemberships().add(new MembershipTO.Builder(groupTO.getKey()).build());
830
831 userTO = createUser(userCR).getEntity();
832 assertNotNull(userTO);
833
834
835 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
836 resource(userTO.getResources().iterator().next()).
837 anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build());
838 assertEquals(1, tasks.getSize());
839
840 ResourceDR resourceDR = new ResourceDR.Builder().key(groupTO.getKey()).
841 action(ResourceDeassociationAction.UNLINK).resource(ldap.getKey()).build();
842
843 GROUP_SERVICE.deassociate(resourceDR);
844 GROUP_SERVICE.delete(groupTO.getKey());
845
846 GroupCR newGroupCR = new GroupCR();
847 newGroupCR.setName("NEWSYNCOPEGROUP1473-" + getUUIDString());
848 newGroupCR.setRealm(SyncopeConstants.ROOT_REALM);
849 newGroupCR.getResources().add(ldap.getKey());
850
851 GroupTO newGroupTO = createGroup(newGroupCR).getEntity();
852 assertNotNull(newGroupTO);
853
854 UserUR userUR = new UserUR();
855 userUR.setKey(userTO.getKey());
856 userUR.getMemberships().add(
857 new MembershipUR.Builder(newGroupTO.getKey()).operation(PatchOperation.ADD_REPLACE).build());
858 USER_SERVICE.update(userUR);
859
860 ConnObject connObject =
861 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey());
862 assertNotNull(connObject);
863 assertTrue(connObject.getAttr("ldapGroups").isPresent());
864 assertEquals(2, connObject.getAttr("ldapGroups").get().getValues().size());
865 } finally {
866 try {
867 RESOURCE_SERVICE.delete(ldap.getKey());
868 if (userTO != null) {
869 USER_SERVICE.delete(userTO.getKey());
870 }
871 SCHEMA_SERVICE.delete(SchemaType.PLAIN, schemaTO.getKey());
872 } catch (Exception ignore) {
873
874 }
875 }
876 }
877
878 @Test
879 public void issueSYNCOPE1567() {
880 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
881 try {
882
883 Provision provisionUser =
884 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null));
885 assertNotNull(provisionUser);
886 provisionUser.getVirSchemas().clear();
887
888 Item relationships = new Item();
889 relationships.setPurpose(MappingPurpose.PROPAGATION);
890 relationships.setIntAttrName("relationships[neighborhood][PRINTER].model");
891 relationships.setExtAttrName("l");
892 provisionUser.getMapping().add(relationships);
893
894 ldap.getProvisions().clear();
895 ldap.getProvisions().add(provisionUser);
896 ldap.setKey(RESOURCE_NAME_LDAP + "1567" + getUUIDString());
897 RESOURCE_SERVICE.create(ldap);
898
899
900 UserCR userCR = UserITCase.getUniqueSample("syncope1567@syncope.apache.org");
901 userCR.getRelationships().add(new RelationshipTO.Builder("neighborhood").
902 otherEnd(PRINTER, "fc6dbc3a-6c07-4965-8781-921e7401a4a5").build());
903 userCR.getResources().clear();
904 userCR.getResources().add(ldap.getKey());
905
906 UserTO userTO = createUser(userCR).getEntity();
907 assertNotNull(userTO);
908 assertFalse(userTO.getRelationships().isEmpty());
909
910
911 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
912 resource(userCR.getResources().iterator().next()).
913 anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build());
914 assertEquals(1, tasks.getSize());
915
916 Set<Attribute> propagationAttrs = POJOHelper.deserialize(
917 tasks.getResult().get(0).getPropagationData(), PropagationData.class).getAttributes();
918 Attribute attr = AttributeUtil.find("l", propagationAttrs);
919 assertNotNull(attr);
920 assertNotNull(attr.getValue());
921 assertEquals("Canon MFC8030", attr.getValue().get(0).toString());
922
923
924 ConnObject connObject =
925 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey());
926 assertNotNull(connObject);
927 assertTrue(connObject.getAttr("l").isPresent());
928 assertEquals("Canon MFC8030", connObject.getAttr("l").get().getValues().get(0));
929 } finally {
930 try {
931 RESOURCE_SERVICE.delete(ldap.getKey());
932 } catch (Exception ignore) {
933
934 }
935 }
936 }
937
938 @Test
939 public void issueSYNCOPE1605() throws ParseException {
940 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
941 try {
942
943 Provision provisionGroup =
944 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null));
945 assertNotNull(provisionGroup);
946 provisionGroup.getVirSchemas().clear();
947 provisionGroup.getMapping().getItems().clear();
948
949 Item item = new Item();
950 item.setConnObjectKey(true);
951 item.setIntAttrName("name");
952 item.setExtAttrName("description");
953 item.setPurpose(MappingPurpose.BOTH);
954
955 provisionGroup.getMapping().setConnObjectKeyItem(item);
956 provisionGroup.getMapping().setConnObjectLink("'cn=' + originalName + ',ou=groups,o=isp'");
957
958 ldap.getProvisions().clear();
959 ldap.getProvisions().add(provisionGroup);
960
961 ldap.setKey(RESOURCE_NAME_LDAP + "1605" + getUUIDString());
962 RESOURCE_SERVICE.create(ldap);
963
964
965 String originalName = "grp1605-" + getUUIDString();
966
967 GroupCR groupCR = new GroupCR();
968 groupCR.setName("SYNCOPEGROUP1605-" + getUUIDString());
969 groupCR.setRealm(SyncopeConstants.ROOT_REALM);
970 groupCR.getResources().add(ldap.getKey());
971 groupCR.getPlainAttrs().add(new Attr.Builder("originalName").value(originalName).build());
972
973 GroupTO groupTO = createGroup(groupCR).getEntity();
974 assertNotNull(groupTO);
975
976
977 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
978 resource(ldap.getKey()).anyTypeKind(AnyTypeKind.GROUP).entityKey(groupTO.getKey()).build());
979 assertEquals(1, tasks.getSize());
980 assertEquals(ResourceOperation.CREATE, tasks.getResult().get(0).getOperation());
981 assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus());
982
983 ConnObject beforeConnObject =
984 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.GROUP.name(), groupTO.getKey());
985
986 GroupUR groupUR = new GroupUR();
987 groupUR.setKey(groupTO.getKey());
988
989 groupUR.getPlainAttrs().add(attrAddReplacePatch("originalName", "new" + originalName));
990 groupTO = updateGroup(groupUR).getEntity();
991
992 tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
993 resource(ldap.getKey()).anyTypeKind(AnyTypeKind.GROUP).entityKey(groupTO.getKey()).
994 orderBy("start DESC").build());
995 assertEquals(2, tasks.getSize());
996 assertEquals(ResourceOperation.UPDATE, tasks.getResult().get(0).getOperation());
997 assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus());
998
999 ConnObject afterConnObject =
1000 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.GROUP.name(), groupTO.getKey());
1001 assertNotEquals(afterConnObject.getAttr(Name.NAME).get().getValues().get(0),
1002 beforeConnObject.getAttr(Name.NAME).get().getValues().get(0));
1003 assertTrue(afterConnObject.getAttr(Name.NAME).get().getValues().get(0).contains("new" + originalName));
1004 } finally {
1005 try {
1006 RESOURCE_SERVICE.delete(ldap.getKey());
1007 } catch (Exception ignore) {
1008
1009 }
1010 }
1011 }
1012
1013 @Test
1014 public void issueSYNCOPE1751() {
1015
1016 GroupTO groupTO = createGroup(
1017 new GroupCR.Builder(SyncopeConstants.ROOT_REALM, "SYNCOPEGROUP1751-" + getUUIDString()).
1018 resource(RESOURCE_NAME_LDAP).build()).getEntity();
1019
1020 String username = "SYNCOPEUSER1751" + getUUIDString();
1021 UserTO userTO = createUser(
1022 new UserCR.Builder(SyncopeConstants.ROOT_REALM, username).plainAttrs(
1023 new Attr.Builder("userId").value(username + "@syncope.org").build(),
1024 new Attr.Builder("fullname").value(username).build(),
1025 new Attr.Builder("surname").value(username).build()).
1026 build()).getEntity();
1027
1028 userTO = updateUser(
1029 new UserUR.Builder(userTO.getKey()).
1030 membership(new MembershipUR.Builder(groupTO.getKey()).build()).
1031 build()).getEntity();
1032
1033
1034 PagedResult<TaskTO> propTasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
1035 resource(RESOURCE_NAME_LDAP).anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build());
1036 assertFalse(propTasks.getResult().isEmpty());
1037 assertEquals(1, propTasks.getSize());
1038 PropagationData propagationData = POJOHelper.deserialize(
1039 PropagationTaskTO.class.cast(propTasks.getResult().get(0)).getPropagationData(),
1040 PropagationData.class);
1041 assertTrue(propagationData.getAttributes().stream().
1042 anyMatch(a -> OperationalAttributes.PASSWORD_NAME.equals(a.getName())));
1043 }
1044 }