View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.fit.core;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNull;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  import static org.junit.jupiter.api.Assertions.fail;
28  
29  import java.util.Collection;
30  import java.util.List;
31  import java.util.Optional;
32  import java.util.Set;
33  import javax.ws.rs.core.Response;
34  import org.apache.syncope.client.lib.SyncopeClient;
35  import org.apache.syncope.common.lib.SyncopeClientException;
36  import org.apache.syncope.common.lib.request.AnyObjectCR;
37  import org.apache.syncope.common.lib.to.AnyObjectTO;
38  import org.apache.syncope.common.lib.to.Item;
39  import org.apache.syncope.common.lib.to.Mapping;
40  import org.apache.syncope.common.lib.to.OrgUnit;
41  import org.apache.syncope.common.lib.to.Provision;
42  import org.apache.syncope.common.lib.to.ResourceTO;
43  import org.apache.syncope.common.lib.types.AnyTypeKind;
44  import org.apache.syncope.common.lib.types.ClientExceptionType;
45  import org.apache.syncope.common.lib.types.ConnConfPropSchema;
46  import org.apache.syncope.common.lib.types.ConnConfProperty;
47  import org.apache.syncope.common.lib.types.EntityViolationType;
48  import org.apache.syncope.common.lib.types.IdMImplementationType;
49  import org.apache.syncope.common.lib.types.MappingPurpose;
50  import org.apache.syncope.common.lib.types.TraceLevel;
51  import org.apache.syncope.common.rest.api.service.ResourceService;
52  import org.apache.syncope.fit.AbstractITCase;
53  import org.identityconnectors.framework.common.objects.ObjectClass;
54  import org.junit.jupiter.api.Assertions;
55  import org.junit.jupiter.api.Test;
56  
57  public class ResourceITCase extends AbstractITCase {
58  
59      private static ResourceTO buildResourceTO(final String resourceKey) {
60          ResourceTO resourceTO = new ResourceTO();
61  
62          resourceTO.setKey(resourceKey);
63          resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
64  
65          Provision provisionTO = new Provision();
66          provisionTO.setAnyType(AnyTypeKind.USER.name());
67          provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
68          resourceTO.getProvisions().add(provisionTO);
69  
70          Mapping mapping = new Mapping();
71          provisionTO.setMapping(mapping);
72  
73          Item item = new Item();
74          item.setExtAttrName("userId");
75          item.setIntAttrName("userId");
76          item.setPurpose(MappingPurpose.BOTH);
77          mapping.add(item);
78  
79          item = new Item();
80          item.setExtAttrName("username");
81          item.setIntAttrName("key");
82          item.setPurpose(MappingPurpose.BOTH);
83          mapping.setConnObjectKeyItem(item);
84  
85          item = new Item();
86          item.setExtAttrName("fullname");
87          item.setIntAttrName("cn");
88          item.setConnObjectKey(false);
89          item.setPurpose(MappingPurpose.PROPAGATION);
90          mapping.add(item);
91  
92          return resourceTO;
93      }
94  
95      @Test
96      public void getPropagationActionsClasses() {
97          Set<String> actions = ANONYMOUS_CLIENT.platform().
98                  getJavaImplInfo(IdMImplementationType.PROPAGATION_ACTIONS).get().getClasses();
99          assertNotNull(actions);
100         assertFalse(actions.isEmpty());
101     }
102 
103     @Test
104     public void create() {
105         String resourceKey = "ws-target-resource-create";
106         ResourceTO resourceTO = buildResourceTO(resourceKey);
107 
108         Response response = RESOURCE_SERVICE.create(resourceTO);
109         resourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
110         assertNotNull(resourceTO);
111 
112         // check for existence
113         resourceTO = RESOURCE_SERVICE.read(resourceKey);
114         assertNotNull(resourceTO);
115     }
116 
117     @Test
118     public void createOverridingProps() {
119         String resourceKey = "overriding-conn-conf-target-resource-create";
120         ResourceTO resourceTO = new ResourceTO();
121 
122         Provision provisionTO = new Provision();
123         provisionTO.setAnyType(AnyTypeKind.USER.name());
124         provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
125         resourceTO.getProvisions().add(provisionTO);
126 
127         Mapping mapping = new Mapping();
128         provisionTO.setMapping(mapping);
129 
130         Item item = new Item();
131         item.setExtAttrName("uid");
132         item.setIntAttrName("userId");
133         item.setPurpose(MappingPurpose.BOTH);
134         mapping.add(item);
135 
136         item = new Item();
137         item.setExtAttrName("username");
138         item.setIntAttrName("key");
139         item.setConnObjectKey(true);
140         item.setPurpose(MappingPurpose.BOTH);
141         mapping.setConnObjectKeyItem(item);
142 
143         item = new Item();
144         item.setExtAttrName("fullname");
145         item.setIntAttrName("cn");
146         item.setConnObjectKey(false);
147         item.setPurpose(MappingPurpose.PROPAGATION);
148         mapping.add(item);
149 
150         resourceTO.setKey(resourceKey);
151         resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
152 
153         ConnConfProperty prop = new ConnConfProperty();
154         ConnConfPropSchema schema = new ConnConfPropSchema();
155         schema.setType("java.lang.String");
156         schema.setName("endpoint");
157         schema.setRequired(true);
158         prop.setSchema(schema);
159         prop.getValues().add("http://invalidurl/");
160 
161         Set<ConnConfProperty> connectorConfigurationProperties = Set.of(prop);
162         resourceTO.getConfOverride().addAll(connectorConfigurationProperties);
163 
164         Response response = RESOURCE_SERVICE.create(resourceTO);
165         ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
166         assertNotNull(actual);
167 
168         // check the existence
169         actual = RESOURCE_SERVICE.read(resourceKey);
170         assertNotNull(actual);
171         assertNull(actual.getPropagationPriority());
172     }
173 
174     @Test
175     public void createWithSingleMappingItem() {
176         String resourceKey = RESOURCE_NAME_CREATE_SINGLE;
177         ResourceTO resourceTO = new ResourceTO();
178         resourceTO.setKey(resourceKey);
179         resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
180 
181         Provision provisionTO = new Provision();
182         provisionTO.setAnyType(AnyTypeKind.USER.name());
183         provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
184         resourceTO.getProvisions().add(provisionTO);
185 
186         Mapping mapping = new Mapping();
187         provisionTO.setMapping(mapping);
188 
189         Item item = new Item();
190         item.setIntAttrName("key");
191         item.setExtAttrName("userId");
192         item.setConnObjectKey(true);
193         item.setPurpose(MappingPurpose.PROPAGATION);
194         mapping.setConnObjectKeyItem(item);
195 
196         provisionTO = new Provision();
197         provisionTO.setAnyType(AnyTypeKind.GROUP.name());
198         provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
199         resourceTO.getProvisions().add(provisionTO);
200 
201         mapping = new Mapping();
202         provisionTO.setMapping(mapping);
203         item = new Item();
204         item.setIntAttrName("key");
205         item.setExtAttrName("groupId");
206         item.setConnObjectKey(true);
207         item.setPurpose(MappingPurpose.PULL);
208         mapping.setConnObjectKeyItem(item);
209 
210         Response response = RESOURCE_SERVICE.create(resourceTO);
211         ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
212 
213         assertNotNull(actual);
214         assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).get().getMapping());
215         assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).get().getMapping().getItems());
216         assertNotNull(actual.getProvision(AnyTypeKind.GROUP.name()).get().getMapping());
217         assertNotNull(actual.getProvision(AnyTypeKind.GROUP.name()).get().getMapping().getItems());
218         assertEquals(
219                 MappingPurpose.PULL,
220                 actual.getProvision(AnyTypeKind.GROUP.name()).get().getMapping().
221                         getConnObjectKeyItem().get().getPurpose());
222         assertEquals(
223                 MappingPurpose.PROPAGATION,
224                 actual.getProvision(AnyTypeKind.USER.name()).get().getMapping().
225                         getConnObjectKeyItem().get().getPurpose());
226     }
227 
228     @Test
229     public void createWithInvalidMapping() {
230         String resourceKey = RESOURCE_NAME_CREATE_WRONG;
231         ResourceTO resourceTO = new ResourceTO();
232         resourceTO.setKey(resourceKey);
233         resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
234 
235         Provision provisionTO = new Provision();
236         provisionTO.setAnyType(AnyTypeKind.USER.name());
237         provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
238         resourceTO.getProvisions().add(provisionTO);
239 
240         Mapping mapping = new Mapping();
241         provisionTO.setMapping(mapping);
242 
243         Item item = new Item();
244         item.setIntAttrName("key");
245         item.setExtAttrName("userId");
246         item.setConnObjectKey(true);
247         mapping.setConnObjectKeyItem(item);
248 
249         item = new Item();
250         item.setExtAttrName("email");
251         // missing intAttrName ...
252         mapping.add(item);
253 
254         try {
255             createResource(resourceTO);
256             fail("Create should not have worked");
257         } catch (SyncopeClientException e) {
258             assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
259             assertEquals("intAttrName", e.getElements().iterator().next());
260         }
261     }
262 
263     @Test
264     public void createWithoutExtAttr() {
265         assertThrows(SyncopeClientException.class, () -> {
266             String resourceKey = RESOURCE_NAME_CREATE_WRONG;
267             ResourceTO resourceTO = new ResourceTO();
268             resourceTO.setKey(resourceKey);
269             resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
270 
271             Provision provisionTO = new Provision();
272             provisionTO.setAnyType(AnyTypeKind.USER.name());
273             provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
274             resourceTO.getProvisions().add(provisionTO);
275 
276             Mapping mapping = new Mapping();
277             provisionTO.setMapping(mapping);
278 
279             Item item = new Item();
280             item.setIntAttrName("key");
281             item.setExtAttrName("userId");
282             item.setConnObjectKey(true);
283             mapping.setConnObjectKeyItem(item);
284 
285             item = new Item();
286             item.setIntAttrName("usernane");
287             // missing extAttrName ...
288             mapping.add(item);
289 
290             createResource(resourceTO);
291         });
292     }
293 
294     @Test
295     public void createWithPasswordPolicy() {
296         String resourceKey = "res-with-password-policy";
297         ResourceTO resourceTO = new ResourceTO();
298         resourceTO.setKey(resourceKey);
299         resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
300         resourceTO.setPasswordPolicy("986d1236-3ac5-4a19-810c-5ab21d79cba1");
301 
302         Provision provisionTO = new Provision();
303         provisionTO.setAnyType(AnyTypeKind.USER.name());
304         provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
305         resourceTO.getProvisions().add(provisionTO);
306 
307         Mapping mapping = new Mapping();
308         provisionTO.setMapping(mapping);
309 
310         Item item = new Item();
311         item.setExtAttrName("userId");
312         item.setIntAttrName("userId");
313         item.setConnObjectKey(true);
314         item.setPurpose(MappingPurpose.BOTH);
315         mapping.setConnObjectKeyItem(item);
316 
317         Response response = RESOURCE_SERVICE.create(resourceTO);
318         ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
319         assertNotNull(actual);
320 
321         // check the existence
322         actual = RESOURCE_SERVICE.read(resourceKey);
323         assertNotNull(actual);
324         assertNotNull(actual.getPasswordPolicy());
325         assertEquals("986d1236-3ac5-4a19-810c-5ab21d79cba1", actual.getPasswordPolicy());
326     }
327 
328     @Test
329     public void updateWithException() {
330         try {
331             ResourceTO resourceTO = new ResourceTO();
332             resourceTO.setKey("resourcenotfound");
333             RESOURCE_SERVICE.update(resourceTO);
334 
335             fail("This should not happen");
336         } catch (SyncopeClientException e) {
337             assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
338         }
339     }
340 
341     @Test
342     public void update() {
343         String resourceKey = RESOURCE_NAME_UPDATE;
344         ResourceTO resourceTO = new ResourceTO();
345         resourceTO.setKey(resourceKey);
346         resourceTO.setConnector("5aa5b8be-7521-481a-9651-c557aea078c1");
347 
348         Provision provisionTO = new Provision();
349         provisionTO.setAnyType(AnyTypeKind.USER.name());
350         provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
351         resourceTO.getProvisions().add(provisionTO);
352 
353         Mapping mapping = new Mapping();
354         provisionTO.setMapping(mapping);
355 
356         // Update with an existing and already assigned mapping
357         Item item = new Item();
358         item.setExtAttrName("test3");
359         item.setIntAttrName("fullname");
360         item.setPurpose(MappingPurpose.BOTH);
361         mapping.add(item);
362 
363         // Update defining new mappings
364         for (int i = 4; i < 6; i++) {
365             item = new Item();
366             item.setExtAttrName("test" + i);
367             item.setIntAttrName("fullname");
368             item.setPurpose(MappingPurpose.BOTH);
369             mapping.add(item);
370         }
371         item = new Item();
372         item.setExtAttrName("username");
373         item.setIntAttrName("key");
374         item.setConnObjectKey(true);
375         item.setPurpose(MappingPurpose.BOTH);
376         mapping.setConnObjectKeyItem(item);
377 
378         RESOURCE_SERVICE.update(resourceTO);
379         ResourceTO actual = RESOURCE_SERVICE.read(resourceTO.getKey());
380         assertNotNull(actual);
381 
382         // check for existence
383         Collection<Item> mapItems = actual.getProvision(AnyTypeKind.USER.name()).get().getMapping().getItems();
384         assertNotNull(mapItems);
385         assertEquals(4, mapItems.size());
386     }
387 
388     @Test
389     public void deleteWithException() {
390         try {
391             RESOURCE_SERVICE.delete("resourcenotfound");
392             fail("This should not happen");
393         } catch (SyncopeClientException e) {
394             assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
395         }
396     }
397 
398     @Test
399     public void syncToken() {
400         ResourceTO resource = RESOURCE_SERVICE.read(RESOURCE_NAME_DBSCRIPTED);
401         resource.setKey(resource.getKey() + getUUIDString());
402 
403         AnyObjectCR anyObjectCR = AnyObjectITCase.getSample("syncToken");
404         anyObjectCR.getResources().clear();
405         anyObjectCR.getResources().add(resource.getKey());
406 
407         AnyObjectTO anyObject = null;
408         try {
409             // create a new resource
410             resource = createResource(resource);
411             assertNull(resource.getProvision(PRINTER).get().getSyncToken());
412 
413             // create some object on the new resource
414             anyObject = createAnyObject(anyObjectCR).getEntity();
415 
416             // update sync token
417             RESOURCE_SERVICE.setLatestSyncToken(resource.getKey(), PRINTER);
418 
419             resource = RESOURCE_SERVICE.read(resource.getKey());
420             assertNotNull(resource.getProvision(PRINTER).get().getSyncToken());
421 
422             // remove sync token
423             RESOURCE_SERVICE.removeSyncToken(resource.getKey(), PRINTER);
424 
425             resource = RESOURCE_SERVICE.read(resource.getKey());
426             assertNull(resource.getProvision(PRINTER).get().getSyncToken());
427         } finally {
428             if (anyObject != null) {
429                 ANY_OBJECT_SERVICE.delete(anyObject.getKey());
430             }
431             RESOURCE_SERVICE.delete(resource.getKey());
432         }
433     }
434 
435     @Test
436     public void delete() {
437         String resourceKey = "tobedeleted";
438 
439         ResourceTO resource = buildResourceTO(resourceKey);
440         Response response = RESOURCE_SERVICE.create(resource);
441         ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
442         assertNotNull(actual);
443 
444         RESOURCE_SERVICE.delete(resourceKey);
445 
446         try {
447             RESOURCE_SERVICE.read(resourceKey);
448             fail("This should not happen");
449         } catch (SyncopeClientException e) {
450             assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
451         }
452     }
453 
454     @Test
455     public void orgUnit() {
456         String resourceKey = "ws-orgunit";
457         ResourceTO resourceTO = buildResourceTO(resourceKey);
458         assertNull(resourceTO.getOrgUnit());
459         assertNull(resourceTO.getPropagationPriority());
460 
461         Response response = RESOURCE_SERVICE.create(resourceTO);
462         resourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
463         assertNotNull(resourceTO);
464         assertNull(resourceTO.getOrgUnit());
465 
466         OrgUnit orgUnit = new OrgUnit();
467         orgUnit.setConnObjectLink("'ou=' + name + ',o=isp'");
468         orgUnit.setObjectClass("organizationalUnit");
469 
470         Item item = new Item();
471         item.setIntAttrName("name");
472         item.setExtAttrName("ou");
473         item.setMandatoryCondition("true");
474         item.setPurpose(MappingPurpose.BOTH);
475         orgUnit.setConnObjectKeyItem(item);
476 
477         resourceTO.setOrgUnit(orgUnit);
478         RESOURCE_SERVICE.update(resourceTO);
479         assertNull(resourceTO.getPropagationPriority());
480 
481         resourceTO = RESOURCE_SERVICE.read(resourceKey);
482         assertNotNull(resourceTO.getOrgUnit());
483 
484         resourceTO.setOrgUnit(null);
485         resourceTO.setPropagationPriority(11);
486         RESOURCE_SERVICE.update(resourceTO);
487 
488         resourceTO = RESOURCE_SERVICE.read(resourceKey);
489         assertNull(resourceTO.getOrgUnit());
490         assertEquals(11, resourceTO.getPropagationPriority());
491     }
492 
493     @Test
494     public void list() {
495         List<ResourceTO> actuals = RESOURCE_SERVICE.list();
496         assertNotNull(actuals);
497         assertFalse(actuals.isEmpty());
498         actuals.forEach(Assertions::assertNotNull);
499     }
500 
501     @Test
502     public void read() {
503         ResourceTO resource = RESOURCE_SERVICE.read(RESOURCE_NAME_DBVIRATTR);
504         assertNotNull(resource);
505 
506         Optional<Provision> provision = resource.getProvision(AnyTypeKind.USER.name());
507         assertTrue(provision.isPresent());
508         assertFalse(provision.get().getMapping().getItems().isEmpty());
509         assertFalse(provision.get().getMapping().getLinkingItems().isEmpty());
510     }
511 
512     @Test
513     public void authorizations() {
514         SyncopeClient puccini = CLIENT_FACTORY.create("puccini", ADMIN_PWD);
515         ResourceService prs = puccini.getService(ResourceService.class);
516 
517         // 1. attempt to read a resource for a connector with a different admin realm: fail
518         try {
519             prs.read(RESOURCE_NAME_WS1);
520             fail("This should not happen");
521         } catch (SyncopeClientException e) {
522             assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
523         }
524 
525         // 2. read and upate a resource for a connector in the realm for which entitlements are owned: succeed
526         try {
527             ResourceTO scriptedsql = prs.read(RESOURCE_NAME_DBSCRIPTED);
528             assertEquals(TraceLevel.ALL, scriptedsql.getCreateTraceLevel());
529 
530             scriptedsql.setCreateTraceLevel(TraceLevel.FAILURES);
531             prs.update(scriptedsql);
532 
533             scriptedsql = prs.read(RESOURCE_NAME_DBSCRIPTED);
534             assertEquals(TraceLevel.FAILURES, scriptedsql.getCreateTraceLevel());
535         } finally {
536             ResourceTO scriptedsql = RESOURCE_SERVICE.read(RESOURCE_NAME_DBSCRIPTED);
537             scriptedsql.setCreateTraceLevel(TraceLevel.ALL);
538             RESOURCE_SERVICE.update(scriptedsql);
539         }
540     }
541 
542     @Test
543     public void issueSYNCOPE323() {
544         ResourceTO actual = RESOURCE_SERVICE.read(RESOURCE_NAME_TESTDB);
545         assertNotNull(actual);
546 
547         try {
548             createResource(actual);
549             fail("This should not happen");
550         } catch (SyncopeClientException e) {
551             assertEquals(Response.Status.CONFLICT, e.getType().getResponseStatus());
552             assertEquals(ClientExceptionType.EntityExists, e.getType());
553         }
554 
555         actual.setKey(null);
556         try {
557             createResource(actual);
558             fail("This should not happen");
559         } catch (SyncopeClientException e) {
560             assertEquals(Response.Status.BAD_REQUEST, e.getType().getResponseStatus());
561             assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
562         }
563     }
564 
565     @Test
566     public void issueSYNCOPE360() {
567         final String name = "SYNCOPE360-" + getUUIDString();
568         RESOURCE_SERVICE.create(buildResourceTO(name));
569 
570         ResourceTO resource = RESOURCE_SERVICE.read(name);
571         assertNotNull(resource);
572         assertNotNull(resource.getProvision(AnyTypeKind.USER.name()).get().getMapping());
573 
574         resource.getProvision(AnyTypeKind.USER.name()).get().setMapping(null);
575         RESOURCE_SERVICE.update(resource);
576 
577         resource = RESOURCE_SERVICE.read(name);
578         assertNotNull(resource);
579         assertNull(resource.getProvision(AnyTypeKind.USER.name()).get().getMapping());
580     }
581 
582     @Test
583     public void issueSYNCOPE368() {
584         final String name = "SYNCOPE368-" + getUUIDString();
585 
586         ResourceTO resourceTO = new ResourceTO();
587 
588         resourceTO.setKey(name);
589         resourceTO.setConnector("74141a3b-0762-4720-a4aa-fc3e374ef3ef");
590 
591         Provision provisionTO = new Provision();
592         provisionTO.setAnyType(AnyTypeKind.GROUP.name());
593         provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
594         resourceTO.getProvisions().add(provisionTO);
595 
596         Mapping mapping = new Mapping();
597         provisionTO.setMapping(mapping);
598 
599         Item item = new Item();
600         item.setIntAttrName("name");
601         item.setExtAttrName("cn");
602         item.setPurpose(MappingPurpose.BOTH);
603         mapping.setConnObjectKeyItem(item);
604 
605         item = new Item();
606         item.setIntAttrName("userOwner");
607         item.setExtAttrName("owner");
608         item.setPurpose(MappingPurpose.BOTH);
609         mapping.add(item);
610 
611         resourceTO = createResource(resourceTO);
612         assertNotNull(resourceTO);
613         assertEquals(2, resourceTO.getProvision(AnyTypeKind.GROUP.name()).get().getMapping().getItems().size());
614     }
615 
616     @Test
617     public void issueSYNCOPE418() {
618         try {
619             RESOURCE_SERVICE.create(
620                     buildResourceTO("http://schemas.examples.org/security/authorization/organizationUnit"));
621             fail("This should not happen");
622         } catch (SyncopeClientException e) {
623             assertEquals(ClientExceptionType.InvalidExternalResource, e.getType());
624             assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidKey.name()));
625         }
626     }
627 
628     @Test
629     public void issueSYNCOPE493() {
630         // create resource with attribute mapping set to NONE and check its propagation
631         String resourceKey = RESOURCE_NAME_CREATE_NONE;
632         ResourceTO resourceTO = new ResourceTO();
633         resourceTO.setKey(resourceKey);
634         resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
635 
636         Provision provisionTO = new Provision();
637         provisionTO.setAnyType(AnyTypeKind.USER.name());
638         provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
639         resourceTO.getProvisions().add(provisionTO);
640 
641         Mapping mapping = new Mapping();
642         provisionTO.setMapping(mapping);
643 
644         Item item = new Item();
645         item.setIntAttrName("key");
646         item.setExtAttrName("userId");
647         item.setConnObjectKey(true);
648         item.setPurpose(MappingPurpose.PROPAGATION);
649         mapping.setConnObjectKeyItem(item);
650 
651         Item item2 = new Item();
652         item2.setConnObjectKey(false);
653         item2.setIntAttrName("gender");
654         item2.setExtAttrName("gender");
655         item2.setPurpose(MappingPurpose.NONE);
656         mapping.add(item2);
657 
658         Response response = RESOURCE_SERVICE.create(resourceTO);
659         ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
660 
661         assertNotNull(actual);
662         assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).get().getMapping());
663         assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).get().getMapping().getItems());
664         assertEquals(
665                 MappingPurpose.PROPAGATION,
666                 actual.getProvision(AnyTypeKind.USER.name()).get().getMapping().
667                         getConnObjectKeyItem().get().getPurpose());
668         actual.getProvision(AnyTypeKind.USER.name()).get().getMapping().getItems().stream().
669                 filter(itemTO -> ("gender".equals(itemTO.getIntAttrName()))).
670                 forEach(itemTO -> assertEquals(MappingPurpose.NONE, itemTO.getPurpose()));
671     }
672 
673     public static void issueSYNCOPE645() {
674         ResourceTO resource = new ResourceTO();
675         resource.setKey("ws-target-resource-basic-save-invalid");
676 
677         String connector = RESOURCE_SERVICE.read("ws-target-resource-1").getConnector();
678         resource.setConnector(connector);
679 
680         Provision provision = new Provision();
681         provision.setAnyType(AnyTypeKind.USER.name());
682         provision.setObjectClass("__ACCOUNT__");
683         resource.getProvisions().add(provision);
684 
685         Mapping mapping = new Mapping();
686         provision.setMapping(mapping);
687 
688         Item item = new Item();
689         item.setIntAttrName("icon");
690         item.setExtAttrName("icon");
691         item.setPurpose(MappingPurpose.BOTH);
692         mapping.setConnObjectKeyItem(item);
693 
694         // save the resource
695         try {
696             RESOURCE_SERVICE.create(resource);
697             fail("This should not happen");
698         } catch (SyncopeClientException e) {
699             assertEquals(ClientExceptionType.InvalidMapping, e.getType());
700         }
701     }
702 
703     @Test
704     public void issueSYNCOPE888() {
705         String resourceKey = RESOURCE_NAME_CREATE_WRONG;
706         ResourceTO resourceTO = new ResourceTO();
707         resourceTO.setKey(resourceKey);
708         resourceTO.setConnector("5ffbb4ac-a8c3-4b44-b699-11b398a1ba08");
709 
710         Provision provisionTO = new Provision();
711         provisionTO.setAnyType(AnyTypeKind.USER.name());
712         provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
713         resourceTO.getProvisions().add(provisionTO);
714 
715         Mapping mapping = new Mapping();
716         provisionTO.setMapping(mapping);
717 
718         Item item = new Item();
719         item.setIntAttrName("key");
720         item.setExtAttrName("userId");
721         item.setConnObjectKey(true);
722         item.setPurpose(MappingPurpose.BOTH);
723         mapping.setConnObjectKeyItem(item);
724 
725         // Add mapping for a not existing internal attribute
726         item = new Item();
727         item.setIntAttrName("locatio");
728         item.setExtAttrName("location");
729         item.setPurpose(MappingPurpose.BOTH);
730         mapping.add(item);
731 
732         try {
733             createResource(resourceTO);
734             fail("Create should not have worked");
735         } catch (SyncopeClientException e) {
736             assertEquals(ClientExceptionType.InvalidMapping, e.getType());
737             assertEquals(1, e.getElements().size());
738             assertEquals("'locatio' not existing", e.getElements().iterator().next());
739         }
740     }
741 }