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().key("1e697572-b896-484c-ae7f-0c8f63fcbc6c").build());
572 TASK_SERVICE.execute(new ExecSpecs.Builder().key("316285cc-ae52-4ea2-a33b-7355e189ac3f").build());
573 }
574 try {
575 Thread.sleep(3000);
576 } catch (InterruptedException e) {
577
578 }
579
580
581 PagedResult<TaskTO> tasks = TASK_SERVICE.search(
582 new TaskQuery.Builder(TaskType.PROPAGATION).
583 page(1).size(2).orderBy("operation DESC").details(false).build());
584 for (TaskTO item : tasks.getResult()) {
585 assertTrue(item.getExecutions().isEmpty());
586 }
587
588 tasks = TASK_SERVICE.search(
589 new TaskQuery.Builder(TaskType.PROPAGATION).
590 page(1).size(2).orderBy("operation DESC").details(true).build());
591 for (TaskTO item : tasks.getResult()) {
592 assertFalse(item.getExecutions().isEmpty());
593 }
594
595
596 PropagationTaskTO task = TASK_SERVICE.read(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c", false);
597 assertNotNull(task);
598 assertEquals("1e697572-b896-484c-ae7f-0c8f63fcbc6c", task.getKey());
599 assertTrue(task.getExecutions().isEmpty());
600
601 task = TASK_SERVICE.read(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c", true);
602 assertNotNull(task);
603 assertEquals("1e697572-b896-484c-ae7f-0c8f63fcbc6c", task.getKey());
604 assertFalse(task.getExecutions().isEmpty());
605
606
607 PagedResult<ExecTO> execs = TASK_SERVICE.listExecutions(new ExecQuery.Builder().
608 key("1e697572-b896-484c-ae7f-0c8f63fcbc6c").
609 before(OffsetDateTime.now().plusSeconds(30)).
610 page(1).size(2).build());
611 assertTrue(execs.getTotalCount() >= execs.getResult().size());
612 }
613
614 @Test
615 public void issueSYNCOPE1288() {
616
617 UserCR userCR = UserITCase.getUniqueSample("xxxyyy@xxx.xxx");
618 userCR.getResources().add(RESOURCE_NAME_LDAP);
619
620 UserTO userTO = createUser(userCR).getEntity();
621 assertNotNull(userTO);
622
623
624 for (int i = 0; i < 9; i++) {
625 UserUR userUR = new UserUR();
626 userUR.setKey(userTO.getKey());
627 userUR.getPlainAttrs().add(new AttrPatch.Builder(new Attr.Builder("userId").value(
628 "test" + getUUIDString() + i + "@test.com").build()).
629 operation(PatchOperation.ADD_REPLACE).
630 build());
631
632 USER_SERVICE.update(userUR);
633 }
634
635
636 PagedResult<TaskTO> unorderedTasks = TASK_SERVICE.search(
637 new TaskQuery.Builder(TaskType.PROPAGATION).
638 resource(RESOURCE_NAME_LDAP).
639 entityKey(userTO.getKey()).
640 anyTypeKind(AnyTypeKind.USER).
641 page(1).
642 size(10).
643 build());
644 Collections.sort(unorderedTasks.getResult(), (t1, t2) -> t1.getStart().compareTo(t2.getStart()));
645 assertNotNull(unorderedTasks);
646 assertFalse(unorderedTasks.getResult().isEmpty());
647 assertEquals(10, unorderedTasks.getResult().size());
648
649 PagedResult<TaskTO> orderedTasks = TASK_SERVICE.search(
650 new TaskQuery.Builder(TaskType.PROPAGATION).
651 resource(RESOURCE_NAME_LDAP).
652 entityKey(userTO.getKey()).
653 anyTypeKind(AnyTypeKind.USER).
654 page(1).
655 size(10).
656 orderBy("start").
657 build());
658 assertNotNull(orderedTasks);
659 assertFalse(orderedTasks.getResult().isEmpty());
660 assertEquals(10, orderedTasks.getResult().size());
661
662 assertTrue(orderedTasks.getResult().equals(unorderedTasks.getResult()));
663
664
665 Collections.reverse(unorderedTasks.getResult());
666 orderedTasks = TASK_SERVICE.search(
667 new TaskQuery.Builder(TaskType.PROPAGATION).
668 resource(RESOURCE_NAME_LDAP).
669 entityKey(userTO.getKey()).
670 anyTypeKind(AnyTypeKind.USER).
671 page(1).
672 size(10).
673 orderBy("start DESC").
674 build());
675
676 assertTrue(orderedTasks.getResult().equals(unorderedTasks.getResult()));
677 }
678
679 @Test
680 public void issueSYNCOPE1430() throws ParseException {
681 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
682 try {
683
684 Provision provision = ldap.getProvision(AnyTypeKind.USER.name()).orElse(null);
685 assertNotNull(provision);
686 provision.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName()));
687 provision.getVirSchemas().clear();
688
689
690 Item loginDateForJexlAsLong = new Item();
691 loginDateForJexlAsLong.setPurpose(MappingPurpose.PROPAGATION);
692 loginDateForJexlAsLong.setIntAttrName("loginDate");
693 loginDateForJexlAsLong.setExtAttrName("employeeNumber");
694 loginDateForJexlAsLong.setPropagationJEXLTransformer("value.toInstant().toEpochMilli()");
695 provision.getMapping().add(loginDateForJexlAsLong);
696
697
698 Item loginDateForJexlAsString = new Item();
699 loginDateForJexlAsString.setPurpose(MappingPurpose.PROPAGATION);
700 loginDateForJexlAsString.setIntAttrName("loginDate");
701 loginDateForJexlAsString.setExtAttrName("street");
702 loginDateForJexlAsString.setPropagationJEXLTransformer(
703 "value.toInstant().toString().split(\"T\")[0].replace(\"-\", \"\")");
704 provision.getMapping().add(loginDateForJexlAsString);
705
706
707 Item loginDateForJavaToLong = new Item();
708 loginDateForJavaToLong.setPurpose(MappingPurpose.PROPAGATION);
709 loginDateForJavaToLong.setIntAttrName("loginDate");
710 loginDateForJavaToLong.setExtAttrName("st");
711 loginDateForJavaToLong.getTransformers().add(DateToLongItemTransformer.class.getSimpleName());
712 provision.getMapping().add(loginDateForJavaToLong);
713
714
715 Item loginDateForJavaToDate = new Item();
716 loginDateForJavaToDate.setPurpose(MappingPurpose.PROPAGATION);
717 loginDateForJavaToDate.setIntAttrName("loginDate");
718 loginDateForJavaToDate.setExtAttrName("carLicense");
719 loginDateForJavaToDate.getTransformers().add(DateToDateItemTransformer.class.getSimpleName());
720 provision.getMapping().add(loginDateForJavaToDate);
721
722 ldap.getProvisions().clear();
723 ldap.getProvisions().add(provision);
724 ldap.setKey(RESOURCE_NAME_LDAP + "1430" + getUUIDString());
725 RESOURCE_SERVICE.create(ldap);
726
727
728 UserCR createReq = UserITCase.getUniqueSample("syncope1430@syncope.apache.org");
729 createReq.getResources().clear();
730 createReq.getResources().add(ldap.getKey());
731 createReq.getPlainAttrs().removeIf(attr -> "loginDate".equals(attr.getSchema()));
732 createReq.getPlainAttrs().add(attr("loginDate", "2019-01-29"));
733 UserTO user = createUser(createReq).getEntity();
734
735
736 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
737 resource(user.getResources().iterator().next()).
738 anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
739 assertEquals(1, tasks.getSize());
740
741 Set<Attribute> propagationAttrs = new HashSet<>();
742 if (StringUtils.isNotBlank(tasks.getResult().get(0).getPropagationData())) {
743 propagationAttrs.addAll(POJOHelper.deserialize(
744 tasks.getResult().get(0).getPropagationData(), PropagationData.class).getAttributes());
745 }
746
747 OffsetDateTime loginDate = LocalDate.parse(user.getPlainAttr("loginDate").get().getValues().get(0)).
748 atStartOfDay(ZoneOffset.UTC).toOffsetDateTime();
749
750 Attribute employeeNumber = AttributeUtil.find("employeeNumber", propagationAttrs);
751 assertNotNull(employeeNumber);
752 assertEquals(loginDate.toInstant().toEpochMilli(), employeeNumber.getValue().get(0));
753
754 Attribute street = AttributeUtil.find("street", propagationAttrs);
755 assertNotNull(street);
756 assertEquals(loginDate.toInstant().toString().split("T")[0].replace("-", ""), street.getValue().get(0));
757
758 Attribute st = AttributeUtil.find("st", propagationAttrs);
759 assertNotNull(st);
760 assertEquals(loginDate.toInstant().toEpochMilli(), st.getValue().get(0));
761
762 Attribute carLicense = AttributeUtil.find("carLicense", propagationAttrs);
763 assertNotNull(carLicense);
764 assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.format(loginDate.plusDays(1)), carLicense.getValue().get(0));
765 } finally {
766 try {
767 RESOURCE_SERVICE.delete(ldap.getKey());
768 } catch (Exception ignore) {
769
770 }
771 }
772 }
773
774 @Test
775 public void issueSYNCOPE1473() throws ParseException {
776
777 PlainSchemaTO schemaTO = new PlainSchemaTO();
778 schemaTO.setKey("ldapGroups" + getUUIDString());
779 schemaTO.setType(AttrSchemaType.String);
780 schemaTO.setMultivalue(true);
781 schemaTO.setReadonly(true);
782 schemaTO.setAnyTypeClass("minimal user");
783
784 schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
785 assertNotNull(schemaTO);
786
787 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
788 UserTO userTO = null;
789 try {
790
791 Provision provisionGroup =
792 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null));
793 assertNotNull(provisionGroup);
794 provisionGroup.getVirSchemas().clear();
795
796 Provision provisionUser =
797 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null));
798 assertNotNull(provisionUser);
799 provisionUser.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName()));
800 provisionUser.getVirSchemas().clear();
801
802 Item ldapGroups = new Item();
803 ldapGroups.setPurpose(MappingPurpose.PROPAGATION);
804 ldapGroups.setIntAttrName(schemaTO.getKey());
805 ldapGroups.setExtAttrName("ldapGroups");
806 provisionUser.getMapping().add(ldapGroups);
807
808 ldap.getProvisions().clear();
809 ldap.getProvisions().add(provisionUser);
810 ldap.getProvisions().add(provisionGroup);
811 ldap.setKey(RESOURCE_NAME_LDAP + "1473" + getUUIDString());
812 RESOURCE_SERVICE.create(ldap);
813
814
815 GroupCR groupCR = new GroupCR();
816 groupCR.setName("SYNCOPEGROUP1473-" + getUUIDString());
817 groupCR.setRealm(SyncopeConstants.ROOT_REALM);
818 groupCR.getResources().add(ldap.getKey());
819
820 GroupTO groupTO = createGroup(groupCR).getEntity();
821 assertNotNull(groupCR);
822
823
824 UserCR userCR = UserITCase.getUniqueSample("syncope1473@syncope.apache.org");
825 userCR.getResources().clear();
826 userCR.getResources().add(ldap.getKey());
827 userCR.getMemberships().add(new MembershipTO.Builder(groupTO.getKey()).build());
828
829 userTO = createUser(userCR).getEntity();
830 assertNotNull(userTO);
831
832
833 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
834 resource(userTO.getResources().iterator().next()).
835 anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build());
836 assertEquals(1, tasks.getSize());
837
838 ResourceDR resourceDR = new ResourceDR.Builder().key(groupTO.getKey()).
839 action(ResourceDeassociationAction.UNLINK).resource(ldap.getKey()).build();
840
841 GROUP_SERVICE.deassociate(resourceDR);
842 GROUP_SERVICE.delete(groupTO.getKey());
843
844 GroupCR newGroupCR = new GroupCR();
845 newGroupCR.setName("NEWSYNCOPEGROUP1473-" + getUUIDString());
846 newGroupCR.setRealm(SyncopeConstants.ROOT_REALM);
847 newGroupCR.getResources().add(ldap.getKey());
848
849 GroupTO newGroupTO = createGroup(newGroupCR).getEntity();
850 assertNotNull(newGroupTO);
851
852 UserUR userUR = new UserUR();
853 userUR.setKey(userTO.getKey());
854 userUR.getMemberships().add(
855 new MembershipUR.Builder(newGroupTO.getKey()).operation(PatchOperation.ADD_REPLACE).build());
856 USER_SERVICE.update(userUR);
857
858 ConnObject connObject =
859 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey());
860 assertNotNull(connObject);
861 assertTrue(connObject.getAttr("ldapGroups").isPresent());
862 assertEquals(2, connObject.getAttr("ldapGroups").get().getValues().size());
863 } finally {
864 try {
865 RESOURCE_SERVICE.delete(ldap.getKey());
866 if (userTO != null) {
867 USER_SERVICE.delete(userTO.getKey());
868 }
869 SCHEMA_SERVICE.delete(SchemaType.PLAIN, schemaTO.getKey());
870 } catch (Exception ignore) {
871
872 }
873 }
874 }
875
876 @Test
877 public void issueSYNCOPE1567() {
878 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
879 try {
880
881 Provision provisionUser =
882 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null));
883 assertNotNull(provisionUser);
884 provisionUser.getVirSchemas().clear();
885
886 Item relationships = new Item();
887 relationships.setPurpose(MappingPurpose.PROPAGATION);
888 relationships.setIntAttrName("relationships[neighborhood][PRINTER].model");
889 relationships.setExtAttrName("l");
890 provisionUser.getMapping().add(relationships);
891
892 ldap.getProvisions().clear();
893 ldap.getProvisions().add(provisionUser);
894 ldap.setKey(RESOURCE_NAME_LDAP + "1567" + getUUIDString());
895 RESOURCE_SERVICE.create(ldap);
896
897
898 UserCR userCR = UserITCase.getUniqueSample("syncope1567@syncope.apache.org");
899 userCR.getRelationships().add(new RelationshipTO.Builder("neighborhood").
900 otherEnd(PRINTER, "fc6dbc3a-6c07-4965-8781-921e7401a4a5").build());
901 userCR.getResources().clear();
902 userCR.getResources().add(ldap.getKey());
903
904 UserTO userTO = createUser(userCR).getEntity();
905 assertNotNull(userTO);
906 assertFalse(userTO.getRelationships().isEmpty());
907
908
909 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
910 resource(userCR.getResources().iterator().next()).
911 anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build());
912 assertEquals(1, tasks.getSize());
913
914 Set<Attribute> propagationAttrs = POJOHelper.deserialize(
915 tasks.getResult().get(0).getPropagationData(), PropagationData.class).getAttributes();
916 Attribute attr = AttributeUtil.find("l", propagationAttrs);
917 assertNotNull(attr);
918 assertNotNull(attr.getValue());
919 assertEquals("Canon MFC8030", attr.getValue().get(0).toString());
920
921
922 ConnObject connObject =
923 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey());
924 assertNotNull(connObject);
925 assertTrue(connObject.getAttr("l").isPresent());
926 assertEquals("Canon MFC8030", connObject.getAttr("l").get().getValues().get(0));
927 } finally {
928 try {
929 RESOURCE_SERVICE.delete(ldap.getKey());
930 } catch (Exception ignore) {
931
932 }
933 }
934 }
935
936 @Test
937 public void issueSYNCOPE1605() throws ParseException {
938 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
939 try {
940
941 Provision provisionGroup =
942 SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null));
943 assertNotNull(provisionGroup);
944 provisionGroup.getVirSchemas().clear();
945 provisionGroup.getMapping().getItems().clear();
946
947 Item item = new Item();
948 item.setConnObjectKey(true);
949 item.setIntAttrName("name");
950 item.setExtAttrName("description");
951 item.setPurpose(MappingPurpose.BOTH);
952
953 provisionGroup.getMapping().setConnObjectKeyItem(item);
954 provisionGroup.getMapping().setConnObjectLink("'cn=' + originalName + ',ou=groups,o=isp'");
955
956 ldap.getProvisions().clear();
957 ldap.getProvisions().add(provisionGroup);
958
959 ldap.setKey(RESOURCE_NAME_LDAP + "1605" + getUUIDString());
960 RESOURCE_SERVICE.create(ldap);
961
962
963 String originalName = "grp1605-" + getUUIDString();
964
965 GroupCR groupCR = new GroupCR();
966 groupCR.setName("SYNCOPEGROUP1605-" + getUUIDString());
967 groupCR.setRealm(SyncopeConstants.ROOT_REALM);
968 groupCR.getResources().add(ldap.getKey());
969 groupCR.getPlainAttrs().add(new Attr.Builder("originalName").value(originalName).build());
970
971 GroupTO groupTO = createGroup(groupCR).getEntity();
972 assertNotNull(groupTO);
973
974
975 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
976 resource(ldap.getKey()).anyTypeKind(AnyTypeKind.GROUP).entityKey(groupTO.getKey()).build());
977 assertEquals(1, tasks.getSize());
978 assertEquals(ResourceOperation.CREATE, tasks.getResult().get(0).getOperation());
979 assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus());
980
981 ConnObject beforeConnObject =
982 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.GROUP.name(), groupTO.getKey());
983
984 GroupUR groupUR = new GroupUR();
985 groupUR.setKey(groupTO.getKey());
986
987 groupUR.getPlainAttrs().add(attrAddReplacePatch("originalName", "new" + originalName));
988 groupTO = updateGroup(groupUR).getEntity();
989
990 tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
991 resource(ldap.getKey()).anyTypeKind(AnyTypeKind.GROUP).entityKey(groupTO.getKey()).
992 orderBy("start DESC").build());
993 assertEquals(2, tasks.getSize());
994 assertEquals(ResourceOperation.UPDATE, tasks.getResult().get(0).getOperation());
995 assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus());
996
997 ConnObject afterConnObject =
998 RESOURCE_SERVICE.readConnObject(ldap.getKey(), AnyTypeKind.GROUP.name(), groupTO.getKey());
999 assertNotEquals(afterConnObject.getAttr(Name.NAME).get().getValues().get(0),
1000 beforeConnObject.getAttr(Name.NAME).get().getValues().get(0));
1001 assertTrue(afterConnObject.getAttr(Name.NAME).get().getValues().get(0).contains("new" + originalName));
1002 } finally {
1003 try {
1004 RESOURCE_SERVICE.delete(ldap.getKey());
1005 } catch (Exception ignore) {
1006
1007 }
1008 }
1009 }
1010
1011 @Test
1012 public void issueSYNCOPE1751() {
1013
1014 GroupTO groupTO = createGroup(
1015 new GroupCR.Builder(SyncopeConstants.ROOT_REALM, "SYNCOPEGROUP1751-" + getUUIDString()).
1016 resource(RESOURCE_NAME_LDAP).build()).getEntity();
1017
1018 String username = "SYNCOPEUSER1751" + getUUIDString();
1019 UserTO userTO = createUser(
1020 new UserCR.Builder(SyncopeConstants.ROOT_REALM, username).plainAttrs(
1021 new Attr.Builder("userId").value(username + "@syncope.org").build(),
1022 new Attr.Builder("fullname").value(username).build(),
1023 new Attr.Builder("surname").value(username).build()).
1024 build()).getEntity();
1025
1026 userTO = updateUser(
1027 new UserUR.Builder(userTO.getKey()).
1028 membership(new MembershipUR.Builder(groupTO.getKey()).build()).
1029 build()).getEntity();
1030
1031
1032 PagedResult<TaskTO> propTasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
1033 resource(RESOURCE_NAME_LDAP).anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build());
1034 assertFalse(propTasks.getResult().isEmpty());
1035 assertEquals(1, propTasks.getSize());
1036 PropagationData propagationData = POJOHelper.deserialize(
1037 PropagationTaskTO.class.cast(propTasks.getResult().get(0)).getPropagationData(),
1038 PropagationData.class);
1039 assertTrue(propagationData.getAttributes().stream().
1040 anyMatch(a -> OperationalAttributes.PASSWORD_NAME.equals(a.getName())));
1041 }
1042 }