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.junit.jupiter.api.Assertions.assertDoesNotThrow;
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.assertNotNull;
25 import static org.junit.jupiter.api.Assertions.assertNull;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.junit.jupiter.api.Assertions.fail;
29 import static org.junit.jupiter.api.Assumptions.assumeTrue;
30
31 import java.io.IOException;
32 import java.security.AccessControlException;
33 import java.time.OffsetDateTime;
34 import java.time.format.DateTimeFormatter;
35 import java.util.ArrayList;
36 import java.util.Comparator;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.UUID;
41 import java.util.function.Function;
42 import java.util.stream.Collectors;
43 import javax.ws.rs.core.GenericType;
44 import javax.ws.rs.core.Response;
45 import org.apache.commons.lang3.RandomStringUtils;
46 import org.apache.commons.lang3.tuple.Triple;
47 import org.apache.cxf.jaxrs.client.WebClient;
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.AccountPolicyTO;
54 import org.apache.syncope.common.lib.policy.HaveIBeenPwnedPasswordRuleConf;
55 import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
56 import org.apache.syncope.common.lib.request.AttrPatch;
57 import org.apache.syncope.common.lib.request.MembershipUR;
58 import org.apache.syncope.common.lib.request.PasswordPatch;
59 import org.apache.syncope.common.lib.request.ResourceAR;
60 import org.apache.syncope.common.lib.request.ResourceDR;
61 import org.apache.syncope.common.lib.request.StatusR;
62 import org.apache.syncope.common.lib.request.StringReplacePatchItem;
63 import org.apache.syncope.common.lib.request.UserCR;
64 import org.apache.syncope.common.lib.request.UserUR;
65 import org.apache.syncope.common.lib.to.ConnObject;
66 import org.apache.syncope.common.lib.to.ImplementationTO;
67 import org.apache.syncope.common.lib.to.MembershipTO;
68 import org.apache.syncope.common.lib.to.PagedResult;
69 import org.apache.syncope.common.lib.to.PropagationStatus;
70 import org.apache.syncope.common.lib.to.PropagationTaskTO;
71 import org.apache.syncope.common.lib.to.ProvisioningResult;
72 import org.apache.syncope.common.lib.to.RealmTO;
73 import org.apache.syncope.common.lib.to.ResourceTO;
74 import org.apache.syncope.common.lib.to.UserTO;
75 import org.apache.syncope.common.lib.types.AnyTypeKind;
76 import org.apache.syncope.common.lib.types.ClientExceptionType;
77 import org.apache.syncope.common.lib.types.ExecStatus;
78 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
79 import org.apache.syncope.common.lib.types.ImplementationEngine;
80 import org.apache.syncope.common.lib.types.PatchOperation;
81 import org.apache.syncope.common.lib.types.PolicyType;
82 import org.apache.syncope.common.lib.types.ResourceAssociationAction;
83 import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
84 import org.apache.syncope.common.lib.types.StatusRType;
85 import org.apache.syncope.common.lib.types.TaskType;
86 import org.apache.syncope.common.rest.api.RESTHeaders;
87 import org.apache.syncope.common.rest.api.batch.BatchResponseItem;
88 import org.apache.syncope.common.rest.api.beans.AnyQuery;
89 import org.apache.syncope.common.rest.api.beans.ComplianceQuery;
90 import org.apache.syncope.common.rest.api.beans.RealmQuery;
91 import org.apache.syncope.common.rest.api.beans.TaskQuery;
92 import org.apache.syncope.common.rest.api.service.ResourceService;
93 import org.apache.syncope.common.rest.api.service.UserSelfService;
94 import org.apache.syncope.common.rest.api.service.UserService;
95 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
96 import org.apache.syncope.fit.AbstractITCase;
97 import org.apache.syncope.fit.core.reference.TestAccountRuleConf;
98 import org.apache.syncope.fit.core.reference.TestPasswordRuleConf;
99 import org.identityconnectors.framework.common.objects.OperationalAttributes;
100 import org.junit.jupiter.api.Test;
101
102 public class UserITCase extends AbstractITCase {
103
104 private static boolean getBooleanAttribute(final ConnObject connObjectTO, final String attrName) {
105 return Boolean.parseBoolean(connObjectTO.getAttr(attrName).get().getValues().get(0));
106 }
107
108 public static UserCR getUniqueSample(final String email) {
109 return getSample(getUUIDString() + email);
110 }
111
112 public static UserCR getSample(final String email) {
113 return new UserCR.Builder(SyncopeConstants.ROOT_REALM, email).
114 password("password123").
115 plainAttr(attr("fullname", email)).
116 plainAttr(attr("firstname", email)).
117 plainAttr(attr("surname", "surname")).
118 plainAttr(attr("ctype", "a type")).
119 plainAttr(attr("userId", email)).
120 plainAttr(attr("email", email)).
121 plainAttr(attr("loginDate", DateTimeFormatter.ISO_LOCAL_DATE.format(OffsetDateTime.now()))).
122 build();
123 }
124
125 @Test
126 public void readPrivileges() {
127 Set<String> privileges = USER_SERVICE.read("rossini").getPrivileges();
128 assertNotNull(privileges);
129 assertEquals(1, privileges.size());
130 }
131
132 @Test
133 public void createUserWithNoPropagation() {
134
135 UserCR req = getUniqueSample("xxx@xxx.xxx");
136 req.setPassword("password123");
137 req.getResources().add(RESOURCE_NAME_NOPROPAGATION);
138
139 UserTO userTO = createUser(req).getEntity();
140
141
142 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).
143 anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).page(1).size(1).build());
144 assertNotNull(tasks);
145 assertFalse(tasks.getResult().isEmpty());
146
147 PropagationTaskTO taskTO = tasks.getResult().get(0);
148 assertNotNull(taskTO);
149 assertFalse(taskTO.getExecutions().isEmpty());
150 assertEquals(ExecStatus.NOT_ATTEMPTED.name(), taskTO.getExecutions().get(0).getStatus());
151 }
152
153 @Test
154 public void enforceMandatoryCondition() {
155 UserCR userCR = getUniqueSample("enforce@apache.org");
156 userCR.getResources().add(RESOURCE_NAME_WS2);
157 userCR.setPassword("newPassword12");
158
159 Attr type = null;
160 for (Attr attr : userCR.getPlainAttrs()) {
161 if ("ctype".equals(attr.getSchema())) {
162 type = attr;
163 }
164 }
165 assertNotNull(type);
166 userCR.getPlainAttrs().remove(type);
167
168 try {
169 createUser(userCR).getEntity();
170 fail("This should not happen");
171 } catch (SyncopeClientException e) {
172 assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
173 }
174
175 userCR.getPlainAttrs().add(type);
176 UserTO userTO = createUser(userCR).getEntity();
177 assertNotNull(userTO);
178 }
179
180 @Test
181 public void enforceMandatoryConditionOnDerived() {
182 ResourceTO resourceTO = RESOURCE_SERVICE.read(RESOURCE_NAME_CSV);
183 assertNotNull(resourceTO);
184 resourceTO.setKey("resource-csv-enforcing");
185 resourceTO.setEnforceMandatoryCondition(true);
186
187 Response response = RESOURCE_SERVICE.create(resourceTO);
188 resourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
189 assertNotNull(resourceTO);
190
191 try {
192 UserCR userCR = getUniqueSample("syncope222@apache.org");
193 userCR.getResources().add(resourceTO.getKey());
194 userCR.setPassword("newPassword12");
195
196 try {
197 createUser(userCR).getEntity();
198 fail("This should not happen");
199 } catch (SyncopeClientException e) {
200 assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
201 }
202
203 userCR.getAuxClasses().add("csv");
204
205 UserTO userTO = createUser(userCR).getEntity();
206 assertNotNull(userTO);
207 assertEquals(Set.of(resourceTO.getKey()), userTO.getResources());
208 } finally {
209 RESOURCE_SERVICE.delete(resourceTO.getKey());
210 }
211 }
212
213 @Test
214 public void createUserWithDbPropagation() {
215 UserCR userCR = getUniqueSample("yyy@yyy.yyy");
216 userCR.getResources().add(RESOURCE_NAME_TESTDB);
217 ProvisioningResult<UserTO> result = createUser(userCR);
218 assertNotNull(result);
219 assertEquals(1, result.getPropagationStatuses().size());
220 assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
221 }
222
223 @Test
224 public void createWithInvalidPassword() {
225 assertThrows(SyncopeClientException.class, () -> {
226 UserCR userCR = getSample("invalidpasswd@syncope.apache.org");
227 userCR.setPassword("pass");
228 createUser(userCR);
229 });
230 }
231
232 @Test
233 public void createWithInvalidUsername() {
234 assertThrows(SyncopeClientException.class, () -> {
235 UserCR userCR = getSample("invalidusername@syncope.apache.org");
236 userCR.setUsername("us");
237 userCR.setRealm("/odd");
238
239 createUser(userCR);
240 });
241 }
242
243 @Test
244 public void createWithInvalidPasswordByRes() {
245 assertThrows(SyncopeClientException.class, () -> {
246 UserCR userCR = getSample("invalidPwdByRes@passwd.com");
247
248
249 userCR.setPassword("password1");
250 userCR.getResources().add(RESOURCE_NAME_NOPROPAGATION);
251 createUser(userCR);
252 });
253 }
254
255 @Test
256 public void createWithInvalidPasswordByGroup() {
257 assertThrows(SyncopeClientException.class, () -> {
258 UserCR userCR = getSample("invalidPwdByGroup@passwd.com");
259
260
261 userCR.setPassword("password1");
262
263 userCR.getMemberships().add(new MembershipTO.Builder("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
264
265 createUser(userCR);
266 });
267 }
268
269 @Test
270 public void createWithException() {
271 assertThrows(SyncopeClientException.class, () -> {
272 UserCR userCR = new UserCR();
273 userCR.getPlainAttrs().add(attr("userId", "userId@nowhere.org"));
274 createUser(userCR);
275 });
276 }
277
278 @Test
279 public void create() {
280
281 PagedResult<PropagationTaskTO> tasks = TASK_SERVICE.search(
282 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1).build());
283 assertNotNull(tasks);
284 assertFalse(tasks.getResult().isEmpty());
285
286 String maxKey = tasks.getResult().iterator().next().getKey();
287 PropagationTaskTO taskTO = TASK_SERVICE.read(TaskType.PROPAGATION, maxKey, true);
288
289 assertNotNull(taskTO);
290 int maxTaskExecutions = taskTO.getExecutions().size();
291
292 UserCR userCR = getUniqueSample("a.b@c.com");
293
294
295 userCR.getMemberships().add(new MembershipTO.Builder("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
296
297
298 Attr attrWithInvalidSchemaTO = attr("invalid schema", "a value");
299 userCR.getPlainAttrs().add(attrWithInvalidSchemaTO);
300
301
302 userCR.getPlainAttrs().add(attr("activationDate", null));
303
304
305 UserTO userTO = createUser(userCR).getEntity();
306
307 assertNotNull(userTO);
308
309
310 assertNotNull(userTO.getCreationDate());
311 assertNotNull(userTO.getCreator());
312 assertNotNull(userTO.getLastChangeDate());
313 assertNotNull(userTO.getLastModifier());
314 assertTrue(userTO.getLastChangeDate().toEpochSecond() - userTO.getCreationDate().toEpochSecond() < 3);
315
316 assertFalse(userTO.getPlainAttrs().contains(attrWithInvalidSchemaTO));
317
318
319 assertNotNull(userTO.getCreationDate());
320
321
322 tasks = TASK_SERVICE.search(new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1).build());
323 assertNotNull(tasks);
324 assertFalse(tasks.getResult().isEmpty());
325
326 String newMaxKey = tasks.getResult().iterator().next().getKey();
327
328
329
330
331 assertEquals(newMaxKey, maxKey);
332
333
334 taskTO = TASK_SERVICE.read(TaskType.PROPAGATION, newMaxKey, true);
335
336 assertNotNull(taskTO);
337 assertEquals(maxTaskExecutions, taskTO.getExecutions().size());
338
339
340 try {
341 Triple<Map<String, Set<String>>, List<String>, UserTO> self =
342 CLIENT_FACTORY.create(userTO.getUsername(), "password123").self();
343 assertNotNull(self);
344 } catch (AccessControlException e) {
345 fail("Credentials should be valid and not cause AccessControlException");
346 }
347
348 try {
349 CLIENT_FACTORY.create(userTO.getUsername(), "passwordXX").getService(UserSelfService.class);
350 fail("Credentials are invalid, thus request should raise AccessControlException");
351 } catch (AccessControlException e) {
352 assertNotNull(e);
353 }
354
355
356 userCR = getSample(userTO.getUsername());
357 Attr userIdAttr = userTO.getPlainAttr("userId").get();
358 userIdAttr.getValues().clear();
359 userIdAttr.getValues().add("a.b@c.com");
360
361 try {
362 createUser(userCR);
363 fail("This should not happen");
364 } catch (SyncopeClientException e) {
365 assertEquals(ClientExceptionType.EntityExists, e.getType());
366 }
367 }
368
369 @Test
370 public void createWithRequiredValueMissing() {
371 UserCR userCR = getUniqueSample("a.b@c.it");
372
373 Attr type = userCR.getPlainAttr("ctype").get();
374 userCR.getPlainAttrs().remove(type);
375
376 userCR.getMemberships().add(new MembershipTO.Builder("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
377
378
379 try {
380 createUser(userCR);
381 fail("This should not happen");
382 } catch (SyncopeClientException e) {
383 assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
384 }
385
386 userCR.getPlainAttrs().add(attr("ctype", "F"));
387
388 Attr surname = userCR.getPlainAttr("surname").get();
389 userCR.getPlainAttrs().remove(surname);
390
391
392 try {
393 createUser(userCR);
394 fail("This should not happen");
395 } catch (SyncopeClientException e) {
396 assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
397 }
398 }
399
400 @Test
401 public void delete() {
402 try {
403 USER_SERVICE.delete(UUID.randomUUID().toString());
404 } catch (SyncopeClientException e) {
405 assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
406 }
407
408 UserCR userCR = getSample("qqgf.z@nn.com");
409
410
411 userCR.getResources().add(RESOURCE_NAME_TESTDB);
412
413 UserTO userTO = createUser(userCR).getEntity();
414
415 String key = userTO.getKey();
416
417 ProvisioningResult<UserTO> result = deleteUser(key);
418 assertNotNull(result);
419 userTO = result.getEntity();
420 assertEquals(key, userTO.getKey());
421 assertTrue(userTO.getPlainAttrs().isEmpty());
422
423
424 assertFalse(result.getPropagationStatuses().isEmpty());
425 assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
426
427 try {
428 USER_SERVICE.delete(userTO.getKey());
429 } catch (SyncopeClientException e) {
430 assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
431 }
432 }
433
434 @Test
435 public void deleteByUsername() {
436 UserCR userCR = getSample("delete.by.username@apache.org");
437
438
439 userCR.getResources().add(RESOURCE_NAME_TESTDB);
440
441 UserTO userTO = createUser(userCR).getEntity();
442
443 String key = userTO.getKey();
444 userTO = USER_SERVICE.read(key);
445
446 ProvisioningResult<UserTO> result = deleteUser(userTO.getKey());
447 assertNotNull(result);
448 userTO = result.getEntity();
449 assertEquals(key, userTO.getKey());
450 assertTrue(userTO.getPlainAttrs().isEmpty());
451
452
453 assertFalse(result.getPropagationStatuses().isEmpty());
454 assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
455
456 try {
457 USER_SERVICE.read(userTO.getKey());
458 } catch (SyncopeClientException e) {
459 assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
460 }
461 }
462
463 @Test
464 public void list() {
465 PagedResult<UserTO> users = USER_SERVICE.search(
466 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).page(1).size(2).build());
467 assertNotNull(users);
468 assertFalse(users.getResult().isEmpty());
469 assertEquals(2, users.getResult().size());
470
471 for (UserTO user : users.getResult()) {
472 assertNotNull(user);
473 }
474
475 users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
476 page(2).size(2).build());
477 assertNotNull(users);
478 assertEquals(2, users.getPage());
479 assertEquals(2, users.getResult().size());
480
481 users = USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
482 page(100).size(2).build());
483 assertNotNull(users);
484 assertTrue(users.getResult().isEmpty());
485 }
486
487 @Test
488 public void read() {
489 UserTO userTO = USER_SERVICE.read("1417acbe-cbf6-4277-9372-e75e04f97000");
490
491 assertNotNull(userTO);
492 assertNull(userTO.getPassword());
493 assertNotNull(userTO.getPlainAttrs());
494 assertFalse(userTO.getPlainAttrs().isEmpty());
495 }
496
497 @Test
498 public void updateWithoutPassword() {
499 UserCR userCR = getUniqueSample("updatewithout@password.com");
500
501 UserTO userTO = createUser(userCR).getEntity();
502 assertNotNull(userTO);
503
504 UserUR userUR = new UserUR.Builder(userTO.getKey()).
505 plainAttr(new AttrPatch.Builder(new Attr.Builder("ctype").build()).
506 operation(PatchOperation.DELETE).
507 build()).build();
508
509 userTO = updateUser(userUR).getEntity();
510
511 assertNotNull(userTO);
512 assertFalse(userTO.getPlainAttr("ctype").isPresent());
513 }
514
515 @Test
516 public void updateInvalidPassword() {
517 assertThrows(SyncopeClientException.class, () -> {
518 UserCR userCR = getSample("updateinvalid@password.com");
519
520 UserTO userTO = createUser(userCR).getEntity();
521 assertNotNull(userTO);
522
523 UserUR userUR = new UserUR();
524 userUR.setKey(userTO.getKey());
525 userUR.setPassword(new PasswordPatch.Builder().value("pass").build());
526
527 USER_SERVICE.update(userUR);
528 });
529 }
530
531 @Test
532 public void updateSamePassword() {
533 assertThrows(SyncopeClientException.class, () -> {
534 UserCR userCR = getUniqueSample("updatesame@password.com");
535 userCR.setRealm("/even/two");
536
537 UserTO userTO = createUser(userCR).getEntity();
538 assertNotNull(userTO);
539
540 UserUR userUR = new UserUR();
541 userUR.setKey(userTO.getKey());
542 userUR.setPassword(new PasswordPatch.Builder().value("password123").build());
543
544 USER_SERVICE.update(userUR);
545 });
546 }
547
548 @Test
549 public void update() {
550 UserCR userCR = getUniqueSample("g.h@t.com");
551
552 userCR.getMemberships().add(new MembershipTO.Builder("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
553
554 UserTO userTO = createUser(userCR).getEntity();
555
556 assertFalse(userTO.getDerAttrs().isEmpty());
557 assertEquals(1, userTO.getMemberships().size());
558
559 UserUR userUR = new UserUR();
560 userUR.setKey(userTO.getKey());
561 userUR.setPassword(new PasswordPatch.Builder().value("new2Password").build());
562
563 String newUserId = getUUIDString() + "t.w@spre.net";
564 userUR.getPlainAttrs().add(attrAddReplacePatch("userId", newUserId));
565
566 String newFullName = getUUIDString() + "g.h@t.com";
567 userUR.getPlainAttrs().add(attrAddReplacePatch("fullname", newFullName));
568
569 userUR.getMemberships().add(new MembershipUR.Builder("f779c0d4-633b-4be5-8f57-32eb478a3ca5").
570 operation(PatchOperation.ADD_REPLACE).build());
571 userUR.getMemberships().add(new MembershipUR.Builder(userTO.getMemberships().get(0).getGroupKey()).
572 operation(PatchOperation.ADD_REPLACE).build());
573
574 userTO = updateUser(userUR).getEntity();
575 assertNotNull(userTO);
576
577
578 assertNotNull(userTO.getCreationDate());
579 assertNotNull(userTO.getCreator());
580 assertNotNull(userTO.getLastChangeDate());
581 assertNotNull(userTO.getLastModifier());
582 assertTrue(userTO.getCreationDate().isBefore(userTO.getLastChangeDate()));
583
584 assertEquals(1, userTO.getMemberships().size());
585 assertFalse(userTO.getDerAttrs().isEmpty());
586
587 Attr userIdAttr = userTO.getPlainAttr("userId").get();
588 assertEquals(List.of(newUserId), userIdAttr.getValues());
589
590 Attr fullNameAttr = userTO.getPlainAttr("fullname").get();
591 assertEquals(List.of(newFullName), fullNameAttr.getValues());
592
593
594 userUR = new UserUR();
595 userUR.setKey(userTO.getUsername());
596 String newUsername = UUID.randomUUID().toString();
597 userUR.setUsername(new StringReplacePatchItem.Builder().value(newUsername).build());
598
599 userTO = updateUser(userUR).getEntity();
600 assertNotNull(userTO);
601 assertEquals(newUsername, userTO.getUsername());
602 }
603
604 @Test
605 public void updatePasswordOnly() {
606 int beforeTasks = TASK_SERVICE.search(
607 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1).build()).getTotalCount();
608 assertFalse(beforeTasks <= 0);
609
610 UserCR userCR = getUniqueSample("pwdonly@t.com");
611 userCR.getMemberships().add(new MembershipTO.Builder("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
612
613 UserTO userTO = createUser(userCR).getEntity();
614
615 UserUR userUR = new UserUR();
616 userUR.setKey(userTO.getKey());
617 userUR.setPassword(new PasswordPatch.Builder().value("newPassword123").resource(RESOURCE_NAME_WS2).build());
618
619 userTO = updateUser(userUR).getEntity();
620
621
622 assertNotNull(userTO.getChangePwdDate());
623
624 int afterTasks = TASK_SERVICE.search(
625 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1).build()).getTotalCount();
626 assertFalse(afterTasks <= 0);
627
628 assertTrue(beforeTasks < afterTasks);
629 }
630
631 @SuppressWarnings("unchecked")
632 @Test
633 public void verifyTaskRegistration() {
634
635 List<PropagationTaskTO> tasks = TASK_SERVICE.<PropagationTaskTO>search(
636 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1000).build()).getResult();
637 assertFalse(tasks.isEmpty());
638
639 String maxKey = tasks.stream().
640 max(Comparator.comparing(PropagationTaskTO::getStart, Comparator.nullsLast(Comparator.naturalOrder()))).
641 map(PropagationTaskTO::getKey).orElse(null);
642 assertNotNull(maxKey);
643
644
645
646
647 UserCR userCR = getUniqueSample("t@p.mode");
648
649
650 userCR.getMemberships().add(new MembershipTO.Builder("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
651
652
653 UserTO userTO = createUser(userCR).getEntity();
654 assertNotNull(userTO);
655
656
657 tasks = TASK_SERVICE.<PropagationTaskTO>search(
658 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1000).build()).getResult();
659 assertFalse(tasks.isEmpty());
660
661 String newMaxKey = tasks.stream().
662 max(Comparator.comparing(PropagationTaskTO::getStart, Comparator.nullsLast(Comparator.naturalOrder()))).
663 map(PropagationTaskTO::getKey).orElse(null);
664 assertNotNull(newMaxKey);
665
666
667
668
669 assertEquals(newMaxKey, maxKey);
670
671
672
673
674 UserUR userUR = new UserUR();
675 userUR.setKey(userTO.getKey());
676
677 userUR.getPlainAttrs().add(attrAddReplacePatch("surname", "surname2"));
678
679 userTO = updateUser(userUR).getEntity();
680
681 assertNotNull(userTO);
682
683
684 tasks = TASK_SERVICE.<PropagationTaskTO>search(
685 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1000).build()).getResult();
686 assertFalse(tasks.isEmpty());
687
688
689
690 newMaxKey = tasks.stream().
691 max(Comparator.comparing(PropagationTaskTO::getStart, Comparator.nullsLast(Comparator.naturalOrder()))).
692 map(PropagationTaskTO::getKey).orElse(null);
693 assertNotNull(newMaxKey);
694
695 assertNotNull(TASK_SERVICE.read(TaskType.PROPAGATION, newMaxKey, false));
696
697
698
699
700 USER_SERVICE.delete(userTO.getKey());
701
702
703 tasks = TASK_SERVICE.<PropagationTaskTO>search(
704 new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(1000).build()).getResult();
705 assertFalse(tasks.isEmpty());
706
707 maxKey = newMaxKey;
708 newMaxKey = tasks.stream().
709 max(Comparator.comparing(PropagationTaskTO::getStart, Comparator.nullsLast(Comparator.naturalOrder()))).
710 map(PropagationTaskTO::getKey).orElse(null);
711 assertNotNull(newMaxKey);
712
713
714
715 assertEquals(newMaxKey, maxKey);
716 }
717
718 @Test
719 public void createActivate() {
720 assumeTrue(IS_FLOWABLE_ENABLED);
721
722 UserCR userCR = getUniqueSample("createActivate@syncope.apache.org");
723
724 userCR.getMemberships().add(new MembershipTO.Builder("268fed79-f440-4390-9435-b273768eb5d6").build());
725
726 UserTO userTO = createUser(userCR).getEntity();
727
728 assertNotNull(userTO);
729 assertNotNull(userTO.getToken());
730 assertNotNull(userTO.getTokenExpireTime());
731
732 assertEquals("created", userTO.getStatus());
733
734 StatusR statusR = new StatusR.Builder(userTO.getKey(), StatusRType.ACTIVATE).token(userTO.getToken()).build();
735
736 userTO = USER_SERVICE.status(statusR).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
737 }).getEntity();
738
739 assertNotNull(userTO);
740 assertNull(userTO.getToken());
741 assertNull(userTO.getTokenExpireTime());
742 assertEquals("active", userTO.getStatus());
743 }
744
745 @Test
746 public void suspendReactivate() {
747 UserCR userCR = getUniqueSample("suspendReactivate@syncope.apache.org");
748
749 userCR.getMemberships().add(new MembershipTO.Builder("bf825fe1-7320-4a54-bd64-143b5c18ab97").build());
750
751 UserTO userTO = createUser(userCR).getEntity();
752
753 assertNotNull(userTO);
754 assertEquals(IS_FLOWABLE_ENABLED
755 ? "active"
756 : "created", userTO.getStatus());
757
758 StatusR statusR = new StatusR.Builder(userTO.getKey(), StatusRType.SUSPEND).token(userTO.getToken()).build();
759
760 userTO = USER_SERVICE.status(statusR).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
761 }).getEntity();
762 assertNotNull(userTO);
763 assertEquals("suspended", userTO.getStatus());
764
765 statusR = new StatusR.Builder(userTO.getKey(), StatusRType.REACTIVATE).build();
766
767 userTO = USER_SERVICE.status(statusR).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
768 }).getEntity();
769 assertNotNull(userTO);
770 assertEquals("active", userTO.getStatus());
771 }
772
773 @Test
774 public void suspendReactivateOnResource() {
775
776 ResourceTO dbTable = RESOURCE_SERVICE.read(RESOURCE_NAME_TESTDB);
777 assertNotNull(dbTable);
778 ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
779 assertNotNull(ldap);
780
781
782 UserCR userCR = getUniqueSample("suspreactonresource@syncope.apache.org");
783 userCR.getMemberships().clear();
784 userCR.getResources().clear();
785 userCR.getResources().add(RESOURCE_NAME_TESTDB);
786 userCR.getResources().add(RESOURCE_NAME_LDAP);
787 UserTO userTO = createUser(userCR).getEntity();
788 assertNotNull(userTO);
789 assertEquals(IS_FLOWABLE_ENABLED
790 ? "active"
791 : "created", userTO.getStatus());
792 String userKey = userTO.getKey();
793
794
795 StatusR statusR = new StatusR.Builder(userKey, StatusRType.SUSPEND).
796 onSyncope(true).
797 resources(RESOURCE_NAME_TESTDB, RESOURCE_NAME_LDAP).
798 build();
799 userTO = USER_SERVICE.status(statusR).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
800 }).getEntity();
801 assertNotNull(userTO);
802 assertEquals("suspended", userTO.getStatus());
803
804 ConnObject connObjectTO =
805 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userKey);
806 assertFalse(getBooleanAttribute(connObjectTO, OperationalAttributes.ENABLE_NAME));
807
808 connObjectTO = RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), userKey);
809 assertNotNull(connObjectTO);
810
811
812 statusR = new StatusR.Builder(userKey, StatusRType.SUSPEND).
813 onSyncope(false).
814 resources(RESOURCE_NAME_LDAP).
815 build();
816 USER_SERVICE.status(statusR);
817 statusR.setType(StatusRType.REACTIVATE);
818 userTO = USER_SERVICE.status(statusR).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
819 }).getEntity();
820 assertNotNull(userTO);
821 assertEquals("suspended", userTO.getStatus());
822
823 connObjectTO = RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userKey);
824 assertFalse(getBooleanAttribute(connObjectTO, OperationalAttributes.ENABLE_NAME));
825
826
827 statusR = new StatusR.Builder(userKey, StatusRType.REACTIVATE).
828 onSyncope(true).
829 resources(RESOURCE_NAME_TESTDB).
830 build();
831 userTO = USER_SERVICE.status(statusR).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
832 }).getEntity();
833 assertNotNull(userTO);
834 assertEquals("active", userTO.getStatus());
835
836 connObjectTO = RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userKey);
837 assertTrue(getBooleanAttribute(connObjectTO, OperationalAttributes.ENABLE_NAME));
838 }
839
840 @Test
841 public void updateMultivalueAttribute() {
842 UserCR userCR = getUniqueSample("multivalue@syncope.apache.org");
843 userCR.getResources().clear();
844 userCR.getVirAttrs().clear();
845
846 UserTO userTO = createUser(userCR).getEntity();
847 assertNotNull(userTO);
848
849 Attr loginDate = userTO.getPlainAttr("loginDate").get();
850 assertNotNull(loginDate);
851 assertEquals(1, loginDate.getValues().size());
852
853 UserUR userUR = new UserUR();
854 userUR.setKey(userTO.getKey());
855
856 loginDate.getValues().add("2000-01-01");
857 userUR.getPlainAttrs().add(new AttrPatch.Builder(loginDate).
858 operation(PatchOperation.ADD_REPLACE).build());
859
860 userTO = updateUser(userUR).getEntity();
861 assertNotNull(userTO);
862
863 loginDate = userTO.getPlainAttr("loginDate").get();
864 assertNotNull(loginDate);
865 assertEquals(2, loginDate.getValues().size());
866 }
867
868 private static void verifyAsyncResult(final List<PropagationStatus> statuses) {
869 assertEquals(3, statuses.size());
870
871 Map<String, PropagationStatus> byResource = statuses.stream().collect(
872 Collectors.toMap(PropagationStatus::getResource, Function.identity()));
873 assertEquals(ExecStatus.SUCCESS, byResource.get(RESOURCE_NAME_LDAP).getStatus());
874 assertTrue(byResource.get(RESOURCE_NAME_TESTDB).getStatus() == ExecStatus.CREATED
875 || byResource.get(RESOURCE_NAME_TESTDB).getStatus() == ExecStatus.SUCCESS);
876 assertTrue(byResource.get(RESOURCE_NAME_TESTDB2).getStatus() == ExecStatus.CREATED
877 || byResource.get(RESOURCE_NAME_TESTDB2).getStatus() == ExecStatus.SUCCESS);
878 }
879
880 @Test
881 public void async() {
882 SyncopeClient asyncClient = CLIENT_FACTORY.create(ADMIN_UNAME, ADMIN_PWD);
883 UserService asyncService = SyncopeClient.nullPriorityAsync(asyncClient.getService(UserService.class), true);
884
885 UserCR userCR = getUniqueSample("async@syncope.apache.org");
886 userCR.getResources().add(RESOURCE_NAME_TESTDB);
887 userCR.getResources().add(RESOURCE_NAME_TESTDB2);
888 userCR.getResources().add(RESOURCE_NAME_LDAP);
889
890 ProvisioningResult<UserTO> result = asyncService.create(userCR).readEntity(
891 new GenericType<>() {
892 });
893 assertNotNull(result);
894 verifyAsyncResult(result.getPropagationStatuses());
895
896 UserUR userUR = new UserUR();
897 userUR.setKey(result.getEntity().getKey());
898 userUR.setPassword(new PasswordPatch.Builder().
899 onSyncope(true).resources(RESOURCE_NAME_LDAP, RESOURCE_NAME_TESTDB, RESOURCE_NAME_TESTDB2).
900 value("password321").build());
901
902 result = asyncService.update(userUR).readEntity(
903 new GenericType<>() {
904 });
905 assertNotNull(result);
906 verifyAsyncResult(result.getPropagationStatuses());
907
908 result = asyncService.delete(result.getEntity().getKey()).readEntity(
909 new GenericType<>() {
910 });
911 assertNotNull(result);
912 verifyAsyncResult(result.getPropagationStatuses());
913 }
914
915 @Test
916 public void groupAttrPropagation() {
917 UserCR userCR = getUniqueSample("checkGroupAttrPropagation@syncope.apache.org");
918 userCR.getResources().clear();
919 userCR.getMemberships().clear();
920 userCR.getVirAttrs().clear();
921
922 userCR.getAuxClasses().add("csv");
923
924 userCR.getMemberships().add(new MembershipTO.Builder("37d15e4c-cdc1-460b-a591-8505c8133806").build());
925
926 userCR.getResources().add(RESOURCE_NAME_CSV);
927
928 UserTO userTO = createUser(userCR).getEntity();
929 assertNotNull(userTO);
930 assertNotNull(userTO.getDerAttr("csvuserid"));
931
932 ConnObject connObjectTO =
933 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), userTO.getKey());
934 assertNotNull(connObjectTO);
935 assertEquals("sx-dx", connObjectTO.getAttr("THEIRGROUP").get().getValues().get(0));
936 }
937
938 @Test
939 public void customPolicyRules() {
940 ImplementationTO implementationTO = new ImplementationTO();
941 implementationTO.setKey("TestAccountRuleConf" + UUID.randomUUID().toString());
942 implementationTO.setEngine(ImplementationEngine.JAVA);
943 implementationTO.setType(IdRepoImplementationType.ACCOUNT_RULE);
944 implementationTO.setBody(POJOHelper.serialize(new TestAccountRuleConf()));
945 Response response = IMPLEMENTATION_SERVICE.create(implementationTO);
946 implementationTO.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
947
948 AccountPolicyTO accountPolicy = new AccountPolicyTO();
949 accountPolicy.setName("Account Policy with custom rules");
950 accountPolicy.getRules().add(implementationTO.getKey());
951 accountPolicy = createPolicy(PolicyType.ACCOUNT, accountPolicy);
952 assertNotNull(accountPolicy);
953
954 implementationTO = new ImplementationTO();
955 implementationTO.setKey("TestPasswordRuleConf" + UUID.randomUUID().toString());
956 implementationTO.setEngine(ImplementationEngine.JAVA);
957 implementationTO.setType(IdRepoImplementationType.PASSWORD_RULE);
958 implementationTO.setBody(POJOHelper.serialize(new TestPasswordRuleConf()));
959 response = IMPLEMENTATION_SERVICE.create(implementationTO);
960 implementationTO.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
961
962 PasswordPolicyTO passwordPolicy = new PasswordPolicyTO();
963 passwordPolicy.setName("Password Policy with custom rules");
964 passwordPolicy.getRules().add(implementationTO.getKey());
965 passwordPolicy = createPolicy(PolicyType.PASSWORD, passwordPolicy);
966 assertNotNull(passwordPolicy);
967
968 RealmTO realm = REALM_SERVICE.search(new RealmQuery.Builder().keyword("two").build()).getResult().get(0);
969 String oldAccountPolicy = realm.getAccountPolicy();
970 realm.setAccountPolicy(accountPolicy.getKey());
971 String oldPasswordPolicy = realm.getPasswordPolicy();
972 realm.setPasswordPolicy(passwordPolicy.getKey());
973 REALM_SERVICE.update(realm);
974
975 try {
976 UserCR userCR = getUniqueSample("custompolicyrules@syncope.apache.org");
977 userCR.setRealm(realm.getFullPath());
978
979 try {
980 ANONYMOUS_CLIENT.getService(UserSelfService.class).compliance(
981 new ComplianceQuery.Builder().password(userCR.getPassword()).realm(userCR.getRealm()).build());
982 } catch (SyncopeClientException e) {
983 assertEquals(ClientExceptionType.InvalidUser, e.getType());
984 assertTrue(e.getElements().iterator().next().startsWith("InvalidPassword"));
985 }
986
987 try {
988 createUser(userCR);
989 fail("This should not happen");
990 } catch (SyncopeClientException e) {
991 assertEquals(ClientExceptionType.InvalidUser, e.getType());
992 assertTrue(e.getElements().iterator().next().startsWith("InvalidPassword"));
993 }
994
995 try {
996 ANONYMOUS_CLIENT.getService(UserSelfService.class).compliance(
997 new ComplianceQuery.Builder().username(userCR.getUsername()).realm(userCR.getRealm()).build());
998 } catch (SyncopeClientException e) {
999 assertEquals(ClientExceptionType.InvalidUser, e.getType());
1000 assertTrue(e.getElements().iterator().next().startsWith("InvalidUsername"));
1001 }
1002
1003 userCR.setPassword(userCR.getPassword() + "XXX");
1004
1005 try {
1006 createUser(userCR);
1007 fail("This should not happen");
1008 } catch (SyncopeClientException e) {
1009 assertEquals(ClientExceptionType.InvalidUser, e.getType());
1010 assertTrue(e.getElements().iterator().next().startsWith("InvalidUsername"));
1011 }
1012
1013 userCR.setUsername("YYY" + userCR.getUsername());
1014
1015 assertDoesNotThrow(() -> ANONYMOUS_CLIENT.getService(UserSelfService.class).compliance(
1016 new ComplianceQuery.Builder().password(userCR.getPassword()).realm(userCR.getRealm()).build()));
1017 assertDoesNotThrow(() -> ANONYMOUS_CLIENT.getService(UserSelfService.class).compliance(
1018 new ComplianceQuery.Builder().username(userCR.getUsername()).realm(userCR.getRealm()).build()));
1019
1020 UserTO userTO = createUser(userCR).getEntity();
1021 assertNotNull(userTO);
1022 } finally {
1023 realm.setAccountPolicy(oldAccountPolicy);
1024 realm.setPasswordPolicy(oldPasswordPolicy);
1025 REALM_SERVICE.update(realm);
1026
1027 POLICY_SERVICE.delete(PolicyType.PASSWORD, passwordPolicy.getKey());
1028 POLICY_SERVICE.delete(PolicyType.ACCOUNT, accountPolicy.getKey());
1029 }
1030 }
1031
1032 @Test
1033 public void mappingPurpose() {
1034 UserCR userCR = getUniqueSample("mpurpose@apache.org");
1035 userCR.getAuxClasses().add("csv");
1036
1037 userCR.getResources().clear();
1038 userCR.getResources().add(RESOURCE_NAME_CSV);
1039
1040 UserTO userTO = createUser(userCR).getEntity();
1041 assertNotNull(userTO);
1042
1043 ConnObject connObjectTO =
1044 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), userTO.getKey());
1045 assertFalse(connObjectTO.getAttr("email").isPresent());
1046 }
1047
1048 @Test
1049 public void batch() throws IOException {
1050 List<String> users = new ArrayList<>();
1051 for (int i = 0; i < 10; i++) {
1052 UserCR userCR = getUniqueSample("batch_" + i + "@apache.org");
1053 users.add(createUser(userCR).getEntity().getKey());
1054 }
1055
1056
1057 users.add(UUID.randomUUID().toString());
1058
1059 assertEquals(11, users.size());
1060
1061 BatchRequest batchRequest = ADMIN_CLIENT.batch();
1062
1063 UserService batchUserService = batchRequest.getService(UserService.class);
1064 users.forEach(user -> batchUserService.status(new StatusR.Builder(user, StatusRType.SUSPEND).
1065 onSyncope(true).
1066 build()));
1067 List<BatchResponseItem> batchResponseItems = parseBatchResponse(batchRequest.commit().getResponse());
1068 assertEquals(10, batchResponseItems.stream().
1069 filter(item -> Response.Status.OK.getStatusCode() == item.getStatus()).count());
1070 assertEquals(1, batchResponseItems.stream().
1071 filter(item -> Response.Status.NOT_FOUND.getStatusCode() == item.getStatus()).count());
1072 assertEquals("suspended", USER_SERVICE.read(users.get(3)).getStatus());
1073
1074 UserService batchUserService2 = batchRequest.getService(UserService.class);
1075 users.forEach(user -> batchUserService2.status(new StatusR.Builder(user, StatusRType.REACTIVATE).
1076 onSyncope(true).
1077 build()));
1078 batchResponseItems = parseBatchResponse(batchRequest.commit().getResponse());
1079 assertEquals(10, batchResponseItems.stream().
1080 filter(item -> Response.Status.OK.getStatusCode() == item.getStatus()).count());
1081 assertEquals(1, batchResponseItems.stream().
1082 filter(item -> Response.Status.NOT_FOUND.getStatusCode() == item.getStatus()).count());
1083 assertEquals("active", USER_SERVICE.read(users.get(3)).getStatus());
1084
1085 UserService batchUserService3 = batchRequest.getService(UserService.class);
1086 users.forEach(batchUserService3::delete);
1087 batchResponseItems = parseBatchResponse(batchRequest.commit().getResponse());
1088 assertEquals(10, batchResponseItems.stream().
1089 filter(item -> Response.Status.OK.getStatusCode() == item.getStatus()).count());
1090 assertEquals(1, batchResponseItems.stream().
1091 filter(item -> Response.Status.NOT_FOUND.getStatusCode() == item.getStatus()).count());
1092
1093 try {
1094 USER_SERVICE.read(users.get(3));
1095 fail("This should not happen");
1096 } catch (SyncopeClientException e) {
1097 assertEquals(ClientExceptionType.NotFound, e.getType());
1098 }
1099 }
1100
1101 @Test
1102 public void unlink() throws IOException {
1103 UserCR userCR = getUniqueSample("unlink@syncope.apache.org");
1104 userCR.getResources().clear();
1105 userCR.getMemberships().clear();
1106 userCR.getVirAttrs().clear();
1107 userCR.getAuxClasses().add("csv");
1108 userCR.getResources().add(RESOURCE_NAME_CSV);
1109
1110 UserTO actual = createUser(userCR).getEntity();
1111 assertNotNull(actual);
1112 assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey()));
1113
1114 ResourceDR resourceDR = new ResourceDR.Builder().key(actual.getKey()).
1115 action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_CSV).build();
1116
1117 assertNotNull(parseBatchResponse(USER_SERVICE.deassociate(resourceDR)));
1118
1119 actual = USER_SERVICE.read(actual.getKey());
1120 assertNotNull(actual);
1121 assertTrue(actual.getResources().isEmpty());
1122
1123 assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey()));
1124 }
1125
1126 @Test
1127 public void link() throws IOException {
1128 UserCR userCR = getUniqueSample("link@syncope.apache.org");
1129 userCR.getResources().clear();
1130 userCR.getMemberships().clear();
1131 userCR.getVirAttrs().clear();
1132 userCR.getAuxClasses().add("csv");
1133
1134 UserTO actual = createUser(userCR).getEntity();
1135 assertNotNull(actual);
1136 assertTrue(actual.getResources().isEmpty());
1137
1138 try {
1139 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1140 fail("This should not happen");
1141 } catch (Exception e) {
1142 assertNotNull(e);
1143 }
1144
1145 ResourceAR resourceAR = new ResourceAR.Builder().key(actual.getKey()).
1146 action(ResourceAssociationAction.LINK).resource(RESOURCE_NAME_CSV).build();
1147
1148 assertNotNull(parseBatchResponse(USER_SERVICE.associate(resourceAR)));
1149
1150 actual = USER_SERVICE.read(actual.getKey());
1151 assertNotNull(actual);
1152 assertFalse(actual.getResources().isEmpty());
1153
1154 try {
1155 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1156 fail("This should not happen");
1157 } catch (Exception e) {
1158 assertNotNull(e);
1159 }
1160 }
1161
1162 @Test
1163 public void unassign() throws IOException {
1164 UserCR userCR = getUniqueSample("unassign@syncope.apache.org");
1165 userCR.getResources().clear();
1166 userCR.getMemberships().clear();
1167 userCR.getVirAttrs().clear();
1168 userCR.getAuxClasses().add("csv");
1169 userCR.getResources().add(RESOURCE_NAME_CSV);
1170
1171 UserTO actual = createUser(userCR).getEntity();
1172 assertNotNull(actual);
1173 assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey()));
1174
1175 ResourceDR resourceDR = new ResourceDR.Builder().key(actual.getKey()).
1176 action(ResourceDeassociationAction.UNASSIGN).resource(RESOURCE_NAME_CSV).build();
1177
1178 assertNotNull(parseBatchResponse(USER_SERVICE.deassociate(resourceDR)));
1179
1180 actual = USER_SERVICE.read(actual.getKey());
1181 assertNotNull(actual);
1182 assertTrue(actual.getResources().isEmpty());
1183
1184 try {
1185 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1186 fail("This should not happen");
1187 } catch (Exception e) {
1188 assertNotNull(e);
1189 }
1190 }
1191
1192 @Test
1193 public void assign() throws IOException {
1194 UserCR userCR = getUniqueSample("assign@syncope.apache.org");
1195 userCR.getResources().clear();
1196 userCR.getMemberships().clear();
1197 userCR.getVirAttrs().clear();
1198 userCR.getAuxClasses().add("csv");
1199
1200 UserTO actual = createUser(userCR).getEntity();
1201 assertNotNull(actual);
1202 assertTrue(actual.getResources().isEmpty());
1203
1204 try {
1205 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1206 fail("This should not happen");
1207 } catch (Exception e) {
1208 assertNotNull(e);
1209 }
1210
1211 ResourceAR resourceAR = new ResourceAR.Builder().key(actual.getKey()).
1212 value("password123").action(ResourceAssociationAction.ASSIGN).resource(RESOURCE_NAME_CSV).build();
1213
1214 assertNotNull(parseBatchResponse(USER_SERVICE.associate(resourceAR)));
1215
1216 actual = USER_SERVICE.read(actual.getKey());
1217 assertNotNull(actual);
1218 assertFalse(actual.getResources().isEmpty());
1219 assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey()));
1220 }
1221
1222 @Test
1223 public void deprovision() throws IOException {
1224 UserCR userCR = getUniqueSample("deprovision@syncope.apache.org");
1225 userCR.getResources().clear();
1226 userCR.getMemberships().clear();
1227 userCR.getVirAttrs().clear();
1228 userCR.getAuxClasses().add("csv");
1229 userCR.getResources().add(RESOURCE_NAME_CSV);
1230
1231 UserTO actual = createUser(userCR).getEntity();
1232 assertNotNull(actual);
1233 assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey()));
1234
1235 ResourceDR resourceDR = new ResourceDR.Builder().key(actual.getKey()).
1236 action(ResourceDeassociationAction.DEPROVISION).resource(RESOURCE_NAME_CSV).build();
1237
1238 assertNotNull(parseBatchResponse(USER_SERVICE.deassociate(resourceDR)));
1239
1240 actual = USER_SERVICE.read(actual.getKey());
1241 assertNotNull(actual);
1242 assertFalse(actual.getResources().isEmpty());
1243
1244 try {
1245 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1246 fail("This should not happen");
1247 } catch (SyncopeClientException e) {
1248 assertEquals(ClientExceptionType.NotFound, e.getType());
1249 }
1250 }
1251
1252 @Test
1253 public void provision() throws IOException {
1254 UserCR userCR = getUniqueSample("provision@syncope.apache.org");
1255 userCR.getResources().clear();
1256 userCR.getMemberships().clear();
1257 userCR.getVirAttrs().clear();
1258 userCR.getAuxClasses().add("csv");
1259
1260 UserTO actual = createUser(userCR).getEntity();
1261 assertNotNull(actual);
1262 assertTrue(actual.getResources().isEmpty());
1263
1264 try {
1265 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1266 fail("This should not happen");
1267 } catch (Exception e) {
1268 assertNotNull(e);
1269 }
1270
1271 ResourceAR resourceAR = new ResourceAR.Builder().key(actual.getKey()).
1272 value("password").action(ResourceAssociationAction.PROVISION).resource(RESOURCE_NAME_CSV).build();
1273
1274 assertNotNull(parseBatchResponse(USER_SERVICE.associate(resourceAR)));
1275
1276 actual = USER_SERVICE.read(actual.getKey());
1277 assertNotNull(actual);
1278 assertTrue(actual.getResources().isEmpty());
1279 assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey()));
1280 }
1281
1282 @Test
1283 public void deprovisionUnlinked() throws IOException {
1284 UserCR userCR = getUniqueSample("provision@syncope.apache.org");
1285 userCR.getResources().clear();
1286 userCR.getMemberships().clear();
1287 userCR.getVirAttrs().clear();
1288 userCR.getAuxClasses().add("csv");
1289
1290 UserTO actual = createUser(userCR).getEntity();
1291 assertNotNull(actual);
1292 assertTrue(actual.getResources().isEmpty());
1293
1294 try {
1295 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1296 fail("This should not happen");
1297 } catch (Exception e) {
1298 assertNotNull(e);
1299 }
1300
1301 ResourceAR resourceAR = new ResourceAR.Builder().key(actual.getKey()).
1302 value("password").action(ResourceAssociationAction.PROVISION).resource(RESOURCE_NAME_CSV).build();
1303
1304 assertNotNull(parseBatchResponse(USER_SERVICE.associate(resourceAR)));
1305
1306 actual = USER_SERVICE.read(actual.getKey());
1307 assertNotNull(actual);
1308 assertTrue(actual.getResources().isEmpty());
1309 assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey()));
1310
1311 ResourceDR resourceDR = new ResourceDR.Builder().key(actual.getKey()).
1312 action(ResourceDeassociationAction.DEPROVISION).resource(RESOURCE_NAME_CSV).build();
1313
1314 assertNotNull(parseBatchResponse(USER_SERVICE.deassociate(resourceDR)));
1315
1316 actual = USER_SERVICE.read(actual.getKey());
1317 assertNotNull(actual);
1318 assertTrue(actual.getResources().isEmpty());
1319
1320 try {
1321 RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), actual.getKey());
1322 fail("This should not happen");
1323 } catch (Exception e) {
1324 assertNotNull(e);
1325 }
1326 }
1327
1328 @Test
1329 public void restResource() {
1330 UserCR userCR = getUniqueSample("rest@syncope.apache.org");
1331 userCR.getResources().clear();
1332 userCR.getResources().add(RESOURCE_NAME_REST);
1333
1334
1335 ProvisioningResult<UserTO> result = createUser(userCR);
1336 assertEquals(1, result.getPropagationStatuses().size());
1337 assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
1338 assertEquals(RESOURCE_NAME_REST, result.getPropagationStatuses().get(0).getResource());
1339 assertEquals("surname", result.getEntity().getPlainAttr("surname").get().getValues().get(0));
1340
1341
1342 WebClient webClient = WebClient.create(BUILD_TOOLS_ADDRESS + "/rest/users/" + result.getEntity().getKey());
1343 Response response = webClient.get();
1344 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
1345 assertNotNull(response.getEntity());
1346
1347
1348 UserUR userUR = new UserUR.Builder(result.getEntity().getKey()).
1349 plainAttr(new AttrPatch.Builder(new Attr.Builder("surname").value("surname2").build()).build()).
1350 build();
1351 result = updateUser(userUR);
1352 assertEquals(1, result.getPropagationStatuses().size());
1353 assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
1354 assertEquals(RESOURCE_NAME_REST, result.getPropagationStatuses().get(0).getResource());
1355 assertEquals("surname2", result.getEntity().getPlainAttr("surname").get().getValues().get(0));
1356
1357
1358 response = webClient.get();
1359 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
1360 assertNotNull(response.getEntity());
1361
1362
1363 result = deleteUser(result.getEntity().getKey());
1364 assertEquals(1, result.getPropagationStatuses().size());
1365 assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
1366 assertEquals(RESOURCE_NAME_REST, result.getPropagationStatuses().get(0).getResource());
1367
1368
1369 assertEquals(Response.Status.NOT_FOUND.getStatusCode(), webClient.get().getStatus());
1370 }
1371
1372 @Test
1373 public void haveIBeenPwned() {
1374 ImplementationTO rule = new ImplementationTO();
1375 rule.setKey("HaveIBeenPwnedPasswordRuleConf" + getUUIDString());
1376 rule.setEngine(ImplementationEngine.JAVA);
1377 rule.setType(IdRepoImplementationType.PASSWORD_RULE);
1378 rule.setBody(POJOHelper.serialize(new HaveIBeenPwnedPasswordRuleConf()));
1379 Response response = IMPLEMENTATION_SERVICE.create(rule);
1380 rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
1381
1382 PasswordPolicyTO pwdPolicy = new PasswordPolicyTO();
1383 pwdPolicy.setName("Have I Been Pwned?");
1384 pwdPolicy.getRules().add(rule.getKey());
1385 pwdPolicy = createPolicy(PolicyType.PASSWORD, pwdPolicy);
1386 assertNotNull(pwdPolicy.getKey());
1387
1388 RealmTO realm = new RealmTO();
1389 realm.setName("hibp");
1390 realm.setPasswordPolicy(pwdPolicy.getKey());
1391 REALM_SERVICE.create(SyncopeConstants.ROOT_REALM, realm);
1392
1393 UserCR userCR = getUniqueSample("hibp@syncope.apache.org");
1394 userCR.setRealm("/hibp");
1395 userCR.setPassword("password");
1396 try {
1397 createUser(userCR);
1398 } catch (SyncopeClientException e) {
1399 assertEquals(ClientExceptionType.InvalidUser, e.getType());
1400 assertEquals("InvalidPassword: Password pwned", e.getElements().iterator().next());
1401 }
1402
1403 userCR.setPassword('1' + RandomStringUtils.randomAlphanumeric(10));
1404 UserTO userTO = createUser(userCR).getEntity();
1405 assertNotNull(userTO.getKey());
1406 }
1407 }