You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by an...@apache.org on 2022/01/14 16:02:35 UTC
[syncope] branch 2_1_X updated: [SYNCOPE-1656] remediation now is generated also on pull update failure (#302)
This is an automated email from the ASF dual-hosted git repository.
andreapatricelli pushed a commit to branch 2_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/2_1_X by this push:
new 111cd77 [SYNCOPE-1656] remediation now is generated also on pull update failure (#302)
111cd77 is described below
commit 111cd779dc400ff567e3362e0e982b64354bf3f5
Author: Andrea Patricelli <an...@apache.org>
AuthorDate: Fri Jan 14 17:02:28 2022 +0100
[SYNCOPE-1656] remediation now is generated also on pull update failure (#302)
* [SYNCOPE-1656] remediation now is generated also on pull update failure, made some refactoring
---
.../java/pushpull/AbstractPullResultHandler.java | 127 +++++++++++++--------
.../pushpull/DefaultUserPullResultHandler.java | 56 +++------
.../org/apache/syncope/fit/AbstractITCase.java | 32 ++++++
.../apache/syncope/fit/core/PullTaskITCase.java | 115 ++++++++++++++++++-
4 files changed, 243 insertions(+), 87 deletions(-)
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
index 2d84f06..3416c3e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
@@ -18,57 +18,60 @@
*/
package org.apache.syncope.core.provisioning.java.pushpull;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.syncope.common.lib.AnyOperations;
import org.apache.syncope.common.lib.patch.AnyPatch;
import org.apache.syncope.common.lib.patch.StringPatchItem;
import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.ProvisioningReport;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.AuditElements.Result;
import org.apache.syncope.common.lib.types.MatchType;
import org.apache.syncope.common.lib.types.MatchingRule;
import org.apache.syncope.common.lib.types.PatchOperation;
-import org.apache.syncope.core.provisioning.api.PropagationByResource;
import org.apache.syncope.common.lib.types.PullMode;
import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.PullMatch;
import org.apache.syncope.core.persistence.api.dao.RemediationDAO;
+import org.apache.syncope.core.persistence.api.dao.TaskDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
-import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
import org.apache.syncope.core.persistence.api.entity.Remediation;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
import org.apache.syncope.core.provisioning.api.AuditManager;
+import org.apache.syncope.core.provisioning.api.PropagationByResource;
import org.apache.syncope.core.provisioning.api.ProvisioningManager;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheKey;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
import org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException;
-import org.apache.syncope.common.lib.to.ProvisioningReport;
import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
-import org.apache.syncope.core.persistence.api.dao.PullMatch;
-import org.apache.syncope.core.persistence.api.dao.TaskDAO;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheKey;
import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullExecutor;
import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullResultHandler;
import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.SyncDelta;
import org.identityconnectors.framework.common.objects.SyncDeltaType;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
@Transactional(rollbackFor = Throwable.class)
public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHandler<PullTask, PullActions>
@@ -90,6 +93,9 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
protected UserDAO userDAO;
@Autowired
+ protected AnyTypeDAO anyTypeDAO;
+
+ @Autowired
protected TaskDAO taskDAO;
@Autowired
@@ -250,18 +256,12 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
if (profile.getTask().isRemediation()) {
// set to SUCCESS to let the incremental flow go on in case of errors
resultStatus = Result.SUCCESS;
- Remediation entity = entityFactory.newEntity(Remediation.class);
- entity.setAnyType(provision.getAnyType());
- entity.setOperation(ResourceOperation.CREATE);
- entity.setPayload(anyTO);
- entity.setError(result.getMessage());
- entity.setInstant(new Date());
- entity.setRemoteName(delta.getObject().getName().getNameValue());
- if (taskDAO.find(profile.getTask().getKey()) != null) {
- entity.setPullTask(profile.getTask());
- }
-
- remediationDAO.save(entity);
+ createRemediation(
+ provision.getAnyType(),
+ anyTO,
+ taskDAO.find(profile.getTask().getKey()) != null ? profile.getTask() : null,
+ result,
+ delta);
} else {
resultStatus = Result.FAILURE;
}
@@ -378,17 +378,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
if (profile.getTask().isRemediation()) {
// set to SUCCESS to let the incremental flow go on in case of errors
resultStatus = Result.SUCCESS;
-
- Remediation entity = entityFactory.newEntity(Remediation.class);
- entity.setAnyType(provision.getAnyType());
- entity.setOperation(ResourceOperation.UPDATE);
- entity.setPayload(anyPatch);
- entity.setError(result.getMessage());
- entity.setInstant(new Date());
- entity.setRemoteName(delta.getObject().getName().getNameValue());
- entity.setPullTask(profile.getTask());
-
- remediationDAO.save(entity);
+ createRemediation(provision.getAnyType(), anyPatch, profile.getTask(), result, delta);
} else {
resultStatus = Result.FAILURE;
}
@@ -682,16 +672,8 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
if (profile.getTask().isRemediation()) {
// set to SUCCESS to let the incremental flow go on in case of errors
resultStatus = Result.SUCCESS;
- Remediation entity = entityFactory.newEntity(Remediation.class);
- entity.setAnyType(provision.getAnyType());
- entity.setOperation(ResourceOperation.DELETE);
- entity.setPayload(match.getAny().getKey());
- entity.setError(result.getMessage());
- entity.setInstant(new Date());
- entity.setRemoteName(delta.getObject().getName().getNameValue());
- entity.setPullTask(profile.getTask());
-
- remediationDAO.save(entity);
+ createRemediation(
+ provision.getAnyType(), match.getAny().getKey(), profile.getTask(), result, delta);
}
}
@@ -948,4 +930,59 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
delta,
furtherInput);
}
+
+ protected Remediation createRemediation(
+ final AnyType anyType,
+ final String anyKey,
+ final PullTask pullTask,
+ final ProvisioningReport result,
+ final SyncDelta delta) {
+ return createRemediation(anyType, anyKey, null, null, pullTask, result, delta);
+ }
+
+ protected Remediation createRemediation(
+ final AnyType anyType,
+ final AnyTO anyTO,
+ final PullTask pullTask,
+ final ProvisioningReport result,
+ final SyncDelta delta) {
+ return createRemediation(anyType, null, anyTO, null, pullTask, result, delta);
+ }
+
+ protected Remediation createRemediation(
+ final AnyType anyType,
+ final AnyPatch anyPatch,
+ final PullTask pullTask,
+ final ProvisioningReport result,
+ final SyncDelta delta) {
+ return createRemediation(anyType, null, null, anyPatch, pullTask, result, delta);
+ }
+
+ protected Remediation createRemediation(
+ final AnyType anyType,
+ final String anyKey,
+ final AnyTO anyTO,
+ final AnyPatch anyPatch,
+ final PullTask pullTask,
+ final ProvisioningReport result,
+ final SyncDelta delta) {
+ Remediation entity = entityFactory.newEntity(Remediation.class);
+
+ entity.setAnyType(anyType);
+ entity.setOperation(anyPatch == null ? ResourceOperation.CREATE : ResourceOperation.UPDATE);
+ if (StringUtils.isNotBlank(anyKey)) {
+ entity.setPayload(anyKey);
+ } else if (anyTO != null) {
+ entity.setPayload(anyTO);
+ } else if (anyPatch != null) {
+ entity.setPayload(anyPatch);
+ }
+ entity.setError(result.getMessage());
+ entity.setInstant(new Date());
+ entity.setRemoteName(delta.getObject().getName().getNameValue());
+ entity.setPullTask(pullTask);
+
+ return remediationDAO.save(entity);
+ }
+
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPullResultHandler.java
index d54e9d3..6194e28 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPullResultHandler.java
@@ -18,13 +18,6 @@
*/
package org.apache.syncope.core.provisioning.java.pushpull;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.tuple.Pair;
@@ -35,6 +28,7 @@ import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.AttrTO;
import org.apache.syncope.common.lib.to.LinkedAccountTO;
import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.ProvisioningReport;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AuditElements;
@@ -47,7 +41,6 @@ import org.apache.syncope.common.lib.types.UnmatchingRule;
import org.apache.syncope.core.persistence.api.dao.PullMatch;
import org.apache.syncope.core.persistence.api.entity.Any;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.Remediation;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.user.LinkedAccount;
import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -56,14 +49,19 @@ import org.apache.syncope.core.provisioning.api.ProvisioningManager;
import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
import org.apache.syncope.core.provisioning.api.WorkflowResult;
import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
-import org.apache.syncope.common.lib.to.ProvisioningReport;
import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
-import org.identityconnectors.framework.common.objects.SyncDelta;
import org.apache.syncope.core.provisioning.api.pushpull.UserPullResultHandler;
import org.identityconnectors.framework.common.objects.AttributeUtil;
+import org.identityconnectors.framework.common.objects.SyncDelta;
import org.identityconnectors.framework.common.objects.SyncDeltaType;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
public class DefaultUserPullResultHandler extends AbstractPullResultHandler implements UserPullResultHandler {
@@ -127,6 +125,11 @@ public class DefaultUserPullResultHandler extends AbstractPullResultHandler impl
Collections.singleton(profile.getTask().getResource().getKey()),
true);
+ if (ProvisioningReport.Status.FAILURE == result.getStatus() && profile.getTask().isRemediation()) {
+ createRemediation(anyTypeDAO.find(result.getAnyType()), anyPatch, profile.getTask(), result,
+ delta);
+ }
+
return updated.getLeft();
}
@@ -395,16 +398,7 @@ public class DefaultUserPullResultHandler extends AbstractPullResultHandler impl
resultStatus = Result.FAILURE;
if (profile.getTask().isRemediation()) {
- Remediation entity = entityFactory.newEntity(Remediation.class);
- entity.setAnyType(provision.getAnyType());
- entity.setOperation(ResourceOperation.UPDATE);
- entity.setPayload(patch);
- entity.setError(report.getMessage());
- entity.setInstant(new Date());
- entity.setRemoteName(delta.getObject().getName().getNameValue());
- entity.setPullTask(profile.getTask());
-
- remediationDAO.save(entity);
+ createRemediation(provision.getAnyType(), patch, profile.getTask(), report, delta);
}
}
@@ -520,16 +514,7 @@ public class DefaultUserPullResultHandler extends AbstractPullResultHandler impl
resultStatus = Result.FAILURE;
if (profile.getTask().isRemediation()) {
- Remediation entity = entityFactory.newEntity(Remediation.class);
- entity.setAnyType(provision.getAnyType());
- entity.setOperation(ResourceOperation.UPDATE);
- entity.setPayload(patch);
- entity.setError(report.getMessage());
- entity.setInstant(new Date());
- entity.setRemoteName(delta.getObject().getName().getNameValue());
- entity.setPullTask(profile.getTask());
-
- remediationDAO.save(entity);
+ createRemediation(provision.getAnyType(), patch, profile.getTask(), report, delta);
}
}
@@ -601,16 +586,7 @@ public class DefaultUserPullResultHandler extends AbstractPullResultHandler impl
output = e;
if (profile.getTask().isRemediation()) {
- Remediation entity = entityFactory.newEntity(Remediation.class);
- entity.setAnyType(provision.getAnyType());
- entity.setOperation(ResourceOperation.UPDATE);
- entity.setPayload(patch);
- entity.setError(report.getMessage());
- entity.setInstant(new Date());
- entity.setRemoteName(delta.getObject().getName().getNameValue());
- entity.setPullTask(profile.getTask());
-
- remediationDAO.save(entity);
+ createRemediation(provision.getAnyType(), patch, profile.getTask(), report, delta);
}
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index f54f968..a79d315 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -34,10 +34,13 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
import java.util.UUID;
import javax.naming.Context;
import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
@@ -606,6 +609,34 @@ public abstract class AbstractITCase {
}
}
+ protected void createLdapRemoteObject(
+ final String bindDn,
+ final String bindPwd,
+ final Pair<String, Set<Attribute>> entryAttrs) throws NamingException {
+
+ InitialDirContext ctx = null;
+ try {
+ ctx = getLdapResourceDirContext(bindDn, bindPwd);
+
+ BasicAttributes entry = new BasicAttributes();
+ entryAttrs.getRight().forEach(item -> entry.put(item));
+
+ ctx.createSubcontext(entryAttrs.getLeft(), entry);
+
+ } catch (NamingException e) {
+ LOG.error("While creating {} with {}", entryAttrs.getLeft(), entryAttrs.getRight(), e);
+ throw e;
+ } finally {
+ if (ctx != null) {
+ try {
+ ctx.close();
+ } catch (NamingException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
protected void updateLdapRemoteObject(
final String bindDn,
final String bindPwd,
@@ -702,4 +733,5 @@ public abstract class AbstractITCase {
} while (results.isEmpty() && i < maxWaitSeconds);
return results;
}
+
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
index f66f8ba..bb2e545 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
@@ -42,10 +42,15 @@ import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.BasicAttribute;
import javax.sql.DataSource;
import javax.ws.rs.core.Response;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
@@ -867,8 +872,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
"SyncopeClientCompositeException: {[RequiredValuesMissing [userId]]}"));
} finally {
resourceService.delete(ldap.getKey());
- remediationService.list(new RemediationQuery.Builder().page(1).size(10).build()).getResult().forEach(
- r -> remediationService.delete(r.getKey()));
+ cleanUpRemediations();
}
}
@@ -1394,4 +1398,111 @@ public class PullTaskITCase extends AbstractTaskITCase {
}
}
}
+
+ @Test
+ public void issueSYNCOPE1656() throws NamingException {
+ // preliminary create a new LDAP object
+ createLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, prepareLdapAttributes(
+ "pullFromLDAP_issue1656",
+ "pullFromLDAP_issue1656@syncope.apache.org",
+ "Active",
+ "pullFromLDAP_issue1656",
+ "Surname",
+ "5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8",
+ "odd",
+ "password"));
+ try {
+ // 1. Pull from resource-ldap
+ PullTaskTO pullTask = new PullTaskTO();
+ pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
+ pullTask.setName("SYNCOPE1656");
+ pullTask.setActive(true);
+ pullTask.setPerformCreate(true);
+ pullTask.setPerformUpdate(true);
+ pullTask.setRemediation(true);
+ pullTask.setPullMode(PullMode.FULL_RECONCILIATION);
+ pullTask.setResource(RESOURCE_NAME_LDAP);
+
+ Response taskResponse = taskService.create(TaskType.PULL, pullTask);
+ pullTask = getObject(taskResponse.getLocation(), TaskService.class, PullTaskTO.class);
+ assertNotNull(pullTask);
+
+ ExecTO execution = execProvisioningTask(
+ taskService, TaskType.PULL, pullTask.getKey(), MAX_WAIT_SECONDS, false);
+ assertEquals(ExecStatus.SUCCESS, ExecStatus.valueOf(execution.getStatus()));
+
+ UserTO pullFromLDAP_issue1656 = userService.read("pullFromLDAP_issue1656");
+ assertEquals("pullFromLDAP_issue1656@syncope.apache.org",
+ pullFromLDAP_issue1656.getPlainAttr("email").get().getValues().get(0));
+ // 2. Edit mail attribute directly on the resource in order to have a not valid email
+ ConnObjectTO connObject =
+ resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(),
+ pullFromLDAP_issue1656.getKey());
+ assertNotNull(connObject);
+ assertEquals("pullFromLDAP_issue1656@syncope.apache.org",
+ connObject.getAttr("mail").get().getValues().get(0));
+ AttrTO userDn = connObject.getAttr(Name.NAME).get();
+ assertNotNull(userDn);
+ assertEquals(1, userDn.getValues().size());
+ updateLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD,
+ userDn.getValues().get(0), Collections.singletonMap("mail", "pullFromLDAP_issue1656@"));
+ // 3. Pull again from resource-ldap
+ execution = execProvisioningTask(taskService, TaskType.PULL, pullTask.getKey(), MAX_WAIT_SECONDS, false);
+ assertEquals(ExecStatus.SUCCESS, ExecStatus.valueOf(execution.getStatus()));
+ assertTrue(execution.getMessage().contains("UPDATE FAILURE"));
+ pullFromLDAP_issue1656 = userService.read("pullFromLDAP_issue1656");
+ assertEquals("pullFromLDAP_issue1656@syncope.apache.org",
+ pullFromLDAP_issue1656.getPlainAttr("email").get().getValues().get(0));
+ final String pullFromLDAP_issue1656_key = pullFromLDAP_issue1656.getKey();
+ // a remediation for pullFromLDAP_issue1656 email should have been created
+ PagedResult<RemediationTO> remediations =
+ remediationService.list(new RemediationQuery.Builder().page(1).size(10).build());
+ assertTrue(remediations.getResult().stream().anyMatch(
+ r -> pullFromLDAP_issue1656_key.equals(r.getAnyPatchPayload().getKey())));
+ assertTrue(remediations.getResult().stream().anyMatch(r -> StringUtils.contains(r.getError(),
+ "\"pullFromLDAP_issue1656@\" is not a valid email address")));
+ } finally {
+ // remove test entity
+ removeLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD,
+ "uid=pullFromLDAP_issue1656,ou=People,o=isp");
+ cleanUpRemediations();
+ }
+ }
+
+ private void cleanUpRemediations() {
+ remediationService.list(new RemediationQuery.Builder().page(1).size(100).build()).getResult().forEach(
+ r -> remediationService.delete(r.getKey()));
+ }
+
+ private Pair<String, Set<Attribute>> prepareLdapAttributes(
+ final String uid,
+ final String email,
+ final String description,
+ final String givenName,
+ final String sn,
+ final String registeredAddress,
+ final String title,
+ final String password) {
+ String entryDn = "uid=" + uid + ",ou=People,o=isp";
+ Set<Attribute> attributes = new HashSet<>();
+
+ attributes.add(new BasicAttribute("description", description));
+ attributes.add(new BasicAttribute("givenName", givenName));
+ attributes.add(new BasicAttribute("mail", email));
+ attributes.add(new BasicAttribute("sn", sn));
+ attributes.add(new BasicAttribute("cn", uid));
+ attributes.add(new BasicAttribute("uid", uid));
+ attributes.add(new BasicAttribute("registeredaddress", registeredAddress));
+ attributes.add(new BasicAttribute("title", title));
+ attributes.add(new BasicAttribute("userpassword", password));
+
+ Attribute oc = new BasicAttribute("objectClass");
+ oc.add("top");
+ oc.add("person");
+ oc.add("inetOrgPerson");
+ oc.add("organizationalPerson");
+ attributes.add(oc);
+
+ return Pair.of(entryDn, attributes);
+ }
}