| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.syncope.fit.core; |
| |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertFalse; |
| import static org.junit.jupiter.api.Assertions.assertNotEquals; |
| import static org.junit.jupiter.api.Assertions.assertNotNull; |
| import static org.junit.jupiter.api.Assertions.assertTrue; |
| |
| import java.io.IOException; |
| import java.text.ParseException; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Optional; |
| import javax.ws.rs.core.Response; |
| import org.apache.syncope.client.lib.batch.BatchRequest; |
| import org.apache.syncope.common.lib.request.AnyObjectCR; |
| import org.apache.syncope.common.lib.request.AttrPatch; |
| import org.apache.syncope.common.lib.request.UserCR; |
| import org.apache.syncope.common.lib.request.UserUR; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| import org.apache.commons.lang3.SerializationUtils; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.syncope.common.lib.SyncopeClientException; |
| import org.apache.syncope.common.lib.SyncopeConstants; |
| import org.apache.syncope.common.lib.to.TaskTO; |
| import org.apache.syncope.common.lib.to.AnyObjectTO; |
| import org.apache.syncope.common.lib.Attr; |
| import org.apache.syncope.common.lib.request.GroupCR; |
| import org.apache.syncope.common.lib.request.GroupUR; |
| import org.apache.syncope.common.lib.request.MembershipUR; |
| import org.apache.syncope.common.lib.request.ResourceDR; |
| import org.apache.syncope.common.lib.to.ConnObjectTO; |
| import org.apache.syncope.common.lib.to.PagedResult; |
| import org.apache.syncope.common.lib.to.PropagationTaskTO; |
| import org.apache.syncope.common.lib.to.ExecTO; |
| import org.apache.syncope.common.lib.to.ImplementationTO; |
| import org.apache.syncope.common.lib.to.GroupTO; |
| import org.apache.syncope.common.lib.to.ItemTO; |
| import org.apache.syncope.common.lib.to.MembershipTO; |
| import org.apache.syncope.common.lib.to.PlainSchemaTO; |
| import org.apache.syncope.common.lib.to.ProvisionTO; |
| import org.apache.syncope.common.lib.to.ProvisioningResult; |
| import org.apache.syncope.common.lib.to.RelationshipTO; |
| import org.apache.syncope.common.lib.to.ResourceTO; |
| import org.apache.syncope.common.lib.to.UserTO; |
| import org.apache.syncope.common.lib.types.AnyTypeKind; |
| import org.apache.syncope.common.lib.types.ImplementationEngine; |
| import org.apache.syncope.common.lib.types.AttrSchemaType; |
| import org.apache.syncope.common.lib.types.IdRepoImplementationType; |
| import org.apache.syncope.common.lib.types.ExecStatus; |
| import org.apache.syncope.common.lib.types.MappingPurpose; |
| import org.apache.syncope.common.lib.types.PatchOperation; |
| import org.apache.syncope.common.lib.types.ResourceDeassociationAction; |
| import org.apache.syncope.common.lib.types.ResourceOperation; |
| import org.apache.syncope.common.lib.types.SchemaType; |
| import org.apache.syncope.common.lib.types.TaskType; |
| import org.apache.syncope.common.rest.api.RESTHeaders; |
| import org.apache.syncope.common.rest.api.beans.ExecuteQuery; |
| import org.apache.syncope.common.rest.api.beans.ExecQuery; |
| import org.apache.syncope.common.rest.api.beans.TaskQuery; |
| import org.apache.syncope.common.rest.api.service.TaskService; |
| import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; |
| import org.apache.syncope.fit.core.reference.DateToDateItemTransformer; |
| import org.apache.syncope.fit.core.reference.DateToLongItemTransformer; |
| import org.identityconnectors.framework.common.objects.Attribute; |
| import org.identityconnectors.framework.common.objects.AttributeUtil; |
| import org.identityconnectors.framework.common.objects.Name; |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.api.BeforeAll; |
| |
| public class PropagationTaskITCase extends AbstractTaskITCase { |
| |
| @BeforeAll |
| public static void testItemTransformersSetup() { |
| ImplementationTO dateToLong = null; |
| ImplementationTO dateToDate = null; |
| try { |
| dateToLong = implementationService.read( |
| IdRepoImplementationType.ITEM_TRANSFORMER, DateToLongItemTransformer.class.getSimpleName()); |
| dateToDate = implementationService.read( |
| IdRepoImplementationType.ITEM_TRANSFORMER, DateToDateItemTransformer.class.getSimpleName()); |
| } catch (SyncopeClientException e) { |
| if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) { |
| dateToLong = new ImplementationTO(); |
| dateToLong.setKey(DateToLongItemTransformer.class.getSimpleName()); |
| dateToLong.setEngine(ImplementationEngine.JAVA); |
| dateToLong.setType(IdRepoImplementationType.ITEM_TRANSFORMER); |
| dateToLong.setBody(DateToLongItemTransformer.class.getName()); |
| Response response = implementationService.create(dateToLong); |
| dateToLong = implementationService.read( |
| dateToLong.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY)); |
| assertNotNull(dateToLong); |
| |
| dateToDate = new ImplementationTO(); |
| dateToDate.setKey(DateToDateItemTransformer.class.getSimpleName()); |
| dateToDate.setEngine(ImplementationEngine.JAVA); |
| dateToDate.setType(IdRepoImplementationType.ITEM_TRANSFORMER); |
| dateToDate.setBody(DateToDateItemTransformer.class.getName()); |
| response = implementationService.create(dateToDate); |
| dateToDate = implementationService.read( |
| dateToDate.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY)); |
| assertNotNull(dateToDate); |
| } |
| } |
| assertNotNull(dateToLong); |
| assertNotNull(dateToDate); |
| } |
| |
| @Test |
| public void paginatedList() { |
| PagedResult<PropagationTaskTO> tasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(2).build()); |
| assertNotNull(tasks); |
| assertEquals(2, tasks.getResult().size()); |
| |
| for (TaskTO task : tasks.getResult()) { |
| assertNotNull(task); |
| } |
| |
| tasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION).page(2).size(2).build()); |
| assertNotNull(tasks); |
| assertEquals(2, tasks.getPage()); |
| assertEquals(2, tasks.getResult().size()); |
| |
| for (TaskTO task : tasks.getResult()) { |
| assertNotNull(task); |
| } |
| |
| tasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION).page(1000).size(2).build()); |
| assertNotNull(tasks); |
| assertTrue(tasks.getResult().isEmpty()); |
| } |
| |
| @Test |
| public void read() { |
| PropagationTaskTO taskTO = taskService.read(TaskType.PROPAGATION, "316285cc-ae52-4ea2-a33b-7355e189ac3f", true); |
| assertNotNull(taskTO); |
| assertNotNull(taskTO.getExecutions()); |
| assertTrue(taskTO.getExecutions().isEmpty()); |
| } |
| |
| @Test |
| public void batch() throws IOException { |
| // create user with testdb resource |
| UserCR userCR = UserITCase.getUniqueSample("taskBatch@apache.org"); |
| userCR.getResources().add(RESOURCE_NAME_TESTDB); |
| UserTO userTO = createUser(userCR).getEntity(); |
| |
| List<PropagationTaskTO> tasks = new ArrayList<>( |
| taskService.<PropagationTaskTO>search(new TaskQuery.Builder(TaskType.PROPAGATION). |
| anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build()). |
| getResult()); |
| assertFalse(tasks.isEmpty()); |
| |
| BatchRequest batchRequest = adminClient.batch(); |
| |
| TaskService batchTaskService = batchRequest.getService(TaskService.class); |
| tasks.forEach(task -> batchTaskService.delete(TaskType.PROPAGATION, task.getKey())); |
| |
| Response response = batchRequest.commit().getResponse(); |
| parseBatchResponse(response); |
| |
| assertFalse(taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION).page(1).size(100).build()). |
| getResult().containsAll(tasks)); |
| } |
| |
| @Test |
| public void propagationJEXLTransformer() { |
| // 0. Set propagation JEXL MappingItemTransformer |
| ResourceTO resource = resourceService.read(RESOURCE_NAME_DBSCRIPTED); |
| ResourceTO originalResource = SerializationUtils.clone(resource); |
| ProvisionTO provision = resource.getProvision(PRINTER).get(); |
| assertNotNull(provision); |
| |
| Optional<ItemTO> mappingItem = provision.getMapping().getItems().stream(). |
| filter(item -> "location".equals(item.getIntAttrName())).findFirst(); |
| assertTrue(mappingItem.isPresent()); |
| assertTrue(mappingItem.get().getTransformers().isEmpty()); |
| |
| String suffix = getUUIDString(); |
| mappingItem.get().setPropagationJEXLTransformer("value + '" + suffix + '\''); |
| |
| try { |
| resourceService.update(resource); |
| |
| // 1. create printer on external resource |
| AnyObjectCR anyObjectCR = AnyObjectITCase.getSample("propagationJEXLTransformer"); |
| String originalLocation = anyObjectCR.getPlainAttr("location").get().getValues().get(0); |
| assertFalse(originalLocation.endsWith(suffix)); |
| |
| AnyObjectTO anyObjectTO = createAnyObject(anyObjectCR).getEntity(); |
| assertNotNull(anyObjectTO); |
| |
| // 2. verify that JEXL MappingItemTransformer was applied during propagation |
| // (location ends with given suffix on external resource) |
| ConnObjectTO connObjectTO = resourceService. |
| readConnObject(RESOURCE_NAME_DBSCRIPTED, anyObjectTO.getType(), anyObjectTO.getKey()); |
| assertFalse(anyObjectTO.getPlainAttr("location").get().getValues().get(0).endsWith(suffix)); |
| assertTrue(connObjectTO.getAttr("LOCATION").get().getValues().get(0).endsWith(suffix)); |
| } finally { |
| resourceService.update(originalResource); |
| } |
| } |
| |
| @Test |
| public void privileges() { |
| ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP); |
| ldap.setKey("ldapWithPrivileges"); |
| |
| ProvisionTO provision = ldap.getProvision(AnyTypeKind.USER.name()).orElse(null); |
| provision.getMapping().getItems().removeIf(item -> "mail".equals(item.getIntAttrName())); |
| provision.getVirSchemas().clear(); |
| |
| ldap.getProvisions().clear(); |
| ldap.getProvisions().add(provision); |
| |
| ItemTO item = new ItemTO(); |
| item.setIntAttrName("privileges[mightyApp]"); |
| item.setExtAttrName("businessCategory"); |
| item.setPurpose(MappingPurpose.PROPAGATION); |
| |
| provision.getMapping().add(item); |
| |
| ldap = createResource(ldap); |
| |
| try { |
| UserCR userCR = UserITCase.getUniqueSample("privilege@syncope.apache.org"); |
| userCR.getResources().add(ldap.getKey()); |
| userCR.getRoles().add("Other"); |
| |
| ProvisioningResult<UserTO> result = createUser(userCR); |
| assertEquals(1, result.getPropagationStatuses().size()); |
| assertNotNull(result.getPropagationStatuses().get(0).getAfterObj()); |
| |
| Attr businessCategory = |
| result.getPropagationStatuses().get(0).getAfterObj().getAttr("businessCategory").orElse(null); |
| assertNotNull(businessCategory); |
| assertEquals(1, businessCategory.getValues().size()); |
| assertEquals("postMighty", businessCategory.getValues().get(0)); |
| } finally { |
| resourceService.delete(ldap.getKey()); |
| } |
| } |
| |
| @Test |
| public void issueSYNCOPE741() { |
| for (int i = 0; i < 3; i++) { |
| taskService.execute(new ExecuteQuery.Builder(). |
| key("1e697572-b896-484c-ae7f-0c8f63fcbc6c").build()); |
| taskService.execute(new ExecuteQuery.Builder(). |
| key("316285cc-ae52-4ea2-a33b-7355e189ac3f").build()); |
| } |
| try { |
| Thread.sleep(3000); |
| } catch (InterruptedException e) { |
| // ignore |
| } |
| |
| // check list |
| PagedResult<TaskTO> tasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION). |
| page(1).size(2).orderBy("operation DESC").details(false).build()); |
| for (TaskTO item : tasks.getResult()) { |
| assertTrue(item.getExecutions().isEmpty()); |
| } |
| |
| tasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION). |
| page(1).size(2).orderBy("operation DESC").details(true).build()); |
| for (TaskTO item : tasks.getResult()) { |
| assertFalse(item.getExecutions().isEmpty()); |
| } |
| |
| // check read |
| PropagationTaskTO task = taskService.read(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c", false); |
| assertNotNull(task); |
| assertEquals("1e697572-b896-484c-ae7f-0c8f63fcbc6c", task.getKey()); |
| assertTrue(task.getExecutions().isEmpty()); |
| |
| task = taskService.read(TaskType.PROPAGATION, "1e697572-b896-484c-ae7f-0c8f63fcbc6c", true); |
| assertNotNull(task); |
| assertEquals("1e697572-b896-484c-ae7f-0c8f63fcbc6c", task.getKey()); |
| assertFalse(task.getExecutions().isEmpty()); |
| |
| // check list executions |
| PagedResult<ExecTO> execs = taskService.listExecutions(new ExecQuery.Builder().key( |
| "1e697572-b896-484c-ae7f-0c8f63fcbc6c"). |
| page(1).size(2).build()); |
| assertTrue(execs.getTotalCount() >= execs.getResult().size()); |
| } |
| |
| @Test |
| public void issueSYNCOPE1288() { |
| // create a new user |
| UserCR userCR = UserITCase.getUniqueSample("xxxyyy@xxx.xxx"); |
| userCR.getResources().add(RESOURCE_NAME_LDAP); |
| |
| UserTO userTO = createUser(userCR).getEntity(); |
| assertNotNull(userTO); |
| |
| // generate some PropagationTasks |
| for (int i = 0; i < 9; i++) { |
| UserUR userUR = new UserUR(); |
| userUR.setKey(userTO.getKey()); |
| userUR.getPlainAttrs().add(new AttrPatch.Builder(new Attr.Builder("userId").value( |
| "test" + getUUIDString() + i + "@test.com").build()). |
| operation(PatchOperation.ADD_REPLACE). |
| build()); |
| |
| userService.update(userUR); |
| } |
| |
| // ASC order |
| PagedResult<TaskTO> unorderedTasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(RESOURCE_NAME_LDAP). |
| entityKey(userTO.getKey()). |
| anyTypeKind(AnyTypeKind.USER). |
| page(1). |
| size(10). |
| build()); |
| Collections.sort(unorderedTasks.getResult(), (t1, t2) -> t1.getStart().compareTo(t2.getStart())); |
| assertNotNull(unorderedTasks); |
| assertFalse(unorderedTasks.getResult().isEmpty()); |
| assertEquals(10, unorderedTasks.getResult().size()); |
| |
| PagedResult<TaskTO> orderedTasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(RESOURCE_NAME_LDAP). |
| entityKey(userTO.getKey()). |
| anyTypeKind(AnyTypeKind.USER). |
| page(1). |
| size(10). |
| orderBy("start"). |
| build()); |
| assertNotNull(orderedTasks); |
| assertFalse(orderedTasks.getResult().isEmpty()); |
| assertEquals(10, orderedTasks.getResult().size()); |
| |
| assertTrue(orderedTasks.getResult().equals(unorderedTasks.getResult())); |
| |
| // DESC order |
| Collections.reverse(unorderedTasks.getResult()); |
| orderedTasks = taskService.search( |
| new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(RESOURCE_NAME_LDAP). |
| entityKey(userTO.getKey()). |
| anyTypeKind(AnyTypeKind.USER). |
| page(1). |
| size(10). |
| orderBy("start DESC"). |
| build()); |
| |
| assertTrue(orderedTasks.getResult().equals(unorderedTasks.getResult())); |
| } |
| |
| @Test |
| public void issueSYNCOPE1430() throws ParseException { |
| ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP); |
| try { |
| // 1. clone the LDAP resource and add some sensible mappings |
| ProvisionTO provision = ldap.getProvision(AnyTypeKind.USER.name()).orElse(null); |
| assertNotNull(provision); |
| provision.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName())); |
| provision.getVirSchemas().clear(); |
| |
| // Date -> long (JEXL expression) -> string (as all JEXL in Syncope) |
| ItemTO loginDateForJexlAsLong = new ItemTO(); |
| loginDateForJexlAsLong.setPurpose(MappingPurpose.PROPAGATION); |
| loginDateForJexlAsLong.setIntAttrName("loginDate"); |
| loginDateForJexlAsLong.setExtAttrName("employeeNumber"); |
| loginDateForJexlAsLong.setPropagationJEXLTransformer("value.getTime()"); |
| provision.getMapping().add(loginDateForJexlAsLong); |
| |
| // Date -> string (JEXL expression) |
| ItemTO loginDateForJexlAsString = new ItemTO(); |
| loginDateForJexlAsString.setPurpose(MappingPurpose.PROPAGATION); |
| loginDateForJexlAsString.setIntAttrName("loginDate"); |
| loginDateForJexlAsString.setExtAttrName("street"); |
| loginDateForJexlAsString.setPropagationJEXLTransformer( |
| "value.toInstant().toString().split(\"T\")[0].replace(\"-\", \"\")"); |
| provision.getMapping().add(loginDateForJexlAsString); |
| |
| // Date -> long |
| ItemTO loginDateForJavaToLong = new ItemTO(); |
| loginDateForJavaToLong.setPurpose(MappingPurpose.PROPAGATION); |
| loginDateForJavaToLong.setIntAttrName("loginDate"); |
| loginDateForJavaToLong.setExtAttrName("st"); |
| loginDateForJavaToLong.getTransformers().add(DateToLongItemTransformer.class.getSimpleName()); |
| provision.getMapping().add(loginDateForJavaToLong); |
| |
| // Date -> date |
| ItemTO loginDateForJavaToDate = new ItemTO(); |
| loginDateForJavaToDate.setPurpose(MappingPurpose.PROPAGATION); |
| loginDateForJavaToDate.setIntAttrName("loginDate"); |
| loginDateForJavaToDate.setExtAttrName("carLicense"); |
| loginDateForJavaToDate.getTransformers().add(DateToDateItemTransformer.class.getSimpleName()); |
| provision.getMapping().add(loginDateForJavaToDate); |
| |
| ldap.getProvisions().clear(); |
| ldap.getProvisions().add(provision); |
| ldap.setKey(RESOURCE_NAME_LDAP + "1430" + getUUIDString()); |
| resourceService.create(ldap); |
| |
| // 2. create user with the new resource assigned |
| UserCR createReq = UserITCase.getUniqueSample("syncope1430@syncope.apache.org"); |
| createReq.getResources().clear(); |
| createReq.getResources().add(ldap.getKey()); |
| createReq.getPlainAttrs().removeIf(attr -> "loginDate".equals(attr.getSchema())); |
| createReq.getPlainAttrs().add(attr("loginDate", "2019-01-29")); |
| UserTO user = createUser(createReq).getEntity(); |
| |
| // 3. check attributes prepared for propagation |
| PagedResult<PropagationTaskTO> tasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(user.getResources().iterator().next()). |
| anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build()); |
| assertEquals(1, tasks.getSize()); |
| |
| Set<Attribute> propagationAttrs = new HashSet<>(); |
| if (StringUtils.isNotBlank(tasks.getResult().get(0).getAttributes())) { |
| propagationAttrs.addAll(List.of( |
| POJOHelper.deserialize(tasks.getResult().get(0).getAttributes(), Attribute[].class))); |
| } |
| |
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| |
| Calendar loginDate = Calendar.getInstance(); |
| loginDate.setTime(sdf.parse(user.getPlainAttr("loginDate").get().getValues().get(0))); |
| |
| Attribute employeeNumber = AttributeUtil.find("employeeNumber", propagationAttrs); |
| assertNotNull(employeeNumber); |
| assertEquals(String.valueOf(loginDate.getTimeInMillis()), employeeNumber.getValue().get(0)); |
| |
| Attribute street = AttributeUtil.find("street", propagationAttrs); |
| assertNotNull(street); |
| assertEquals(loginDate.toInstant().toString().split("T")[0].replace("-", ""), street.getValue().get(0)); |
| |
| Attribute st = AttributeUtil.find("st", propagationAttrs); |
| assertNotNull(st); |
| assertEquals(loginDate.getTimeInMillis(), st.getValue().get(0)); |
| |
| loginDate.add(Calendar.DAY_OF_MONTH, 1); |
| |
| Attribute carLicense = AttributeUtil.find("carLicense", propagationAttrs); |
| assertNotNull(carLicense); |
| assertEquals(sdf.format(loginDate.getTime()), carLicense.getValue().get(0)); |
| } finally { |
| try { |
| resourceService.delete(ldap.getKey()); |
| } catch (Exception ignore) { |
| // ignore |
| } |
| } |
| } |
| |
| @Test |
| public void issueSYNCOPE1473() throws ParseException { |
| // create a new group schema |
| PlainSchemaTO schemaTO = new PlainSchemaTO(); |
| schemaTO.setKey("ldapGroups" + getUUIDString()); |
| schemaTO.setType(AttrSchemaType.String); |
| schemaTO.setMultivalue(true); |
| schemaTO.setReadonly(true); |
| schemaTO.setAnyTypeClass("minimal user"); |
| |
| schemaTO = createSchema(SchemaType.PLAIN, schemaTO); |
| assertNotNull(schemaTO); |
| |
| ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP); |
| UserTO userTO = null; |
| try { |
| // 1. clone the LDAP resource and add some sensible mappings |
| ProvisionTO provisionGroup = |
| SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null)); |
| assertNotNull(provisionGroup); |
| provisionGroup.getVirSchemas().clear(); |
| |
| ProvisionTO provisionUser = |
| SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null)); |
| assertNotNull(provisionUser); |
| provisionUser.getMapping().getItems().removeIf(item -> "mail".equals(item.getExtAttrName())); |
| provisionUser.getVirSchemas().clear(); |
| |
| ItemTO ldapGroups = new ItemTO(); |
| ldapGroups.setPurpose(MappingPurpose.PROPAGATION); |
| ldapGroups.setIntAttrName(schemaTO.getKey()); |
| ldapGroups.setExtAttrName("ldapGroups"); |
| provisionUser.getMapping().add(ldapGroups); |
| |
| ldap.getProvisions().clear(); |
| ldap.getProvisions().add(provisionUser); |
| ldap.getProvisions().add(provisionGroup); |
| ldap.setKey(RESOURCE_NAME_LDAP + "1473" + getUUIDString()); |
| resourceService.create(ldap); |
| |
| // 1. create group with the new resource assigned |
| GroupCR groupCR = new GroupCR(); |
| groupCR.setName("SYNCOPEGROUP1473-" + getUUIDString()); |
| groupCR.setRealm(SyncopeConstants.ROOT_REALM); |
| groupCR.getResources().add(ldap.getKey()); |
| |
| GroupTO groupTO = createGroup(groupCR).getEntity(); |
| assertNotNull(groupCR); |
| |
| // 2. create user with the new resource assigned |
| UserCR userCR = UserITCase.getUniqueSample("syncope1473@syncope.apache.org"); |
| userCR.getResources().clear(); |
| userCR.getResources().add(ldap.getKey()); |
| userCR.getMemberships().add(new MembershipTO.Builder(groupTO.getKey()).build()); |
| |
| userTO = createUser(userCR).getEntity(); |
| assertNotNull(userTO); |
| |
| // 3. check attributes prepared for propagation |
| PagedResult<PropagationTaskTO> tasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(userTO.getResources().iterator().next()). |
| anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build()); |
| assertEquals(1, tasks.getSize()); |
| |
| ResourceDR resourceDR = new ResourceDR.Builder().key(groupTO.getKey()). |
| action(ResourceDeassociationAction.UNLINK).resource(ldap.getKey()).build(); |
| |
| groupService.deassociate(resourceDR); |
| groupService.delete(groupTO.getKey()); |
| |
| GroupCR newGroupCR = new GroupCR(); |
| newGroupCR.setName("NEWSYNCOPEGROUP1473-" + getUUIDString()); |
| newGroupCR.setRealm(SyncopeConstants.ROOT_REALM); |
| newGroupCR.getResources().add(ldap.getKey()); |
| |
| GroupTO newGroupTO = createGroup(newGroupCR).getEntity(); |
| assertNotNull(newGroupTO); |
| |
| UserUR userUR = new UserUR(); |
| userUR.setKey(userTO.getKey()); |
| userUR.getMemberships().add( |
| new MembershipUR.Builder(newGroupTO.getKey()).operation(PatchOperation.ADD_REPLACE).build()); |
| userService.update(userUR); |
| |
| ConnObjectTO connObject = |
| resourceService.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey()); |
| assertNotNull(connObject); |
| assertTrue(connObject.getAttr("ldapGroups").isPresent()); |
| assertEquals(2, connObject.getAttr("ldapGroups").get().getValues().size()); |
| } finally { |
| try { |
| resourceService.delete(ldap.getKey()); |
| if (userTO != null) { |
| userService.delete(userTO.getKey()); |
| } |
| schemaService.delete(SchemaType.PLAIN, schemaTO.getKey()); |
| } catch (Exception ignore) { |
| // ignore |
| } |
| } |
| } |
| |
| @Test |
| public void issueSYNCOPE1567() { |
| ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP); |
| try { |
| // 1. clone the LDAP resource and add the relationships mapping |
| ProvisionTO provisionUser = |
| SerializationUtils.clone(ldap.getProvision(AnyTypeKind.USER.name()).orElse(null)); |
| assertNotNull(provisionUser); |
| provisionUser.getVirSchemas().clear(); |
| |
| ItemTO relationships = new ItemTO(); |
| relationships.setPurpose(MappingPurpose.PROPAGATION); |
| relationships.setIntAttrName("relationships[neighborhood][PRINTER].model"); |
| relationships.setExtAttrName("l"); |
| provisionUser.getMapping().add(relationships); |
| |
| ldap.getProvisions().clear(); |
| ldap.getProvisions().add(provisionUser); |
| ldap.setKey(RESOURCE_NAME_LDAP + "1567" + getUUIDString()); |
| resourceService.create(ldap); |
| |
| // 1. create user with relationship and the new resource assigned |
| UserCR userCR = UserITCase.getUniqueSample("syncope1567@syncope.apache.org"); |
| userCR.getRelationships().add(new RelationshipTO.Builder(). |
| type("neighborhood").otherEnd(PRINTER, "fc6dbc3a-6c07-4965-8781-921e7401a4a5").build()); |
| userCR.getResources().clear(); |
| userCR.getResources().add(ldap.getKey()); |
| |
| UserTO userTO = createUser(userCR).getEntity(); |
| assertNotNull(userTO); |
| assertFalse(userTO.getRelationships().isEmpty()); |
| |
| // 2. check attributes prepared for propagation |
| PagedResult<PropagationTaskTO> tasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(userCR.getResources().iterator().next()). |
| anyTypeKind(AnyTypeKind.USER).entityKey(userTO.getKey()).build()); |
| assertEquals(1, tasks.getSize()); |
| |
| Set<Attribute> propagationAttrs = Stream.of( |
| POJOHelper.deserialize(tasks.getResult().get(0).getAttributes(), Attribute[].class)). |
| collect(Collectors.toSet()); |
| Attribute attr = AttributeUtil.find("l", propagationAttrs); |
| assertNotNull(attr); |
| assertNotNull(attr.getValue()); |
| assertEquals("Canon MFC8030", attr.getValue().get(0).toString()); |
| |
| // 3. check propagated value |
| ConnObjectTO connObject = |
| resourceService.readConnObject(ldap.getKey(), AnyTypeKind.USER.name(), userTO.getKey()); |
| assertNotNull(connObject); |
| assertTrue(connObject.getAttr("l").isPresent()); |
| assertEquals("Canon MFC8030", connObject.getAttr("l").get().getValues().get(0)); |
| } finally { |
| try { |
| resourceService.delete(ldap.getKey()); |
| } catch (Exception ignore) { |
| // ignore |
| } |
| } |
| } |
| |
| @Test |
| public void issueSYNCOPE1605() throws ParseException { |
| ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP); |
| try { |
| // 1. clone the LDAP resource and add some sensible mappings |
| ProvisionTO provisionGroup = |
| SerializationUtils.clone(ldap.getProvision(AnyTypeKind.GROUP.name()).orElse(null)); |
| assertNotNull(provisionGroup); |
| provisionGroup.getVirSchemas().clear(); |
| provisionGroup.getMapping().getItems().clear(); |
| |
| ItemTO item = new ItemTO(); |
| item.setConnObjectKey(true); |
| item.setIntAttrName("name"); |
| item.setExtAttrName("description"); |
| item.setPurpose(MappingPurpose.BOTH); |
| |
| provisionGroup.getMapping().setConnObjectKeyItem(item); |
| provisionGroup.getMapping().setConnObjectLink("'cn=' + originalName + ',ou=groups,o=isp'"); |
| |
| ldap.getProvisions().clear(); |
| ldap.getProvisions().add(provisionGroup); |
| |
| ldap.setKey(RESOURCE_NAME_LDAP + "1605" + getUUIDString()); |
| resourceService.create(ldap); |
| |
| // 1. create group with the new resource assigned |
| String originalName = "grp1605-" + getUUIDString(); |
| |
| GroupCR groupCR = new GroupCR(); |
| groupCR.setName("SYNCOPEGROUP1605-" + getUUIDString()); |
| groupCR.setRealm(SyncopeConstants.ROOT_REALM); |
| groupCR.getResources().add(ldap.getKey()); |
| groupCR.getPlainAttrs().add(new Attr.Builder("originalName").value(originalName).build()); |
| |
| GroupTO groupTO = createGroup(groupCR).getEntity(); |
| assertNotNull(groupTO); |
| |
| // 3. check attributes prepared for propagation |
| PagedResult<PropagationTaskTO> tasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(ldap.getKey()).anyTypeKind(AnyTypeKind.GROUP).entityKey(groupTO.getKey()).build()); |
| assertEquals(1, tasks.getSize()); |
| assertEquals(ResourceOperation.CREATE, tasks.getResult().get(0).getOperation()); |
| assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus()); |
| |
| ConnObjectTO beforeConnObject = |
| resourceService.readConnObject(ldap.getKey(), AnyTypeKind.GROUP.name(), groupTO.getKey()); |
| |
| GroupUR groupUR = new GroupUR(); |
| groupUR.setKey(groupTO.getKey()); |
| |
| groupUR.getPlainAttrs().add(attrAddReplacePatch("originalName", "new" + originalName)); |
| groupTO = updateGroup(groupUR).getEntity(); |
| |
| tasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION). |
| resource(ldap.getKey()).anyTypeKind(AnyTypeKind.GROUP).entityKey(groupTO.getKey()). |
| orderBy("start DESC").build()); |
| assertEquals(2, tasks.getSize()); |
| assertEquals(ResourceOperation.UPDATE, tasks.getResult().get(0).getOperation()); |
| assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus()); |
| |
| ConnObjectTO afterConnObject = |
| resourceService.readConnObject(ldap.getKey(), AnyTypeKind.GROUP.name(), groupTO.getKey()); |
| assertNotEquals(afterConnObject.getAttr(Name.NAME).get().getValues().get(0), |
| beforeConnObject.getAttr(Name.NAME).get().getValues().get(0)); |
| assertTrue(afterConnObject.getAttr(Name.NAME).get().getValues().get(0).contains("new" + originalName)); |
| } finally { |
| try { |
| resourceService.delete(ldap.getKey()); |
| } catch (Exception ignore) { |
| // ignore |
| } |
| } |
| } |
| } |