You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2018/03/28 14:53:26 UTC
[1/2] syncope git commit: [SYNCOPE-1287] Core implementation
Repository: syncope
Updated Branches:
refs/heads/master 59a3422e4 -> 51b314fe5
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
index d9cfafa..892850e 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
@@ -48,6 +48,7 @@ import org.apache.syncope.core.provisioning.api.data.SchemaDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class SchemaLogic extends AbstractTransactionalLogic<SchemaTO> {
@@ -145,11 +146,13 @@ public class SchemaLogic extends AbstractTransactionalLogic<SchemaTO> {
}
@PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
public <T extends SchemaTO> List<T> list(final SchemaType schemaType, final List<String> anyTypeClasses) {
return doSearch(schemaType, anyTypeClasses, null);
}
@PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
public <T extends SchemaTO> List<T> search(
final SchemaType schemaType, final List<String> anyTypeClasses, final String keyword) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/SecurityQuestionLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SecurityQuestionLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SecurityQuestionLogic.java
index f77f2fd..46285f2 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SecurityQuestionLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SecurityQuestionLogic.java
@@ -50,8 +50,7 @@ public class SecurityQuestionLogic extends AbstractTransactionalLogic<SecurityQu
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = true)
public List<SecurityQuestionTO> list() {
- return securityQuestionDAO.findAll().stream().
- map(securityQuestion -> binder.getSecurityQuestionTO(securityQuestion)).collect(Collectors.toList());
+ return securityQuestionDAO.findAll().stream().map(binder::getSecurityQuestionTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.SECURITY_QUESTION_READ + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index 0fb587a..8aa7151 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -23,6 +23,7 @@ import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Method;
import java.net.InetAddress;
+import java.net.URI;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collections;
@@ -68,6 +69,7 @@ import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.Entity;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
@@ -210,8 +212,8 @@ public class SyncopeLogic extends AbstractLogic<AbstractBaseBean> {
PLATFORM_INFO.setBuildNumber(buildNumber);
if (bundleManager.getLocations() != null) {
- bundleManager.getLocations().
- forEach(location -> PLATFORM_INFO.getConnIdLocations().add(location.toASCIIString()));
+ PLATFORM_INFO.getConnIdLocations().addAll(bundleManager.getLocations().stream().
+ map(URI::toASCIIString).collect(Collectors.toList()));
}
PLATFORM_INFO.setPropagationTaskExecutor(AopUtils.getTargetClass(propagationTaskExecutor).getName());
@@ -246,19 +248,19 @@ public class SyncopeLogic extends AbstractLogic<AbstractBaseBean> {
AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> {
PLATFORM_INFO.getAnyTypes().clear();
PLATFORM_INFO.getAnyTypes().addAll(anyTypeDAO.findAll().stream().
- map(type -> type.getKey()).collect(Collectors.toList()));
+ map(Entity::getKey).collect(Collectors.toList()));
PLATFORM_INFO.getUserClasses().clear();
PLATFORM_INFO.getUserClasses().addAll(anyTypeDAO.findUser().getClasses().stream().
- map(cls -> cls.getKey()).collect(Collectors.toList()));
+ map(Entity::getKey).collect(Collectors.toList()));
PLATFORM_INFO.getAnyTypeClasses().clear();
PLATFORM_INFO.getAnyTypeClasses().addAll(anyTypeClassDAO.findAll().stream().
- map(cls -> cls.getKey()).collect(Collectors.toList()));
+ map(Entity::getKey).collect(Collectors.toList()));
PLATFORM_INFO.getResources().clear();
PLATFORM_INFO.getResources().addAll(resourceDAO.findAll().stream().
- map(resource -> resource.getKey()).collect(Collectors.toList()));
+ map(Entity::getKey).collect(Collectors.toList()));
return null;
});
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
index baad7e8..bcbe645 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
@@ -63,6 +63,7 @@ import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
@@ -156,6 +157,7 @@ public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
}
@PreAuthorize("hasRole('" + StandardEntitlement.TASK_LIST + "')")
+ @Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public <T extends TaskTO> Pair<Integer, List<T>> list(
final TaskType type,
@@ -191,6 +193,7 @@ public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
}
@PreAuthorize("hasRole('" + StandardEntitlement.TASK_READ + "')")
+ @Transactional(readOnly = true)
public <T extends TaskTO> T read(final TaskType type, final String key, final boolean details) {
Task task = taskDAO.find(key);
if (task == null) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
index 62b43ae..8fc4745 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserWorkflowLogic.java
@@ -58,7 +58,6 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
private UserDAO userDAO;
@PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_CLAIM + "')")
- @Transactional(rollbackFor = { Throwable.class })
public WorkflowFormTO claimForm(final String taskId) {
return uwfAdapter.claimForm(taskId);
}
@@ -82,20 +81,19 @@ public class UserWorkflowLogic extends AbstractTransactionalLogic<WorkflowFormTO
@PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_READ + "') and hasRole('"
+ StandardEntitlement.USER_READ + "')")
- @Transactional(rollbackFor = { Throwable.class })
+ @Transactional(readOnly = true)
public WorkflowFormTO getFormForUser(final String key) {
User user = userDAO.authFind(key);
return uwfAdapter.getForm(user.getWorkflowId());
}
@PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_LIST + "')")
- @Transactional(rollbackFor = { Throwable.class })
+ @Transactional(readOnly = true)
public List<WorkflowFormTO> getForms() {
return uwfAdapter.getForms();
}
@PreAuthorize("hasRole('" + StandardEntitlement.WORKFLOW_FORM_SUBMIT + "')")
- @Transactional(rollbackFor = { Throwable.class })
public UserTO submitForm(final WorkflowFormTO form) {
WorkflowResult<? extends AnyPatch> updated = uwfAdapter.submitForm(form);
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/InvalidEntityException.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/InvalidEntityException.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/InvalidEntityException.java
index f9db494..d6a3fe7 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/InvalidEntityException.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/attrvalue/validation/InvalidEntityException.java
@@ -89,6 +89,8 @@ public class InvalidEntityException extends ValidationException {
entityViolationType.setMessage(message.trim());
+ entityViolationType.setPropertyPath(violation.getPropertyPath().toString());
+
if (!this.violations.containsKey(violation.getLeafBean().getClass())) {
this.violations.put(violation.getLeafBean().getClass(), EnumSet.noneOf(EntityViolationType.class));
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RemediationDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RemediationDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RemediationDAO.java
new file mode 100644
index 0000000..f00cb8a
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RemediationDAO.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+
+public interface RemediationDAO extends DAO<Remediation> {
+
+ Remediation find(String key);
+
+ List<Remediation> findByPullTask(PullTask pullTask);
+
+ List<Remediation> findAll();
+
+ Remediation save(Remediation remediation);
+
+ void delete(Remediation remediation);
+
+ void delete(String key);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java
new file mode 100644
index 0000000..1278241
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Remediation.java
@@ -0,0 +1,65 @@
+/*
+ * 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.core.persistence.api.entity;
+
+import java.util.Date;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+
+public interface Remediation extends Entity {
+
+ AnyTypeKind getAnyTypeKind();
+
+ void setAnyTypeKind(AnyTypeKind anyTypeKind);
+
+ ResourceOperation getOperation();
+
+ void setOperation(ResourceOperation operation);
+
+ void setPayload(AnyTO anyTO);
+
+ void setPayload(AnyPatch anyPatch);
+
+ void setPayload(String key);
+
+ <T extends AnyTO> T getPayloadAsTO(Class<T> reference);
+
+ <P extends AnyPatch> P getPayloadAsPatch(Class<P> reference);
+
+ String getPayloadAsKey();
+
+ String getError();
+
+ void setError(String error);
+
+ Date getInstant();
+
+ void setInstant(Date instant);
+
+ PullTask getPullTask();
+
+ void setPullTask(PullTask pullTask);
+
+ String getRemoteName();
+
+ void setRemoteName(String remoteName);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
index d4234f2..2d8ffdd 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PullTask.java
@@ -44,4 +44,9 @@ public interface PullTask extends ProvisioningTask {
Optional<? extends AnyTemplatePullTask> getTemplate(AnyType anyType);
List<? extends AnyTemplatePullTask> getTemplates();
+
+ void setRemediation(boolean remediation);
+
+ boolean isRemediation();
+
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARemediationDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARemediationDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARemediationDAO.java
new file mode 100644
index 0000000..b78c425
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARemediationDAO.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.core.persistence.api.dao.RemediationDAO;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+import org.apache.syncope.core.persistence.jpa.entity.JPARemediation;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPARemediationDAO extends AbstractDAO<Remediation> implements RemediationDAO {
+
+ @Override
+ public Remediation find(final String key) {
+ return entityManager().find(JPARemediation.class, key);
+ }
+
+ @Override
+ public List<Remediation> findByPullTask(final PullTask pullTask) {
+ TypedQuery<Remediation> query = entityManager().createQuery(
+ "SELECT e FROM " + JPARemediation.class.getSimpleName() + " e WHERE e.pullTask=:pullTask",
+ Remediation.class);
+ query.setParameter("pullTask", pullTask);
+ return query.getResultList();
+ }
+
+ @Override
+ public List<Remediation> findAll() {
+ TypedQuery<Remediation> query = entityManager().createQuery(
+ "SELECT e FROM " + JPARemediation.class.getSimpleName() + " e ", Remediation.class);
+ return query.getResultList();
+ }
+
+ @Override
+ public Remediation save(final Remediation remediation) {
+ return entityManager().merge(remediation);
+ }
+
+ @Override
+ public void delete(final Remediation remediation) {
+ entityManager().remove(remediation);
+ }
+
+ @Override
+ public void delete(final String key) {
+ Remediation remediation = find(key);
+ if (remediation == null) {
+ return;
+ }
+
+ delete(remediation);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
index 792a661..d47ba5d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
@@ -25,6 +25,7 @@ import javax.persistence.TypedQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.TaskType;
+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.search.OrderByClause;
import org.apache.syncope.core.persistence.api.entity.Entity;
@@ -41,6 +42,7 @@ import org.apache.syncope.core.persistence.jpa.entity.task.JPAPushTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPASchedTask;
import org.apache.syncope.core.persistence.jpa.entity.task.JPAPullTask;
import org.apache.syncope.core.persistence.jpa.entity.task.AbstractTask;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ReflectionUtils;
@@ -48,6 +50,9 @@ import org.springframework.util.ReflectionUtils;
@Repository
public class JPATaskDAO extends AbstractDAO<Task> implements TaskDAO {
+ @Autowired
+ private RemediationDAO remediationDAO;
+
@Override
public Class<? extends Task> getEntityReference(final TaskType type) {
Class<? extends Task> result = null;
@@ -303,6 +308,12 @@ public class JPATaskDAO extends AbstractDAO<Task> implements TaskDAO {
@Override
public void delete(final Task task) {
+ if (task instanceof PullTask) {
+ remediationDAO.findByPullTask((PullTask) task).forEach(remediation -> {
+ remediation.setPullTask(null);
+ });
+ }
+
entityManager().remove(task);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index aa2809a..8de177e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -130,6 +130,7 @@ import org.apache.syncope.core.persistence.api.entity.DynRealm;
import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
import org.apache.syncope.core.persistence.api.entity.Implementation;
import org.apache.syncope.core.persistence.api.entity.Privilege;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
import org.apache.syncope.core.persistence.api.entity.policy.CorrelationRule;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResourceHistoryConf;
import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
@@ -285,6 +286,8 @@ public class JPAEntityFactory implements EntityFactory {
result = (E) new JPAAccessToken();
} else if (reference.equals(Implementation.class)) {
result = (E) new JPAImplementation();
+ } else if (reference.equals(Remediation.class)) {
+ result = (E) new JPARemediation();
} else {
throw new IllegalArgumentException("Could not find a JPA implementation of " + reference.getName());
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java
new file mode 100644
index 0000000..6f31cc9
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARemediation.java
@@ -0,0 +1,171 @@
+/*
+ * 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.core.persistence.jpa.entity;
+
+import java.util.Date;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+import org.apache.syncope.core.persistence.jpa.entity.task.JPAPullTask;
+import org.apache.syncope.core.persistence.jpa.validation.entity.RemediationCheck;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+
+@Entity
+@Table(name = JPARemediation.TABLE)
+@RemediationCheck
+public class JPARemediation extends AbstractGeneratedKeyEntity implements Remediation {
+
+ private static final long serialVersionUID = -1612530286294448682L;
+
+ public static final String TABLE = "Remediation";
+
+ @NotNull
+ @Enumerated(EnumType.STRING)
+ private AnyTypeKind anyTypeKind;
+
+ @NotNull
+ @Enumerated(EnumType.STRING)
+ private ResourceOperation operation;
+
+ @NotNull
+ @Lob
+ private String payload;
+
+ @NotNull
+ @Lob
+ private String error;
+
+ @NotNull
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date instant;
+
+ @ManyToOne
+ private JPAPullTask pullTask;
+
+ @NotNull
+ private String remoteName;
+
+ @Override
+ public AnyTypeKind getAnyTypeKind() {
+ return anyTypeKind;
+ }
+
+ @Override
+ public void setAnyTypeKind(final AnyTypeKind anyTypeKind) {
+ this.anyTypeKind = anyTypeKind;
+ }
+
+ @Override
+ public ResourceOperation getOperation() {
+ return operation;
+ }
+
+ @Override
+ public void setOperation(final ResourceOperation operation) {
+ this.operation = operation;
+ }
+
+ @Override
+ public <T extends AnyTO> T getPayloadAsTO(final Class<T> reference) {
+ return POJOHelper.deserialize(this.payload, reference);
+ }
+
+ @Override
+ public <P extends AnyPatch> P getPayloadAsPatch(final Class<P> reference) {
+ return POJOHelper.deserialize(this.payload, reference);
+ }
+
+ @Override
+ public String getPayloadAsKey() {
+ return this.payload;
+ }
+
+ @Override
+ public void setPayload(final AnyTO anyTO) {
+ this.payload = POJOHelper.serialize(anyTO);
+ }
+
+ @Override
+ public void setPayload(final AnyPatch anyPatch) {
+ this.payload = POJOHelper.serialize(anyPatch);
+ }
+
+ @Override
+ public void setPayload(final String key) {
+ this.payload = key;
+ }
+
+ @Override
+ public String getError() {
+ return error;
+ }
+
+ @Override
+ public void setError(final String error) {
+ this.error = error;
+ }
+
+ @Override
+ public Date getInstant() {
+ return instant == null
+ ? null
+ : new Date(instant.getTime());
+ }
+
+ @Override
+ public void setInstant(final Date instant) {
+ this.instant = instant == null
+ ? null
+ : new Date(instant.getTime());
+ }
+
+ @Override
+ public PullTask getPullTask() {
+ return pullTask;
+ }
+
+ @Override
+ public void setPullTask(final PullTask pullTask) {
+ checkType(pullTask, JPAPullTask.class);
+ this.pullTask = (JPAPullTask) pullTask;
+ }
+
+ @Override
+ public String getRemoteName() {
+ return remoteName;
+ }
+
+ @Override
+ public void setRemoteName(final String remoteName) {
+ this.remoteName = remoteName;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
index d42c3ea..5974800 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.persistence.jpa.entity.task;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
+import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@@ -33,6 +34,8 @@ import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.common.lib.types.PullMode;
@@ -71,6 +74,11 @@ public class JPAPullTask extends AbstractProvisioningTask implements PullTask {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "pullTask")
private List<JPAAnyTemplatePullTask> templates = new ArrayList<>();
+ @Basic
+ @Min(0)
+ @Max(1)
+ private Integer remediation;
+
@Override
public PullMode getPullMode() {
return pullMode;
@@ -134,4 +142,14 @@ public class JPAPullTask extends AbstractProvisioningTask implements PullTask {
return templates;
}
+ @Override
+ public void setRemediation(final boolean remediation) {
+ this.remediation = getBooleanAsInteger(remediation);
+ }
+
+ @Override
+ public boolean isRemediation() {
+ return isBooleanAsInteger(remediation);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationCheck.java
new file mode 100644
index 0000000..7a0a9c2
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.persistence.jpa.validation.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = RemediationValidator.class)
+@Documented
+public @interface RemediationCheck {
+
+ String message() default "{org.apache.syncope.core.persistence.validation.remediation}";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationValidator.java
new file mode 100644
index 0000000..25f9fb2
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RemediationValidator.java
@@ -0,0 +1,80 @@
+/*
+ * 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.core.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
+
+public class RemediationValidator extends AbstractValidator<RemediationCheck, Remediation> {
+
+ @Override
+ public boolean isValid(final Remediation remediation, final ConstraintValidatorContext context) {
+ boolean isValid = true;
+
+ switch (remediation.getOperation()) {
+ case CREATE:
+ if (remediation.getPayloadAsTO(remediation.getAnyTypeKind().getTOClass()) == null) {
+ context.disableDefaultConstraintViolation();
+ context.buildConstraintViolationWithTemplate(
+ getTemplate(EntityViolationType.InvalidRemediation,
+ "Expected " + remediation.getAnyTypeKind().getTOClass().getName())).
+ addPropertyNode("payload").addConstraintViolation();
+
+ isValid = false;
+ }
+ break;
+
+ case UPDATE:
+ if (remediation.getPayloadAsPatch(remediation.getAnyTypeKind().getPatchClass()) == null) {
+ context.disableDefaultConstraintViolation();
+ context.buildConstraintViolationWithTemplate(
+ getTemplate(EntityViolationType.InvalidRemediation,
+ "Expected " + remediation.getAnyTypeKind().getPatchClass().getName())).
+ addPropertyNode("payload").addConstraintViolation();
+
+ isValid = false;
+ }
+ break;
+
+ case DELETE:
+ if (!SyncopeConstants.UUID_PATTERN.matcher(remediation.getPayloadAsKey()).matches()) {
+ context.disableDefaultConstraintViolation();
+ context.buildConstraintViolationWithTemplate(
+ getTemplate(EntityViolationType.InvalidRemediation, "Expected UUID")).
+ addPropertyNode("payload").addConstraintViolation();
+
+ isValid = false;
+ }
+ break;
+
+ case NONE:
+ default:
+ context.disableDefaultConstraintViolation();
+ context.buildConstraintViolationWithTemplate(
+ getTemplate(EntityViolationType.InvalidRemediation, "NONE is not allowed")).
+ addPropertyNode("operation").addConstraintViolation();
+
+ isValid = false;
+ }
+
+ return isValid;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java
new file mode 100644
index 0000000..02315fa
--- /dev/null
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/RemediationTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.core.persistence.jpa.inner;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
+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.entity.Remediation;
+import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional("Master")
+public class RemediationTest extends AbstractTest {
+
+ @Autowired
+ private RemediationDAO remediationDAO;
+
+ @Autowired
+ private TaskDAO taskDAO;
+
+ @Test
+ public void findAll() {
+ List<Remediation> remediations = remediationDAO.findAll();
+ assertTrue(remediations.isEmpty());
+ }
+
+ @Test
+ public void create() {
+ Remediation remediation = entityFactory.newEntity(Remediation.class);
+ remediation.setAnyTypeKind(AnyTypeKind.ANY_OBJECT);
+ remediation.setOperation(ResourceOperation.CREATE);
+ remediation.setError("Error");
+ remediation.setInstant(new Date());
+ remediation.setRemoteName("remote");
+ remediation.setPullTask(taskDAO.find("38abbf9e-a1a3-40a1-a15f-7d0ac02f47f1"));
+
+ // missing payload
+ try {
+ remediationDAO.save(remediation);
+ fail("This should not happen");
+ } catch (InvalidEntityException e) {
+ Set<EntityViolationType> violations = e.getViolations().values().iterator().next();
+ assertEquals(2, violations.size());
+ assertTrue(violations.stream().allMatch(violation -> violation.getPropertyPath().equals("payload")));
+ }
+
+ remediation.setPayload(UUID.randomUUID().toString());
+
+ // wrong payload for operation
+ try {
+ remediationDAO.save(remediation);
+ fail("This should not happen");
+ } catch (InvalidEntityException e) {
+ Set<EntityViolationType> violations = e.getViolations().values().iterator().next();
+ assertEquals(1, violations.size());
+ assertTrue(violations.stream().anyMatch(violation -> violation.getPropertyPath().equals("payload")));
+ }
+
+ remediation.setOperation(ResourceOperation.DELETE);
+
+ remediation = remediationDAO.save(remediation);
+ assertNotNull(remediation.getKey());
+ assertNotNull(remediation.getPullTask());
+
+ taskDAO.delete(remediation.getPullTask());
+
+ remediationDAO.flush();
+
+ remediation = remediationDAO.find(remediation.getKey());
+ assertNull(remediation.getPullTask());
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ConnInstanceDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ConnInstanceDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ConnInstanceDataBinder.java
index ae7074f..9fa892e 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ConnInstanceDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ConnInstanceDataBinder.java
@@ -18,9 +18,11 @@
*/
package org.apache.syncope.core.provisioning.api.data;
+import org.apache.syncope.common.lib.to.ConnInstanceHistoryConfTO;
import org.apache.syncope.common.lib.to.ConnInstanceTO;
import org.apache.syncope.common.lib.types.ConnConfPropSchema;
import org.apache.syncope.core.persistence.api.entity.ConnInstance;
+import org.apache.syncope.core.persistence.api.entity.ConnInstanceHistoryConf;
import org.identityconnectors.framework.api.ConfigurationProperty;
public interface ConnInstanceDataBinder {
@@ -31,6 +33,8 @@ public interface ConnInstanceDataBinder {
ConnInstanceTO getConnInstanceTO(ConnInstance connInstance);
+ ConnInstanceHistoryConfTO getConnInstanceHistoryConfTO(ConnInstanceHistoryConf history);
+
ConnInstance update(ConnInstanceTO connInstanceTO);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RemediationDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RemediationDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RemediationDataBinder.java
new file mode 100644
index 0000000..42d8332
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/RemediationDataBinder.java
@@ -0,0 +1,28 @@
+/*
+ * 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.core.provisioning.api.data;
+
+import org.apache.syncope.common.lib.to.RemediationTO;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
+
+public interface RemediationDataBinder {
+
+ RemediationTO getRemediationTO(Remediation remediation);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ResourceDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ResourceDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ResourceDataBinder.java
index 9f1ea5d..84b2254 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ResourceDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ResourceDataBinder.java
@@ -18,8 +18,10 @@
*/
package org.apache.syncope.core.provisioning.api.data;
+import org.apache.syncope.common.lib.to.ResourceHistoryConfTO;
import org.apache.syncope.common.lib.to.ResourceTO;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResourceHistoryConf;
public interface ResourceDataBinder {
@@ -29,4 +31,5 @@ public interface ResourceDataBinder {
ExternalResource update(ExternalResource resource, ResourceTO resourceTO);
+ ResourceHistoryConfTO getResourceHistoryConfTO(ExternalResourceHistoryConf history);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
index d4b9206..333311c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ConnInstanceHistoryConfTO;
import org.apache.syncope.common.lib.to.ConnInstanceTO;
import org.apache.syncope.common.lib.to.ConnPoolConfTO;
import org.apache.syncope.common.lib.types.ClientExceptionType;
@@ -277,4 +278,15 @@ public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder {
return connInstanceTO;
}
+
+ @Override
+ public ConnInstanceHistoryConfTO getConnInstanceHistoryConfTO(final ConnInstanceHistoryConf history) {
+ ConnInstanceHistoryConfTO historyTO = new ConnInstanceHistoryConfTO();
+ historyTO.setKey(history.getKey());
+ historyTO.setCreator(history.getCreator());
+ historyTO.setCreation(history.getCreation());
+ historyTO.setConnInstanceTO(history.getConf());
+
+ return historyTO;
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RemediationDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RemediationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RemediationDataBinderImpl.java
new file mode 100644
index 0000000..d95f866
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RemediationDataBinderImpl.java
@@ -0,0 +1,65 @@
+/*
+ * 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.core.provisioning.java.data;
+
+import org.apache.syncope.common.lib.to.RemediationTO;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
+import org.apache.syncope.core.provisioning.api.data.RemediationDataBinder;
+import org.apache.syncope.core.spring.BeanUtils;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RemediationDataBinderImpl implements RemediationDataBinder {
+
+ private static final String[] IGNORE_PROPERTIES = {
+ "payload", "anyTOPayload", "anyPatchPayload", "keyPayload", "pullTask" };
+
+ @Override
+ public RemediationTO getRemediationTO(final Remediation remediation) {
+ RemediationTO remediationTO = new RemediationTO();
+
+ BeanUtils.copyProperties(remediation, remediationTO);
+
+ switch (remediation.getOperation()) {
+ case CREATE:
+ remediationTO.setAnyTOPayload(
+ remediation.getPayloadAsTO(remediation.getAnyTypeKind().getTOClass()));
+ break;
+
+ case UPDATE:
+ remediationTO.setAnyPatchPayload(
+ remediation.getPayloadAsPatch(remediation.getAnyTypeKind().getPatchClass()));
+ break;
+
+ case DELETE:
+ remediationTO.setKeyPayload(remediation.getPayloadAsKey());
+ break;
+
+ default:
+ }
+
+ if (remediation.getPullTask() != null) {
+ remediationTO.setPullTask(remediation.getPullTask().getKey());
+ remediationTO.setResource(remediation.getPullTask().getResource().getKey());
+ }
+
+ return remediationTO;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index 1db8e56..681743e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -34,6 +34,7 @@ import org.apache.syncope.common.lib.to.ItemTO;
import org.apache.syncope.common.lib.to.MappingTO;
import org.apache.syncope.common.lib.to.OrgUnitTO;
import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.ResourceHistoryConfTO;
import org.apache.syncope.common.lib.to.ResourceTO;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.MappingPurpose;
@@ -646,4 +647,15 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
return resourceTO;
}
+
+ @Override
+ public ResourceHistoryConfTO getResourceHistoryConfTO(final ExternalResourceHistoryConf history) {
+ ResourceHistoryConfTO historyTO = new ResourceHistoryConfTO();
+ historyTO.setKey(history.getKey());
+ historyTO.setCreator(history.getCreator());
+ historyTO.setCreation(history.getCreation());
+ historyTO.setResourceTO(history.getConf());
+
+ return historyTO;
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
index 1b30e59..6fcc05e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -219,6 +219,8 @@ public class TaskDataBinderImpl implements TaskDataBinder {
// remove all templates not contained in the TO
pullTask.getTemplates().
removeIf(anyTemplate -> !pullTaskTO.getTemplates().containsKey(anyTemplate.getAnyType().getKey()));
+
+ pullTask.setRemediation(pullTaskTO.isRemediation());
}
// 3. fill the remaining fields
@@ -407,6 +409,8 @@ public class TaskDataBinderImpl implements TaskDataBinder {
pullTask.getTemplates().forEach(template -> {
pullTaskTO.getTemplates().put(template.getAnyType().getKey(), template.get());
});
+
+ pullTaskTO.setRemediation(pullTask.isRemediation());
break;
case PUSH:
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
----------------------------------------------------------------------
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 2832cb5..a748562 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
@@ -20,6 +20,7 @@ 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 org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.syncope.common.lib.AnyOperations;
@@ -36,10 +37,13 @@ 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.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.RemediationDAO;
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.AnyUtils;
+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.VirSchema;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
@@ -78,11 +82,17 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
protected ConnObjectUtils connObjectUtils;
@Autowired
+ protected RemediationDAO remediationDAO;
+
+ @Autowired
protected VirSchemaDAO virSchemaDAO;
@Autowired
protected VirAttrCache virAttrCache;
+ @Autowired
+ protected EntityFactory entityFactory;
+
protected SyncopePullExecutor executor;
protected Result latestResult;
@@ -299,6 +309,19 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
LOG.error("Could not create {} {} ", anyTO.getType(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
+
+ if (profile.getTask().isRemediation()) {
+ Remediation entity = entityFactory.newEntity(Remediation.class);
+ entity.setAnyTypeKind(getAnyUtils().getAnyTypeKind());
+ entity.setOperation(ResourceOperation.CREATE);
+ entity.setPayload(anyTO);
+ entity.setError(result.getMessage());
+ entity.setInstant(new Date());
+ entity.setRemoteName(delta.getObject().getName().getNameValue());
+ entity.setPullTask(profile.getTask());
+
+ remediationDAO.save(entity);
+ }
}
finalize(operation, resultStatus, null, output, delta);
@@ -343,8 +366,9 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
resultStatus = Result.FAILURE;
output = null;
} else {
+ AnyPatch anyPatch = null;
try {
- AnyPatch anyPatch = connObjectUtils.getAnyPatch(
+ anyPatch = connObjectUtils.getAnyPatch(
before.getKey(),
delta.getObject(),
before,
@@ -384,6 +408,19 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
output = e;
resultStatus = Result.FAILURE;
+
+ if (profile.getTask().isRemediation()) {
+ Remediation entity = entityFactory.newEntity(Remediation.class);
+ entity.setAnyTypeKind(provision.getAnyType().getKind());
+ 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);
+ }
}
}
finalize(MatchingRule.toEventName(MatchingRule.UPDATE),
@@ -659,6 +696,19 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
LOG.error("Could not delete {} {}", provision.getAnyType().getKey(), key, e);
output = e;
+
+ if (profile.getTask().isRemediation()) {
+ Remediation entity = entityFactory.newEntity(Remediation.class);
+ entity.setAnyTypeKind(provision.getAnyType().getKind());
+ entity.setOperation(ResourceOperation.DELETE);
+ entity.setPayload(key);
+ entity.setError(result.getMessage());
+ entity.setInstant(new Date());
+ entity.setRemoteName(delta.getObject().getName().getNameValue());
+ entity.setPullTask(profile.getTask());
+
+ remediationDAO.save(entity);
+ }
}
finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, delta);
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java
new file mode 100644
index 0000000..201bb48
--- /dev/null
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/RemediationServiceImpl.java
@@ -0,0 +1,116 @@
+/*
+ * 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.core.rest.cxf.service;
+
+import java.util.Date;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.RemediationTO;
+import org.apache.syncope.common.rest.api.service.RemediationService;
+import org.apache.syncope.core.logic.RemediationLogic;
+import org.apache.syncope.core.persistence.api.dao.AnyDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class RemediationServiceImpl extends AbstractServiceImpl implements RemediationService {
+
+ @Autowired
+ private RemediationLogic logic;
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private GroupDAO groupDAO;
+
+ @Autowired
+ private AnyObjectDAO anyObjectDAO;
+
+ @Override
+ public List<RemediationTO> list() {
+ return logic.list();
+ }
+
+ @Override
+ public RemediationTO read(final String key) {
+ return logic.read(key);
+ }
+
+ @Override
+ public Response delete(final String key) {
+ logic.delete(key);
+ return Response.noContent().build();
+ }
+
+ @Override
+ public Response remedy(final String key, final AnyTO anyTO) {
+ ProvisioningResult<?> created = logic.remedy(key, anyTO, isNullPriorityAsync());
+ return createResponse(created);
+ }
+
+ private void check(final String key, final String anyKey) {
+ RemediationTO remediation = logic.read(key);
+
+ AnyDAO<?> anyDAO;
+ switch (remediation.getAnyTypeKind()) {
+ case USER:
+ default:
+ anyDAO = userDAO;
+ break;
+
+ case GROUP:
+ anyDAO = groupDAO;
+ break;
+
+ case ANY_OBJECT:
+ anyDAO = anyObjectDAO;
+ }
+
+ Date etagDate = anyDAO.findLastChange(anyKey);
+ if (etagDate == null) {
+ throw new NotFoundException(remediation.getAnyTypeKind().name() + " for " + key);
+ }
+ checkETag(String.valueOf(etagDate.getTime()));
+ }
+
+ @Override
+ public Response remedy(final String key, final AnyPatch anyPatch) {
+ check(key, anyPatch.getKey());
+
+ ProvisioningResult<?> updated = logic.remedy(key, anyPatch, isNullPriorityAsync());
+ return modificationResponse(updated);
+ }
+
+ @Override
+ public Response remedy(final String key, final String anyKey) {
+ check(key, anyKey);
+
+ ProvisioningResult<?> deleted = logic.remedy(key, anyKey, isNullPriorityAsync());
+ return modificationResponse(deleted);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
----------------------------------------------------------------------
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 7143545..3151971 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
@@ -86,6 +86,7 @@ import org.apache.syncope.common.rest.api.service.ImplementationService;
import org.apache.syncope.common.rest.api.service.MailTemplateService;
import org.apache.syncope.common.rest.api.service.RealmService;
import org.apache.syncope.common.rest.api.service.RelationshipTypeService;
+import org.apache.syncope.common.rest.api.service.RemediationService;
import org.apache.syncope.common.rest.api.service.ReportTemplateService;
import org.apache.syncope.common.rest.api.service.ResourceHistoryService;
import org.apache.syncope.common.rest.api.service.RoleService;
@@ -241,6 +242,8 @@ public abstract class AbstractITCase {
protected static ImplementationService implementationService;
+ protected static RemediationService remediationService;
+
protected static CamelRouteService camelRouteService;
protected static SAML2SPService saml2SpService;
@@ -311,6 +314,7 @@ public abstract class AbstractITCase {
schemaService = adminClient.getService(SchemaService.class);
securityQuestionService = adminClient.getService(SecurityQuestionService.class);
implementationService = adminClient.getService(ImplementationService.class);
+ remediationService = adminClient.getService(RemediationService.class);
camelRouteService = adminClient.getService(CamelRouteService.class);
saml2SpService = adminClient.getService(SAML2SPService.class);
saml2IdPService = adminClient.getService(SAML2IdPService.class);
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AbstractTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AbstractTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AbstractTaskITCase.java
index 11fbb0b..55c1a85 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AbstractTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AbstractTaskITCase.java
@@ -35,7 +35,6 @@ import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.patch.DeassociationPatch;
import org.apache.syncope.common.lib.to.TaskTO;
import org.apache.syncope.common.lib.to.ExecTO;
-import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.NotificationTaskTO;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.UserTO;
@@ -102,29 +101,20 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
* Clean Syncope and LDAP resource status.
*/
protected void ldapCleanup() {
- PagedResult<GroupTO> matchingGroups = groupService.search(new AnyQuery.Builder().realm(
- SyncopeConstants.ROOT_REALM).
+ groupService.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
fiql(SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo("testLDAPGroup").query()).
- build());
- if (matchingGroups.getSize() > 0) {
- for (GroupTO group : matchingGroups.getResult()) {
- groupService.deassociate(new DeassociationPatch.Builder().key(group.getKey()).
- action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_LDAP).build());
- groupService.delete(group.getKey());
- }
- }
- PagedResult<UserTO> matchingUsers = userService.search(
- new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
- fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("pullFromLDAP").
- query()).
- build());
- if (matchingUsers.getSize() > 0) {
- for (UserTO user : matchingUsers.getResult()) {
- userService.deassociate(new DeassociationPatch.Builder().key(user.getKey()).
- action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_LDAP).build());
- userService.delete(user.getKey());
- }
- }
+ build()).getResult().forEach(group -> {
+ groupService.deassociate(new DeassociationPatch.Builder().key(group.getKey()).
+ action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_LDAP).build());
+ groupService.delete(group.getKey());
+ });
+ userService.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
+ fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("pullFromLDAP").query()).
+ build()).getResult().forEach(user -> {
+ userService.deassociate(new DeassociationPatch.Builder().key(user.getKey()).
+ action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_LDAP).build());
+ userService.delete(user.getKey());
+ });
}
protected static ExecTO execTask(
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
----------------------------------------------------------------------
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 3e6d67a..6522fcb 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
@@ -35,6 +35,7 @@ import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
@@ -65,6 +66,7 @@ import org.apache.syncope.common.lib.to.PullTaskTO;
import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.ImplementationTO;
import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.RemediationTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -77,6 +79,7 @@ import org.apache.syncope.common.lib.types.PolicyType;
import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
import org.apache.syncope.common.lib.types.PullMode;
+import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.common.rest.api.beans.AnyQuery;
@@ -659,6 +662,87 @@ public class PullTaskITCase extends AbstractTaskITCase {
}
@Test
+ public void remediation() {
+ // First of all, clear any potential conflict with existing user / group
+ ldapCleanup();
+
+ // 1. create ldap cloned resource, where 'userId' (mandatory on Syncope) is removed from mapping
+ ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP);
+ ldap.setKey("ldapForRemediation");
+
+ ProvisionTO provision = ldap.getProvision(AnyTypeKind.USER.name()).get();
+ provision.getVirSchemas().clear();
+ provision.getMapping().getItems().removeIf(item -> "userId".equals(item.getIntAttrName()));
+
+ ldap = createResource(ldap);
+
+ // 2. create PullTask with remediation enabled, for the new resource
+ PullTaskTO pullTask = (PullTaskTO) taskService.list(new TaskQuery.Builder(TaskType.PULL).
+ resource(RESOURCE_NAME_LDAP).build()).getResult().get(0);
+ assertNotNull(pullTask);
+ pullTask.setResource(ldap.getKey());
+ pullTask.setRemediation(true);
+ pullTask.getActions().clear();
+
+ Response response = taskService.create(TaskType.PULL, pullTask);
+ if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
+ throw (RuntimeException) clientFactory.getExceptionMapper().fromResponse(response);
+ }
+ pullTask = getObject(response.getLocation(), TaskService.class, PullTaskTO.class);
+ assertNotNull(pullTask);
+
+ try {
+ // 3. execute the pull task and verify that:
+ ExecTO execution = execProvisioningTask(taskService, TaskType.PULL, pullTask.getKey(), 50, false);
+ assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
+
+ // 3a. user was not pulled
+ try {
+ userService.read("pullFromLDAP");
+ fail("This should never happen");
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.NotFound, e.getType());
+ }
+
+ // 3b. remediation was created
+ Optional<RemediationTO> remediation = remediationService.list().stream().
+ filter(r -> "uid=pullFromLDAP,ou=People,o=isp".equalsIgnoreCase(r.getRemoteName())).
+ findFirst();
+ assertTrue(remediation.isPresent());
+ assertEquals(AnyTypeKind.USER, remediation.get().getAnyTypeKind());
+ assertEquals(ResourceOperation.CREATE, remediation.get().getOperation());
+ assertNotNull(remediation.get().getAnyTOPayload());
+ assertNull(remediation.get().getAnyPatchPayload());
+ assertNull(remediation.get().getKeyPayload());
+ assertTrue(remediation.get().getError().contains("RequiredValuesMissing [userId]"));
+
+ // 4. remedy by copying the email value to userId
+ UserTO user = (UserTO) remediation.get().getAnyTOPayload();
+ user.getResources().clear();
+
+ String email = user.getPlainAttr("email").get().getValues().get(0);
+ user.getPlainAttrs().add(new AttrTO.Builder().schema("userId").value(email).build());
+
+ remediationService.remedy(remediation.get().getKey(), user);
+
+ // 5. user is now found
+ user = userService.read("pullFromLDAP");
+ assertNotNull(user);
+ assertEquals(email, user.getPlainAttr("userId").get().getValues().get(0));
+
+ // 6. remediation was removed
+ try {
+ remediationService.read(remediation.get().getKey());
+ fail("This should never happen");
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.NotFound, e.getType());
+ }
+ } finally {
+ resourceService.delete(ldap.getKey());
+ }
+ }
+
+ @Test
public void issueSYNCOPE68() {
//-----------------------------
// Create a new user ... it should be updated applying pull policy
[2/2] syncope git commit: [SYNCOPE-1287] Core implementation
Posted by il...@apache.org.
[SYNCOPE-1287] Core implementation
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/51b314fe
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/51b314fe
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/51b314fe
Branch: refs/heads/master
Commit: 51b314fe514695a79b3f0e39e8b1f06dd49dbebc
Parents: 59a3422
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Mar 28 16:53:12 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Mar 28 16:53:12 2018 +0200
----------------------------------------------------------------------
.../console/tasks/SchedTaskWizardBuilder.java | 6 +-
.../tasks/SchedTaskWizardBuilder$Profile.html | 1 +
.../SchedTaskWizardBuilder$Profile.properties | 1 +
...SchedTaskWizardBuilder$Profile_it.properties | 1 +
...SchedTaskWizardBuilder$Profile_ja.properties | 1 +
...edTaskWizardBuilder$Profile_pt_BR.properties | 1 +
...SchedTaskWizardBuilder$Profile_ru.properties | 1 +
.../syncope/common/lib/to/PullTaskTO.java | 11 +
.../syncope/common/lib/to/RemediationTO.java | 165 ++++++++++++++
.../syncope/common/lib/types/AnyTypeKind.java | 19 +-
.../common/lib/types/EntityViolationType.java | 12 ++
.../common/lib/types/StandardEntitlement.java | 8 +
.../rest/api/service/ImplementationService.java | 6 +-
.../rest/api/service/RemediationService.java | 213 +++++++++++++++++++
.../common/rest/api/service/UserService.java | 27 +--
.../syncope/core/logic/AccessTokenLogic.java | 2 +-
.../syncope/core/logic/AnyTypeClassLogic.java | 3 +-
.../apache/syncope/core/logic/AnyTypeLogic.java | 2 +-
.../syncope/core/logic/ApplicationLogic.java | 3 +-
.../core/logic/ConnectorHistoryLogic.java | 16 +-
.../syncope/core/logic/ConnectorLogic.java | 49 ++---
.../apache/syncope/core/logic/DomainLogic.java | 5 +-
.../syncope/core/logic/DynRealmLogic.java | 6 +-
.../syncope/core/logic/ImplementationLogic.java | 6 +-
.../apache/syncope/core/logic/LoggerLogic.java | 2 +
.../syncope/core/logic/MailTemplateLogic.java | 3 +
.../syncope/core/logic/NotificationLogic.java | 6 +-
.../apache/syncope/core/logic/PolicyLogic.java | 5 +-
.../apache/syncope/core/logic/RealmLogic.java | 2 +
.../core/logic/RelationshipTypeLogic.java | 6 +-
.../syncope/core/logic/RemediationLogic.java | 210 ++++++++++++++++++
.../apache/syncope/core/logic/ReportLogic.java | 5 +-
.../syncope/core/logic/ReportTemplateLogic.java | 3 +
.../core/logic/ResourceHistoryLogic.java | 16 +-
.../syncope/core/logic/ResourceLogic.java | 3 +-
.../apache/syncope/core/logic/RoleLogic.java | 2 +-
.../apache/syncope/core/logic/SchemaLogic.java | 3 +
.../core/logic/SecurityQuestionLogic.java | 3 +-
.../apache/syncope/core/logic/SyncopeLogic.java | 14 +-
.../apache/syncope/core/logic/TaskLogic.java | 3 +
.../syncope/core/logic/UserWorkflowLogic.java | 6 +-
.../validation/InvalidEntityException.java | 2 +
.../persistence/api/dao/RemediationDAO.java | 39 ++++
.../persistence/api/entity/Remediation.java | 65 ++++++
.../persistence/api/entity/task/PullTask.java | 5 +
.../persistence/jpa/dao/JPARemediationDAO.java | 73 +++++++
.../core/persistence/jpa/dao/JPATaskDAO.java | 11 +
.../jpa/entity/JPAEntityFactory.java | 3 +
.../persistence/jpa/entity/JPARemediation.java | 171 +++++++++++++++
.../jpa/entity/task/JPAPullTask.java | 18 ++
.../jpa/validation/entity/RemediationCheck.java | 41 ++++
.../validation/entity/RemediationValidator.java | 80 +++++++
.../persistence/jpa/inner/RemediationTest.java | 103 +++++++++
.../api/data/ConnInstanceDataBinder.java | 4 +
.../api/data/RemediationDataBinder.java | 28 +++
.../api/data/ResourceDataBinder.java | 3 +
.../java/data/ConnInstanceDataBinderImpl.java | 12 ++
.../java/data/RemediationDataBinderImpl.java | 65 ++++++
.../java/data/ResourceDataBinderImpl.java | 12 ++
.../java/data/TaskDataBinderImpl.java | 4 +
.../pushpull/AbstractPullResultHandler.java | 52 ++++-
.../cxf/service/RemediationServiceImpl.java | 116 ++++++++++
.../org/apache/syncope/fit/AbstractITCase.java | 4 +
.../syncope/fit/core/AbstractTaskITCase.java | 36 ++--
.../apache/syncope/fit/core/PullTaskITCase.java | 84 ++++++++
65 files changed, 1755 insertions(+), 133 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
index 8efd140..a23f39b 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
@@ -240,8 +240,12 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends AjaxWizardBui
destinationRealm.setNullValid(!(taskTO instanceof PullTaskTO));
pullTaskSpecifics.add(destinationRealm);
+ AjaxCheckBoxPanel remediation = new AjaxCheckBoxPanel(
+ "remediation", "remediation", new PropertyModel<>(taskTO, "remediation"), false);
+ pullTaskSpecifics.add(remediation);
+
// ------------------------------
- // Only for pull tasks
+ // Only for push tasks
// ------------------------------
WebMarkupContainer pushTaskSpecifics = new WebMarkupContainer("pushTaskSpecifics");
add(pushTaskSpecifics.setRenderBodyOnly(true));
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.html b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.html
index d45da13..4eabfb5 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.html
@@ -28,6 +28,7 @@ under the License.
<div class="form-group"><span wicket:id="destinationRealm">[destinationRealm]</span></div>
<div class="form-group"><span wicket:id="pullMode">[pullMode]</span></div>
<div class="form-group"><span wicket:id="reconFilterBuilder">[filter]</span></div>
+ <div class="form-group"><span wicket:id="remediation">[remediation]</span></div>
</span>
<span wicket:id="pushTaskSpecifics">
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.properties b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.properties
index 8200501..2acbca2 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile.properties
@@ -31,3 +31,4 @@ edit=Edit
execute=Execute
executeDryRun=Dry run
latestExecStatus=Last status
+remediation=Remediation
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_it.properties
index 5cddafd..bc2c4bd 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_it.properties
@@ -31,3 +31,4 @@ edit=Edit
execute=Execute
executeDryRun=Dry run
latestExecStatus=Last status
+remediation=Remediation
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ja.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ja.properties b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ja.properties
index b1b725c..1204172 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ja.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ja.properties
@@ -31,3 +31,4 @@ edit=\u7de8\u96c6
execute=\u5b9f\u884c
executeDryRun=\u4e88\u884c\u6f14\u7fd2
latestExecStatus=\u6700\u7d42\u30b9\u30c6\u30fc\u30bf\u30b9
+remediation=Remediation
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_pt_BR.properties
index 8200501..2acbca2 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_pt_BR.properties
@@ -31,3 +31,4 @@ edit=Edit
execute=Execute
executeDryRun=Dry run
latestExecStatus=Last status
+remediation=Remediation
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ru.properties
index 3b79aad..18bbca6 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder$Profile_ru.properties
@@ -32,3 +32,4 @@ edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c
execute=\u0417\u0430\u043f\u0443\u0441\u043a
executeDryRun=\u041f\u0440\u043e\u0431\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a
latestExecStatus=\u0421\u0442\u0430\u0442\u0443\u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430
+remediation=Remediation
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
index 2638ad6..3981200 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PullTaskTO.java
@@ -50,6 +50,8 @@ public class PullTaskTO extends ProvisioningTaskTO implements TemplatableTO {
@XmlElement(required = true)
private String destinationRealm;
+ private boolean remediation;
+
@XmlTransient
@JsonProperty("@class")
@Schema(name = "@class", required = true, example = "org.apache.syncope.common.lib.to.PullTaskTO")
@@ -90,4 +92,13 @@ public class PullTaskTO extends ProvisioningTaskTO implements TemplatableTO {
public Map<String, AnyTO> getTemplates() {
return templates;
}
+
+ public boolean isRemediation() {
+ return remediation;
+ }
+
+ public void setRemediation(final boolean remediation) {
+ this.remediation = remediation;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java
new file mode 100644
index 0000000..0b971cd
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RemediationTO.java
@@ -0,0 +1,165 @@
+/*
+ * 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.common.lib.to;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.util.Date;
+import javax.ws.rs.PathParam;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+
+@XmlRootElement(name = "remediation")
+@XmlType
+public class RemediationTO extends AbstractBaseBean implements EntityTO {
+
+ private static final long serialVersionUID = 3983540425142284975L;
+
+ private String key;
+
+ private AnyTypeKind anyTypeKind;
+
+ private ResourceOperation operation;
+
+ private AnyTO anyTOPayload;
+
+ private AnyPatch anyPatchPayload;
+
+ private String keyPayload;
+
+ private String error;
+
+ private Date instant;
+
+ private String pullTask;
+
+ private String resource;
+
+ private String remoteName;
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @PathParam("key")
+ @Override
+ public void setKey(final String key) {
+ this.key = key;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public AnyTypeKind getAnyTypeKind() {
+ return anyTypeKind;
+ }
+
+ public void setAnyTypeKind(final AnyTypeKind anyTypeKind) {
+ this.anyTypeKind = anyTypeKind;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public ResourceOperation getOperation() {
+ return operation;
+ }
+
+ public void setOperation(final ResourceOperation operation) {
+ this.operation = operation;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public AnyTO getAnyTOPayload() {
+ return anyTOPayload;
+ }
+
+ public void setAnyTOPayload(final AnyTO anyTOPayload) {
+ this.anyTOPayload = anyTOPayload;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public AnyPatch getAnyPatchPayload() {
+ return anyPatchPayload;
+ }
+
+ public void setAnyPatchPayload(final AnyPatch anyPatchPayload) {
+ this.anyPatchPayload = anyPatchPayload;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public String getKeyPayload() {
+ return keyPayload;
+ }
+
+ public void setKeyPayload(final String keyPayload) {
+ this.keyPayload = keyPayload;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public String getError() {
+ return error;
+ }
+
+ public void setError(final String error) {
+ this.error = error;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public Date getInstant() {
+ return instant == null
+ ? null
+ : new Date(instant.getTime());
+ }
+
+ public void setInstant(final Date instant) {
+ this.instant = instant == null
+ ? null
+ : new Date(instant.getTime());
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public String getPullTask() {
+ return pullTask;
+ }
+
+ public void setPullTask(final String pullTask) {
+ this.pullTask = pullTask;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(final String resource) {
+ this.resource = resource;
+ }
+
+ @Schema(accessMode = Schema.AccessMode.READ_ONLY)
+
+ public String getRemoteName() {
+ return remoteName;
+ }
+
+ public void setRemoteName(final String remoteName) {
+ this.remoteName = remoteName;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
index 12fbf59..6cd6c98 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
@@ -19,6 +19,10 @@
package org.apache.syncope.common.lib.types;
import javax.xml.bind.annotation.XmlEnum;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.GroupPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.GroupTO;
@@ -27,18 +31,25 @@ import org.apache.syncope.common.lib.to.UserTO;
@XmlEnum
public enum AnyTypeKind {
- USER(UserTO.class),
- GROUP(GroupTO.class),
- ANY_OBJECT(AnyObjectTO.class);
+ USER(UserTO.class, UserPatch.class),
+ GROUP(GroupTO.class, GroupPatch.class),
+ ANY_OBJECT(AnyObjectTO.class, AnyObjectPatch.class);
private final Class<? extends AnyTO> toClass;
- AnyTypeKind(final Class<? extends AnyTO> toClass) {
+ private final Class<? extends AnyPatch> patchClass;
+
+ AnyTypeKind(final Class<? extends AnyTO> toClass, final Class<? extends AnyPatch> patchClass) {
this.toClass = toClass;
+ this.patchClass = patchClass;
}
public Class<? extends AnyTO> getTOClass() {
return toClass;
}
+ public Class<? extends AnyPatch> getPatchClass() {
+ return patchClass;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
index 6cc7e7c..462ee5f 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
@@ -47,10 +47,13 @@ public enum EntityViolationType {
InvalidPlainAttr("org.apache.syncope.core.persistence.validation.plainattr"),
InvalidUsername("org.apache.syncope.core.persistence.validation.user.username"),
InvalidValueList("org.apache.syncope.core.persistence.validation.attr.valueList"),
+ InvalidRemediation("org.apache.syncope.core.persistence.validation.remediation"),
MoreThanOneNonNull("org.apache.syncope.core.persistence.validation.attrvalue.moreThanOneNonNull");
private String message;
+ private String propertyPath;
+
EntityViolationType(final String message) {
this.message = message;
}
@@ -62,4 +65,13 @@ public enum EntityViolationType {
public String getMessage() {
return message;
}
+
+ public String getPropertyPath() {
+ return propertyPath;
+ }
+
+ public void setPropertyPath(final String propertyPath) {
+ this.propertyPath = propertyPath;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
index 00a6638..0968f34 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/StandardEntitlement.java
@@ -302,6 +302,14 @@ public final class StandardEntitlement {
public static final String IMPLEMENTATION_DELETE = "IMPLEMENTATION_DELETE";
+ public static final String REMEDIATION_LIST = "REMEDIATION_LIST";
+
+ public static final String REMEDIATION_READ = "REMEDIATION_READ";
+
+ public static final String REMEDIATION_REMEDY = "REMEDIATION_REMEDY";
+
+ public static final String REMEDIATION_DELETE = "REMEDIATION_DELETE";
+
private static final Set<String> VALUES;
static {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
index 620d3fc..cf6352e 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
@@ -47,7 +47,7 @@ import org.apache.syncope.common.lib.types.ImplementationType;
public interface ImplementationService extends JAXRSService {
/**
- * Returns a list of all implementations.
+ * Returns a list of all implementations of the given type.
*
* @param type implementation type
* @return list of all implementations.
@@ -58,7 +58,7 @@ public interface ImplementationService extends JAXRSService {
List<ImplementationTO> list(@NotNull @PathParam("type") ImplementationType type);
/**
- * Returns implementation with matching key.
+ * Returns implementation with matching type and key.
*
* @param type implementation type
* @param key key of implementation to be read
@@ -94,7 +94,7 @@ public interface ImplementationService extends JAXRSService {
Response update(@NotNull ImplementationTO implementationTO);
/**
- * Deletes the implementation matching the given key.
+ * Deletes the implementation matching the given key and type.
*
* @param type implementation type
* @param key key for implementation to be deleted
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RemediationService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RemediationService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RemediationService.java
new file mode 100644
index 0000000..936eca5
--- /dev/null
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RemediationService.java
@@ -0,0 +1,213 @@
+/*
+ * 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.common.rest.api.service;
+
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.security.SecurityRequirements;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PATCH;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.RemediationTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+
+/**
+ * REST operations for remediations.
+ */
+@Tag(name = "Remediations")
+@SecurityRequirements({
+ @SecurityRequirement(name = "BasicAuthentication"),
+ @SecurityRequirement(name = "Bearer") })
+@Path("remediations")
+public interface RemediationService extends JAXRSService {
+
+ /**
+ * Returns a list of all remediations.
+ *
+ * @return list of all remediations.
+ */
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ List<RemediationTO> list();
+
+ /**
+ * Returns remediation with matching key.
+ *
+ * @param key key of remediation to be read
+ * @return remediation with matching key
+ */
+ @GET
+ @Path("{key}")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ RemediationTO read(@NotNull @PathParam("key") String key);
+
+ /**
+ * Deletes the remediation matching the given key.
+ *
+ * @param key key for remediation to be deleted
+ * @return an empty response if operation was successful
+ */
+ @DELETE
+ @Path("{key}")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ Response delete(@NotNull @PathParam("key") String key);
+
+ /**
+ * Perform remediation by creating the provided user, group or any object.
+ *
+ * @param key key for remediation to act on
+ * @param anyTO user, group or any object to create
+ * @return Response object featuring Location header of created object as well as the object itself
+ * enriched with propagation status information
+ */
+ @Parameter(name = RESTHeaders.PREFER, in = ParameterIn.HEADER,
+ description = "Allows client to specify a preference for the result to be returned from the server",
+ allowEmptyValue = true, schema =
+ @Schema(defaultValue = "return-content", allowableValues = { "return-content", "return-no-content" }))
+ @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+ description = "If 'true', instructs the propagation process not to wait for completion when communicating"
+ + " with External Resources with no priority set",
+ allowEmptyValue = true, schema =
+ @Schema(type = "boolean", defaultValue = "false"))
+ @ApiResponses(
+ @ApiResponse(responseCode = "201",
+ description = "Object successfully created enriched with propagation status information, as Entity,"
+ + "or empty if 'Prefer: return-no-content' was specified",
+ content =
+ @Content(schema =
+ @Schema(implementation = ProvisioningResult.class)), headers = {
+ @Header(name = RESTHeaders.RESOURCE_KEY, schema =
+ @Schema(type = "string"),
+ description = "UUID generated for the object created"),
+ @Header(name = HttpHeaders.LOCATION, schema =
+ @Schema(type = "string"),
+ description = "URL of the object created"),
+ @Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
+ @Schema(type = "string"),
+ description = "Allows the server to inform the "
+ + "client about the fact that a specified preference was applied") }))
+ @POST
+ @Path("{key}")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ Response remedy(@NotNull @PathParam("key") String key, @NotNull AnyTO anyTO);
+
+ /**
+ * Perform remediation by updating the provided user, group or any object.
+ *
+ * @param key key for remediation to act on
+ * @param anyPatch user, group or any object to update
+ * @return Response object featuring the updated object enriched with propagation status information
+ */
+ @Parameter(name = RESTHeaders.PREFER, in = ParameterIn.HEADER,
+ description = "Allows client to specify a preference for the result to be returned from the server",
+ allowEmptyValue = true, schema =
+ @Schema(defaultValue = "return-content", allowableValues = { "return-content", "return-no-content" }))
+ @Parameter(name = HttpHeaders.IF_MATCH, in = ParameterIn.HEADER,
+ description = "When the provided ETag value does not match the latest modification date of the entity, "
+ + "an error is reported and the requested operation is not performed.",
+ allowEmptyValue = true, schema =
+ @Schema(type = "string"))
+ @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+ description = "If 'true', instructs the propagation process not to wait for completion when communicating"
+ + " with External Resources with no priority set",
+ allowEmptyValue = true, schema =
+ @Schema(type = "boolean", defaultValue = "false"))
+ @ApiResponses({
+ @ApiResponse(responseCode = "200",
+ description = "Object successfully updated enriched with propagation status information, as Entity",
+ content =
+ @Content(schema =
+ @Schema(implementation = ProvisioningResult.class))),
+ @ApiResponse(responseCode = "204",
+ description = "No content if 'Prefer: return-no-content' was specified", headers =
+ @Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
+ @Schema(type = "string"),
+ description = "Allows the server to inform the "
+ + "client about the fact that a specified preference was applied")),
+ @ApiResponse(responseCode = "412",
+ description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
+ + " date of the entity") })
+ @PATCH
+ @Path("{key}")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ Response remedy(@NotNull @PathParam("key") String key, @NotNull AnyPatch anyPatch);
+
+ /**
+ * Perform remediation by deleting the provided user, group or any object.
+ *
+ * @param key key for remediation to act on
+ * @param anyKey user's, group's or any object's key to delete
+ * @return Response object featuring the deleted object enriched with propagation status information
+ */
+ @Parameter(name = RESTHeaders.PREFER, in = ParameterIn.HEADER,
+ description = "Allows client to specify a preference for the result to be returned from the server",
+ allowEmptyValue = true, schema =
+ @Schema(defaultValue = "return-content", allowableValues = { "return-content", "return-no-content" }))
+ @Parameter(name = HttpHeaders.IF_MATCH, in = ParameterIn.HEADER,
+ description = "When the provided ETag value does not match the latest modification date of the entity, "
+ + "an error is reported and the requested operation is not performed.",
+ allowEmptyValue = true, schema =
+ @Schema(type = "string"))
+ @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+ description = "If 'true', instructs the propagation process not to wait for completion when communicating"
+ + " with External Resources with no priority set",
+ allowEmptyValue = true, schema =
+ @Schema(type = "boolean", defaultValue = "false"))
+ @ApiResponses({
+ @ApiResponse(responseCode = "200",
+ description = "Object successfully deleted enriched with propagation status information, as Entity",
+ content =
+ @Content(schema =
+ @Schema(implementation = ProvisioningResult.class))),
+ @ApiResponse(responseCode = "204",
+ description = "No content if 'Prefer: return-no-content' was specified", headers =
+ @Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
+ @Schema(type = "string"),
+ description = "Allows the server to inform the "
+ + "client about the fact that a specified preference was applied")),
+ @ApiResponse(responseCode = "412",
+ description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
+ + " date of the entity") })
+ @DELETE
+ @Path("{key}/{anyKey}")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ Response remedy(@NotNull @PathParam("key") String key, @NotNull String anyKey);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
index 3bb0148..7a52fa5 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
@@ -53,8 +53,7 @@ import org.apache.syncope.common.rest.api.beans.AnyQuery;
*/
@Tag(name = "Users")
@SecurityRequirements({
- @SecurityRequirement(name = "BasicAuthentication")
- ,
+ @SecurityRequirement(name = "BasicAuthentication"),
@SecurityRequirement(name = "Bearer") })
@Path("users")
public interface UserService extends AnyService<UserTO> {
@@ -99,12 +98,10 @@ public interface UserService extends AnyService<UserTO> {
@Schema(implementation = ProvisioningResult.class)), headers = {
@Header(name = RESTHeaders.RESOURCE_KEY, schema =
@Schema(type = "string"),
- description = "UUID generated for the user created")
- ,
+ description = "UUID generated for the user created"),
@Header(name = HttpHeaders.LOCATION, schema =
@Schema(type = "string"),
- description = "URL of the user created")
- ,
+ description = "URL of the user created"),
@Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
@Schema(type = "string"),
description = "Allows the server to inform the "
@@ -141,15 +138,13 @@ public interface UserService extends AnyService<UserTO> {
description = "User successfully updated enriched with propagation status information, as Entity",
content =
@Content(schema =
- @Schema(implementation = ProvisioningResult.class)))
- ,
+ @Schema(implementation = ProvisioningResult.class))),
@ApiResponse(responseCode = "204",
description = "No content if 'Prefer: return-no-content' was specified", headers =
@Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
@Schema(type = "string"),
description = "Allows the server to inform the "
- + "client about the fact that a specified preference was applied"))
- ,
+ + "client about the fact that a specified preference was applied")),
@ApiResponse(responseCode = "412",
description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
+ " date of the entity") })
@@ -185,15 +180,13 @@ public interface UserService extends AnyService<UserTO> {
description = "User successfully updated enriched with propagation status information, as Entity",
content =
@Content(schema =
- @Schema(implementation = ProvisioningResult.class)))
- ,
+ @Schema(implementation = ProvisioningResult.class))),
@ApiResponse(responseCode = "204",
description = "No content if 'Prefer: return-no-content' was specified", headers =
@Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
@Schema(type = "string"),
description = "Allows the server to inform the "
- + "client about the fact that a specified preference was applied"))
- ,
+ + "client about the fact that a specified preference was applied")),
@ApiResponse(responseCode = "412",
description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
+ " date of the entity") })
@@ -229,15 +222,13 @@ public interface UserService extends AnyService<UserTO> {
description = "User successfully updated enriched with propagation status information, as Entity",
content =
@Content(schema =
- @Schema(implementation = ProvisioningResult.class)))
- ,
+ @Schema(implementation = ProvisioningResult.class))),
@ApiResponse(responseCode = "204",
description = "No content if 'Prefer: return-no-content' was specified", headers =
@Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
@Schema(type = "string"),
description = "Allows the server to inform the "
- + "client about the fact that a specified preference was applied"))
- ,
+ + "client about the fact that a specified preference was applied")),
@ApiResponse(responseCode = "412",
description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
+ " date of the entity") })
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
index aa71fbd..0c00b45 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
@@ -113,7 +113,7 @@ public class AccessTokenLogic extends AbstractTransactionalLogic<AccessTokenTO>
Integer count = accessTokenDAO.count();
List<AccessTokenTO> result = accessTokenDAO.findAll(page, size, orderByClauses).stream().
- map(accessToken -> binder.getAccessTokenTO(accessToken)).collect(Collectors.toList());
+ map(binder::getAccessTokenTO).collect(Collectors.toList());
return Pair.of(count, result);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
index 03f6909..adab632 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
@@ -62,8 +62,7 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO
@PreAuthorize("hasRole('" + StandardEntitlement.ANYTYPECLASS_LIST + "')")
@Transactional(readOnly = true)
public List<AnyTypeClassTO> list() {
- return anyTypeClassDAO.findAll().stream().
- map(anyTypeClass -> binder.getAnyTypeClassTO(anyTypeClass)).collect(Collectors.toList());
+ return anyTypeClassDAO.findAll().stream().map(binder::getAnyTypeClassTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.ANYTYPECLASS_CREATE + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
index 95944c9..d606af2 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
@@ -66,7 +66,7 @@ public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> {
@PreAuthorize("hasRole('" + StandardEntitlement.ANYTYPE_LIST + "')")
@Transactional(readOnly = true)
public List<AnyTypeTO> list() {
- return anyTypeDAO.findAll().stream().map(anyType -> binder.getAnyTypeTO(anyType)).collect(Collectors.toList());
+ return anyTypeDAO.findAll().stream().map(binder::getAnyTypeTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.ANYTYPE_CREATE + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ApplicationLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ApplicationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ApplicationLogic.java
index e25f532..50495ca 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ApplicationLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ApplicationLogic.java
@@ -73,8 +73,7 @@ public class ApplicationLogic extends AbstractTransactionalLogic<ApplicationTO>
@PreAuthorize("hasRole('" + StandardEntitlement.APPLICATION_LIST + "')")
@Transactional(readOnly = true)
public List<ApplicationTO> list() {
- return applicationDAO.findAll().stream().
- map(application -> binder.getApplicationTO(application)).collect(Collectors.toList());
+ return applicationDAO.findAll().stream().map(binder::getApplicationTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.APPLICATION_CREATE + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorHistoryLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorHistoryLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorHistoryLogic.java
index e7ff07c..e3a22a8 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorHistoryLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorHistoryLogic.java
@@ -32,6 +32,7 @@ import org.apache.syncope.core.provisioning.api.data.ConnInstanceDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class ConnectorHistoryLogic extends AbstractTransactionalLogic<ConnInstanceHistoryConfTO> {
@@ -45,17 +46,8 @@ public class ConnectorHistoryLogic extends AbstractTransactionalLogic<ConnInstan
@Autowired
private ConnInstanceDataBinder binder;
- private ConnInstanceHistoryConfTO getConnInstanceHistoryConfTO(final ConnInstanceHistoryConf history) {
- ConnInstanceHistoryConfTO historyTO = new ConnInstanceHistoryConfTO();
- historyTO.setKey(history.getKey());
- historyTO.setCreator(history.getCreator());
- historyTO.setCreation(history.getCreation());
- historyTO.setConnInstanceTO(history.getConf());
-
- return historyTO;
- }
-
@PreAuthorize("hasRole('" + StandardEntitlement.CONNECTOR_HISTORY_LIST + "')")
+ @Transactional(readOnly = true)
public List<ConnInstanceHistoryConfTO> list(final String key) {
ConnInstance connInstance = connInstanceDAO.find(key);
if (connInstance == null) {
@@ -63,7 +55,7 @@ public class ConnectorHistoryLogic extends AbstractTransactionalLogic<ConnInstan
}
return connInstanceHistoryConfDAO.findByEntity(connInstance).stream().
- map(historyConf -> getConnInstanceHistoryConfTO(historyConf)).collect(Collectors.toList());
+ map(binder::getConnInstanceHistoryConfTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.CONNECTOR_HISTORY_RESTORE + "')")
@@ -93,7 +85,7 @@ public class ConnectorHistoryLogic extends AbstractTransactionalLogic<ConnInstan
if (!"list".equals(method.getName())) {
try {
String key = (String) args[0];
- return getConnInstanceHistoryConfTO(connInstanceHistoryConfDAO.find(key));
+ return binder.getConnInstanceHistoryConfTO(connInstanceHistoryConfDAO.find(key));
} catch (Throwable ignore) {
LOG.debug("Unresolved reference", ignore);
throw new UnresolvedReferenceException(ignore);
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorLogic.java
index 75d704e..c5bbdf8 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ConnectorLogic.java
@@ -19,11 +19,9 @@
package org.apache.syncope.core.logic;
import java.lang.reflect.Method;
-import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
@@ -47,8 +45,8 @@ import org.apache.syncope.core.spring.security.AuthContextUtils;
import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.identityconnectors.common.l10n.CurrentLocale;
import org.identityconnectors.framework.api.ConfigurationProperties;
-import org.identityconnectors.framework.api.ConnectorInfoManager;
import org.identityconnectors.framework.api.ConnectorKey;
+import org.identityconnectors.framework.common.objects.AttributeInfo;
import org.identityconnectors.framework.common.objects.AttributeUtil;
import org.identityconnectors.framework.common.objects.ObjectClassInfo;
import org.springframework.beans.factory.annotation.Autowired;
@@ -149,9 +147,8 @@ public class ConnectorLogic extends AbstractTransactionalLogic<ConnInstanceTO> {
try {
result = binder.getConnInstanceTO(connInstance);
} catch (NotFoundException e) {
- LOG.
- error("Connector '{}#{}' not found", connInstance.getBundleName(), connInstance.
- getVersion());
+ LOG.error("Connector '{}#{}' not found",
+ connInstance.getBundleName(), connInstance.getVersion());
}
return result;
@@ -181,29 +178,31 @@ public class ConnectorLogic extends AbstractTransactionalLogic<ConnInstanceTO> {
}
List<ConnBundleTO> connectorBundleTOs = new ArrayList<>();
- for (Map.Entry<URI, ConnectorInfoManager> entry : connIdBundleManager.getConnInfoManagers().entrySet()) {
- entry.getValue().getConnectorInfos().stream().map(bundle -> {
+ connIdBundleManager.getConnInfoManagers().forEach((uri, cim) -> {
+ connectorBundleTOs.addAll(cim.getConnectorInfos().stream().map(bundle -> {
ConnBundleTO connBundleTO = new ConnBundleTO();
connBundleTO.setDisplayName(bundle.getConnectorDisplayName());
- connBundleTO.setLocation(entry.getKey().toString());
+
+ connBundleTO.setLocation(uri.toString());
+
ConnectorKey key = bundle.getConnectorKey();
connBundleTO.setBundleName(key.getBundleName());
connBundleTO.setConnectorName(key.getConnectorName());
connBundleTO.setVersion(key.getBundleVersion());
+
ConfigurationProperties properties = connIdBundleManager.getConfigurationProperties(bundle);
- for (String propName : properties.getPropertyNames()) {
- connBundleTO.getProperties().add(binder.build(properties.getProperty(propName)));
- }
+ connBundleTO.getProperties().addAll(properties.getPropertyNames().stream().
+ map(propName -> binder.build(properties.getProperty(propName))).collect(Collectors.toList()));
+
return connBundleTO;
- }).forEachOrdered(connBundleTO -> {
- connectorBundleTOs.add(connBundleTO);
- });
- }
+ }).collect(Collectors.toList()));
+ });
return connectorBundleTOs;
}
@PreAuthorize("hasRole('" + StandardEntitlement.CONNECTOR_READ + "')")
+
public List<ConnIdObjectClassTO> buildObjectClassInfo(
final ConnInstanceTO connInstanceTO, final boolean includeSpecial) {
@@ -217,23 +216,19 @@ public class ConnectorLogic extends AbstractTransactionalLogic<ConnInstanceTO> {
connFactory.buildConnInstanceOverride(actual, connInstanceTO.getConf(), null)).
getObjectClassInfo();
- List<ConnIdObjectClassTO> result = new ArrayList<>(objectClassInfo.size());
- objectClassInfo.stream().map(info -> {
+ return objectClassInfo.stream().map(info -> {
ConnIdObjectClassTO connIdObjectClassTO = new ConnIdObjectClassTO();
connIdObjectClassTO.setType(info.getType());
connIdObjectClassTO.setAuxiliary(info.isAuxiliary());
connIdObjectClassTO.setContainer(info.isContainer());
- info.getAttributeInfo().stream().
+
+ connIdObjectClassTO.getAttributes().addAll(info.getAttributeInfo().stream().
filter(attrInfo -> includeSpecial || !AttributeUtil.isSpecialName(attrInfo.getName())).
- forEachOrdered(attrInfo -> {
- connIdObjectClassTO.getAttributes().add(attrInfo.getName());
- });
- return connIdObjectClassTO;
- }).forEachOrdered((connIdObjectClassTO) -> {
- result.add(connIdObjectClassTO);
- });
+ map(AttributeInfo::getName).
+ collect(Collectors.toList()));
- return result;
+ return connIdObjectClassTO;
+ }).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.CONNECTOR_READ + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
index d9d29ba..9e3967b 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
@@ -33,6 +33,7 @@ import org.apache.syncope.core.provisioning.api.data.DomainDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class DomainLogic extends AbstractTransactionalLogic<DomainTO> {
@@ -48,6 +49,7 @@ public class DomainLogic extends AbstractTransactionalLogic<DomainTO> {
@PreAuthorize("hasRole('" + StandardEntitlement.DOMAIN_READ + "') and authentication.details.domain == "
+ "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+ @Transactional(readOnly = true)
public DomainTO read(final String key) {
Domain domain = domainDAO.find(key);
if (domain == null) {
@@ -60,8 +62,9 @@ public class DomainLogic extends AbstractTransactionalLogic<DomainTO> {
}
@PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
public List<DomainTO> list() {
- return domainDAO.findAll().stream().map(domain -> binder.getDomainTO(domain)).collect(Collectors.toList());
+ return domainDAO.findAll().stream().map(binder::getDomainTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.DOMAIN_CREATE + "') and authentication.details.domain == "
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/DynRealmLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/DynRealmLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/DynRealmLogic.java
index de9e78a..487cc59 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/DynRealmLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/DynRealmLogic.java
@@ -31,6 +31,7 @@ import org.apache.syncope.core.provisioning.api.data.DynRealmDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class DynRealmLogic extends AbstractTransactionalLogic<DynRealmTO> {
@@ -42,6 +43,7 @@ public class DynRealmLogic extends AbstractTransactionalLogic<DynRealmTO> {
private DynRealmDAO dynRealmDAO;
@PreAuthorize("hasRole('" + StandardEntitlement.DYNREALM_READ + "')")
+ @Transactional(readOnly = true)
public DynRealmTO read(final String key) {
DynRealm dynRealm = dynRealmDAO.find(key);
if (dynRealm == null) {
@@ -53,9 +55,9 @@ public class DynRealmLogic extends AbstractTransactionalLogic<DynRealmTO> {
return binder.getDynRealmTO(dynRealm);
}
+ @Transactional(readOnly = true)
public List<DynRealmTO> list() {
- return dynRealmDAO.findAll().stream().
- map(dynRealm -> binder.getDynRealmTO(dynRealm)).collect(Collectors.toList());
+ return dynRealmDAO.findAll().stream().map(binder::getDynRealmTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.DYNREALM_CREATE + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
index 83bc933..3079483 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
@@ -43,6 +43,7 @@ import org.apache.syncope.core.provisioning.api.data.ImplementationDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class ImplementationLogic extends AbstractTransactionalLogic<ImplementationTO> {
@@ -75,12 +76,13 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
private NotificationDAO notificationDAO;
@PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_LIST + "')")
+ @Transactional(readOnly = true)
public List<ImplementationTO> list(final ImplementationType type) {
- return implementationDAO.find(type).stream().
- map(implementation -> binder.getImplementationTO(implementation)).collect(Collectors.toList());
+ return implementationDAO.find(type).stream().map(binder::getImplementationTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_READ + "')")
+ @Transactional(readOnly = true)
public ImplementationTO read(final ImplementationType type, final String key) {
Implementation implementation = implementationDAO.find(key);
if (implementation == null) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
index 0867c62..c576774 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/LoggerLogic.java
@@ -95,6 +95,7 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
@PreAuthorize("hasRole('" + StandardEntitlement.LOG_LIST + "') and authentication.details.domain == "
+ "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+ @Transactional(readOnly = true)
public List<LogAppender> memoryAppenders() {
return loggerLoader.getMemoryAppenders().keySet().stream().map(appender -> {
LogAppender logAppender = new LogAppender();
@@ -105,6 +106,7 @@ public class LoggerLogic extends AbstractTransactionalLogic<LoggerTO> {
@PreAuthorize("hasRole('" + StandardEntitlement.LOG_READ + "') and authentication.details.domain == "
+ "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+ @Transactional(readOnly = true)
public List<LogStatementTO> getLastLogStatements(final String memoryAppender) {
MemoryAppender appender = loggerLoader.getMemoryAppenders().get(memoryAppender);
if (appender == null) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
index 3f2b7c8..d33d68a 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
@@ -39,6 +39,7 @@ import org.apache.syncope.core.persistence.api.entity.Notification;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class MailTemplateLogic extends AbstractTransactionalLogic<MailTemplateTO> {
@@ -59,6 +60,7 @@ public class MailTemplateLogic extends AbstractTransactionalLogic<MailTemplateTO
}
@PreAuthorize("hasRole('" + StandardEntitlement.MAIL_TEMPLATE_READ + "')")
+ @Transactional(readOnly = true)
public MailTemplateTO read(final String key) {
MailTemplate mailTemplate = mailTemplateDAO.find(key);
if (mailTemplate == null) {
@@ -71,6 +73,7 @@ public class MailTemplateLogic extends AbstractTransactionalLogic<MailTemplateTO
}
@PreAuthorize("hasRole('" + StandardEntitlement.MAIL_TEMPLATE_LIST + "')")
+ @Transactional(readOnly = true)
public List<MailTemplateTO> list() {
return mailTemplateDAO.findAll().stream().
map(template -> getMailTemplateTO(template.getKey())).collect(Collectors.toList());
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java
index b594613..d9a662f 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java
@@ -38,6 +38,7 @@ import org.quartz.JobKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class NotificationLogic extends AbstractJobLogic<NotificationTO> {
@@ -49,6 +50,7 @@ public class NotificationLogic extends AbstractJobLogic<NotificationTO> {
private NotificationDataBinder binder;
@PreAuthorize("hasRole('" + StandardEntitlement.NOTIFICATION_READ + "')")
+ @Transactional(readOnly = true)
public NotificationTO read(final String key) {
Notification notification = notificationDAO.find(key);
if (notification == null) {
@@ -61,9 +63,9 @@ public class NotificationLogic extends AbstractJobLogic<NotificationTO> {
}
@PreAuthorize("hasRole('" + StandardEntitlement.NOTIFICATION_LIST + "')")
+ @Transactional(readOnly = true)
public List<NotificationTO> list() {
- return notificationDAO.findAll().stream().
- map(notification -> binder.getNotificationTO(notification)).collect(Collectors.toList());
+ return notificationDAO.findAll().stream().map(binder::getNotificationTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.NOTIFICATION_CREATE + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
index 2506a90..29f3052 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/PolicyLogic.java
@@ -36,6 +36,7 @@ import org.apache.syncope.core.provisioning.api.data.PolicyDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class PolicyLogic extends AbstractTransactionalLogic<PolicyTO> {
@@ -76,14 +77,16 @@ public class PolicyLogic extends AbstractTransactionalLogic<PolicyTO> {
}
@PreAuthorize("hasRole('" + StandardEntitlement.POLICY_LIST + "')")
+ @Transactional(readOnly = true)
public <T extends PolicyTO> List<T> list(final PolicyType type) {
PolicyUtils policyUtils = policyUtilsFactory.getInstance(type);
return policyDAO.find(policyUtils.policyClass()).stream().
- <T>map(policy -> binder.getPolicyTO(policy)).collect(Collectors.toList());
+ <T>map(binder::getPolicyTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.POLICY_READ + "')")
+ @Transactional(readOnly = true)
public <T extends PolicyTO> T read(final PolicyType type, final String key) {
Policy policy = policyDAO.find(key);
if (policy == null) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java
index 4c2a8cc..86a1847 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java
@@ -50,6 +50,7 @@ import org.apache.syncope.core.spring.security.AuthContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class RealmLogic extends AbstractTransactionalLogic<RealmTO> {
@@ -70,6 +71,7 @@ public class RealmLogic extends AbstractTransactionalLogic<RealmTO> {
private PropagationTaskExecutor taskExecutor;
@PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
public List<RealmTO> list(final String fullPath) {
Realm realm = realmDAO.findByFullPath(fullPath);
if (realm == null) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java
index 30ac9a2..b0c1ff5 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/RelationshipTypeLogic.java
@@ -32,6 +32,7 @@ import org.apache.syncope.core.provisioning.api.data.RelationshipTypeDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class RelationshipTypeLogic extends AbstractTransactionalLogic<RelationshipTypeTO> {
@@ -43,6 +44,7 @@ public class RelationshipTypeLogic extends AbstractTransactionalLogic<Relationsh
private RelationshipTypeDAO relationshipTypeDAO;
@PreAuthorize("hasRole('" + StandardEntitlement.RELATIONSHIPTYPE_READ + "')")
+ @Transactional(readOnly = true)
public RelationshipTypeTO read(final String key) {
RelationshipType relationshipType = relationshipTypeDAO.find(key);
if (relationshipType == null) {
@@ -55,9 +57,9 @@ public class RelationshipTypeLogic extends AbstractTransactionalLogic<Relationsh
}
@PreAuthorize("hasRole('" + StandardEntitlement.RELATIONSHIPTYPE_LIST + "')")
+ @Transactional(readOnly = true)
public List<RelationshipTypeTO> list() {
- return relationshipTypeDAO.findAll().stream().
- map(relationshipType -> binder.getRelationshipTypeTO(relationshipType)).collect(Collectors.toList());
+ return relationshipTypeDAO.findAll().stream().map(binder::getRelationshipTypeTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.RELATIONSHIPTYPE_CREATE + "')")
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java
new file mode 100644
index 0000000..1fb93e0
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java
@@ -0,0 +1,210 @@
+/*
+ * 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.core.logic;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.GroupPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.RemediationTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.RemediationDAO;
+import org.apache.syncope.core.persistence.api.entity.Remediation;
+import org.apache.syncope.core.provisioning.api.data.RemediationDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class RemediationLogic extends AbstractTransactionalLogic<RemediationTO> {
+
+ @Autowired
+ private UserLogic userLogic;
+
+ @Autowired
+ private GroupLogic groupLogic;
+
+ @Autowired
+ private AnyObjectLogic anyObjectLogic;
+
+ @Autowired
+ private RemediationDataBinder binder;
+
+ @Autowired
+ private RemediationDAO remediationDAO;
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.REMEDIATION_LIST + "')")
+ @Transactional(readOnly = true)
+ public List<RemediationTO> list() {
+ return remediationDAO.findAll().stream().map(binder::getRemediationTO).collect(Collectors.toList());
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.REMEDIATION_READ + "')")
+ @Transactional(readOnly = true)
+ public RemediationTO read(final String key) {
+ Remediation remediation = remediationDAO.find(key);
+ if (remediation == null) {
+ LOG.error("Could not find remediation '" + key + "'");
+
+ throw new NotFoundException(key);
+ }
+
+ return binder.getRemediationTO(remediation);
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.REMEDIATION_DELETE + "')")
+ public void delete(final String key) {
+ Remediation remediation = remediationDAO.find(key);
+ if (remediation == null) {
+ LOG.error("Could not find remediation '" + key + "'");
+
+ throw new NotFoundException(key);
+ }
+
+ remediationDAO.delete(remediation);
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.REMEDIATION_REMEDY + "')")
+ public ProvisioningResult<?> remedy(final String key, final AnyTO anyTO, final boolean nullPriorityAsync) {
+ Remediation remediation = remediationDAO.find(key);
+ if (remediation == null) {
+ LOG.error("Could not find remediation '" + key + "'");
+
+ throw new NotFoundException(key);
+ }
+
+ ProvisioningResult<?> result;
+ switch (remediation.getAnyTypeKind()) {
+ case USER:
+ default:
+ result = userLogic.create((UserTO) anyTO, true, nullPriorityAsync);
+ break;
+
+ case GROUP:
+ result = groupLogic.create((GroupTO) anyTO, nullPriorityAsync);
+ break;
+
+ case ANY_OBJECT:
+ result = anyObjectLogic.create((AnyObjectTO) anyTO, nullPriorityAsync);
+ }
+
+ remediationDAO.delete(remediation);
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.REMEDIATION_REMEDY + "')")
+ public ProvisioningResult<?> remedy(final String key, final AnyPatch anyPatch, final boolean nullPriorityAsync) {
+ Remediation remediation = remediationDAO.find(key);
+ if (remediation == null) {
+ LOG.error("Could not find remediation '" + key + "'");
+
+ throw new NotFoundException(key);
+ }
+
+ ProvisioningResult<?> result;
+ switch (remediation.getAnyTypeKind()) {
+ case USER:
+ default:
+ result = userLogic.update((UserPatch) anyPatch, nullPriorityAsync);
+ break;
+
+ case GROUP:
+ result = groupLogic.update((GroupPatch) anyPatch, nullPriorityAsync);
+ break;
+
+ case ANY_OBJECT:
+ result = anyObjectLogic.update((AnyObjectPatch) anyPatch, nullPriorityAsync);
+ }
+
+ remediationDAO.delete(remediation);
+
+ return result;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.REMEDIATION_REMEDY + "')")
+ public ProvisioningResult<?> remedy(final String key, final String anyKey, final boolean nullPriorityAsync) {
+ Remediation remediation = remediationDAO.find(key);
+ if (remediation == null) {
+ LOG.error("Could not find remediation '" + key + "'");
+
+ throw new NotFoundException(key);
+ }
+
+ ProvisioningResult<?> result;
+ switch (remediation.getAnyTypeKind()) {
+ case USER:
+ default:
+ result = userLogic.delete(anyKey, nullPriorityAsync);
+ break;
+
+ case GROUP:
+ result = groupLogic.delete(anyKey, nullPriorityAsync);
+ break;
+
+ case ANY_OBJECT:
+ result = anyObjectLogic.delete(anyKey, nullPriorityAsync);
+ }
+
+ remediationDAO.delete(remediation);
+
+ return result;
+ }
+
+ @Override
+ protected RemediationTO resolveReference(final Method method, final Object... args)
+ throws UnresolvedReferenceException {
+
+ String key = null;
+
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; key == null && i < args.length; i++) {
+ if (args[i] instanceof String) {
+ key = (String) args[i];
+ } else if (args[i] instanceof RemediationTO) {
+ key = ((RemediationTO) args[i]).getKey();
+ }
+ }
+ }
+
+ if (StringUtils.isNotBlank(key)) {
+ try {
+ return binder.getRemediationTO(remediationDAO.find(key));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
index 6a5a442..780e8ac 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java
@@ -68,6 +68,7 @@ import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class ReportLogic extends AbstractExecutableLogic<ReportTO> {
@@ -136,11 +137,13 @@ public class ReportLogic extends AbstractExecutableLogic<ReportTO> {
}
@PreAuthorize("hasRole('" + StandardEntitlement.REPORT_LIST + "')")
+ @Transactional(readOnly = true)
public List<ReportTO> list() {
- return reportDAO.findAll().stream().map(report -> binder.getReportTO(report)).collect(Collectors.toList());
+ return reportDAO.findAll().stream().map(binder::getReportTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.REPORT_READ + "')")
+ @Transactional(readOnly = true)
public ReportTO read(final String key) {
Report report = reportDAO.find(key);
if (report == null) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
index d59831c..5dc61c1 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
@@ -39,6 +39,7 @@ import org.apache.syncope.core.persistence.api.entity.Report;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class ReportTemplateLogic extends AbstractTransactionalLogic<ReportTemplateTO> {
@@ -59,6 +60,7 @@ public class ReportTemplateLogic extends AbstractTransactionalLogic<ReportTempla
}
@PreAuthorize("hasRole('" + StandardEntitlement.REPORT_TEMPLATE_READ + "')")
+ @Transactional(readOnly = true)
public ReportTemplateTO read(final String key) {
ReportTemplate reportTemplate = reportTemplateDAO.find(key);
if (reportTemplate == null) {
@@ -71,6 +73,7 @@ public class ReportTemplateLogic extends AbstractTransactionalLogic<ReportTempla
}
@PreAuthorize("hasRole('" + StandardEntitlement.REPORT_TEMPLATE_LIST + "')")
+ @Transactional(readOnly = true)
public List<ReportTemplateTO> list() {
return reportTemplateDAO.findAll().stream().
map(template -> getReportTemplateTO(template.getKey())).collect(Collectors.toList());
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceHistoryLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceHistoryLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceHistoryLogic.java
index d027e97..42126fb 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceHistoryLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceHistoryLogic.java
@@ -32,6 +32,7 @@ import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class ResourceHistoryLogic extends AbstractTransactionalLogic<ResourceHistoryConfTO> {
@@ -45,17 +46,8 @@ public class ResourceHistoryLogic extends AbstractTransactionalLogic<ResourceHis
@Autowired
private ResourceDataBinder binder;
- private ResourceHistoryConfTO getResourceHistoryConfTO(final ExternalResourceHistoryConf history) {
- ResourceHistoryConfTO historyTO = new ResourceHistoryConfTO();
- historyTO.setKey(history.getKey());
- historyTO.setCreator(history.getCreator());
- historyTO.setCreation(history.getCreation());
- historyTO.setResourceTO(history.getConf());
-
- return historyTO;
- }
-
@PreAuthorize("hasRole('" + StandardEntitlement.RESOURCE_HISTORY_LIST + "')")
+ @Transactional(readOnly = true)
public List<ResourceHistoryConfTO> list(final String key) {
ExternalResource resource = resourceDAO.find(key);
if (resource == null) {
@@ -63,7 +55,7 @@ public class ResourceHistoryLogic extends AbstractTransactionalLogic<ResourceHis
}
return resourceHistoryConfDAO.findByEntity(resource).stream().
- map(historyConf -> getResourceHistoryConfTO(historyConf)).collect(Collectors.toList());
+ map(binder::getResourceHistoryConfTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.RESOURCE_HISTORY_RESTORE + "')")
@@ -93,7 +85,7 @@ public class ResourceHistoryLogic extends AbstractTransactionalLogic<ResourceHis
if (!"list".equals(method.getName())) {
try {
String key = (String) args[0];
- return getResourceHistoryConfTO(resourceHistoryConfDAO.find(key));
+ return binder.getResourceHistoryConfTO(resourceHistoryConfDAO.find(key));
} catch (Throwable ignore) {
LOG.debug("Unresolved reference", ignore);
throw new UnresolvedReferenceException(ignore);
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index 1901393..e90b245 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -274,8 +274,7 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
@PreAuthorize("hasRole('" + StandardEntitlement.RESOURCE_LIST + "')")
@Transactional(readOnly = true)
public List<ResourceTO> list() {
- return resourceDAO.findAll().stream().
- map(resource -> binder.getResourceTO(resource)).collect(Collectors.toList());
+ return resourceDAO.findAll().stream().map(binder::getResourceTO).collect(Collectors.toList());
}
private Triple<ExternalResource, AnyType, Provision> connObjectInit(
http://git-wip-us.apache.org/repos/asf/syncope/blob/51b314fe/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
index e8b9f8a..a04e518 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/RoleLogic.java
@@ -59,7 +59,7 @@ public class RoleLogic extends AbstractTransactionalLogic<RoleTO> {
@PreAuthorize("hasRole('" + StandardEntitlement.ROLE_LIST + "')")
@Transactional(readOnly = true)
public List<RoleTO> list() {
- return roleDAO.findAll().stream().map(role -> binder.getRoleTO(role)).collect(Collectors.toList());
+ return roleDAO.findAll().stream().map(binder::getRoleTO).collect(Collectors.toList());
}
@PreAuthorize("hasRole('" + StandardEntitlement.ROLE_CREATE + "')")