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 2022/01/31 17:20:01 UTC

[syncope] branch master updated: [SYNCOPE-1641] added resources to match to purge propagation tasks API (#305)

This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new c1087c5  [SYNCOPE-1641] added resources to match to purge propagation tasks API (#305)
c1087c5 is described below

commit c1087c525b65258fdea224a85acb8fda5eb32384
Author: Andrea Patricelli <an...@apache.org>
AuthorDate: Mon Jan 31 18:19:54 2022 +0100

    [SYNCOPE-1641] added resources to match to purge propagation tasks API (#305)
---
 .../common/rest/api/service/TaskService.java        |  5 ++++-
 .../org/apache/syncope/core/logic/TaskLogic.java    | 11 +++++++++--
 .../core/rest/cxf/service/TaskServiceImpl.java      |  7 ++++---
 .../syncope/core/persistence/api/dao/TaskDAO.java   |  5 ++++-
 .../src/test/resources/domains/MasterContent.xml    |  5 +++++
 .../core/persistence/jpa/dao/JPATaskDAO.java        | 13 ++++++++++++-
 .../core/persistence/jpa/inner/TaskTest.java        |  4 ++--
 .../src/test/resources/domains/MasterContent.xml    |  5 +++++
 .../syncope/fit/core/PropagationTaskITCase.java     | 21 +++++++++++++++++++--
 9 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
index caa1695..dcaa2c7 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
@@ -148,6 +148,7 @@ public interface TaskService extends ExecutableService {
      *
      * @param since match all executions started afterwards
      * @param statuses execution status(es) to match
+     * @param resources external resource(s) to match
      * @return deleted propagation tasks
      */
     @ApiResponses({
@@ -157,5 +158,7 @@ public interface TaskService extends ExecutableService {
     @Path("PROPAGATION/purge")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
     Response purgePropagations(
-            @QueryParam("since") Date since, @QueryParam("statuses") List<ExecStatus> statuses);
+            @QueryParam("since") Date since, 
+            @QueryParam("statuses") List<ExecStatus> statuses, 
+            @QueryParam("resources") List<String> resources);
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
index afcb042..904491f 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java
@@ -23,6 +23,8 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.stream.Collectors;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.ArrayUtils;
@@ -472,8 +474,13 @@ public class TaskLogic extends AbstractExecutableLogic<TaskTO> {
     }
 
     @PreAuthorize("hasRole('" + IdRepoEntitlement.TASK_DELETE + "')")
-    public List<PropagationTaskTO> purgePropagations(final Date since, final List<ExecStatus> statuses) {
-        return taskDAO.purgePropagations(since, statuses);
+    public List<PropagationTaskTO> purgePropagations(
+            final Date since,
+            final List<ExecStatus> statuses,
+            final List<String> resources) {
+        return taskDAO.purgePropagations(since, statuses, Optional.ofNullable(resources).
+                map(r -> r.stream().map(resourceDAO::find).filter(Objects::nonNull).collect(Collectors.toList()))
+                .orElse(null));
     }
 
     @Override
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
index 9b32cb4..3177cdd 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
@@ -98,11 +98,12 @@ public class TaskServiceImpl extends AbstractExecutableService implements TaskSe
     }
 
     @Override
-    public Response purgePropagations(final Date since, final List<ExecStatus> statuses) {
-        if (since == null && CollectionUtils.isEmpty(statuses)) {
+    public Response purgePropagations(final Date since, final List<ExecStatus> statuses, final List<String> resources) {
+        if (since == null && CollectionUtils.isEmpty(statuses) && CollectionUtils.isEmpty(resources)) {
             return Response.status(Response.Status.PRECONDITION_FAILED).build();
         }
 
-        return Response.ok(logic.purgePropagations(since, statuses)).build();
+        return Response.ok(logic.purgePropagations(since, statuses, resources)).build();
     }
+
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
index 7161479..8cd5f73 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
@@ -76,5 +76,8 @@ public interface TaskDAO extends DAO<Task> {
 
     void deleteAll(ExternalResource resource, TaskType type);
 
-    List<PropagationTaskTO> purgePropagations(Date since, List<ExecStatus> statuses);
+    List<PropagationTaskTO> purgePropagations(
+            Date since, 
+            List<ExecStatus> statuses,
+            List<ExternalResource> externalResources);
 }
diff --git a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
index 698faf4..dbc0d9c 100644
--- a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
@@ -1038,6 +1038,11 @@ under the License.
   <Task DTYPE="PropagationTask" id="316285cc-ae52-4ea2-a33b-7355e189ac3f" operation="DELETE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"type","value":["type"]}]'/>
+  <!--SYNCOPE-1641 to be purged-->
+  <Task DTYPE="PropagationTask" id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" operation="UPDATE"
+        objectClassName="__ACCOUNT__" resource_id="ws-target-resource-1" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
+        attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
+  <TaskExec id="c3290f8b-caf9-4a85-84fb-fb619b65cd49" task_id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
   <Task DTYPE="PullTask" remediation="0" id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" name="CSV (update matching; assign unmatching)" resource_id="resource-csv"
         destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
         pullMode="INCREMENTAL" unmatchingRule="ASSIGN" matchingRule="UPDATE" active="1"
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 c28b6ff..d7d573c 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
@@ -487,7 +487,10 @@ public class JPATaskDAO extends AbstractDAO<Task> implements TaskDAO {
     }
 
     @Override
-    public List<PropagationTaskTO> purgePropagations(final Date since, final List<ExecStatus> statuses) {
+    public List<PropagationTaskTO> purgePropagations(
+            final Date since, 
+            final List<ExecStatus> statuses, 
+            final List<ExternalResource> externalResources) {
         StringBuilder queryString = new StringBuilder("SELECT t.task_id "
                 + "FROM TaskExec t INNER JOIN Task z ON t.task_id=z.id AND z.dtype='PropagationTask' "
                 + "WHERE t.enddate=(SELECT MAX(e.enddate) FROM TaskExec e WHERE e.task_id=t.task_id) ");
@@ -505,6 +508,14 @@ public class JPATaskDAO extends AbstractDAO<Task> implements TaskDAO {
                     }).collect(Collectors.joining(" OR "))).
                     append(")");
         }
+        if (!CollectionUtils.isEmpty(externalResources)) {
+            queryString.append("AND (").
+                    append(externalResources.stream().map(externalResource -> {
+                        queryParameters.add(externalResource.getKey());
+                        return "z.resource_id = ?" + queryParameters.size();
+                    }).collect(Collectors.joining(" OR "))).
+                    append(")");
+        }
 
         Query query = entityManager().createNativeQuery(queryString.toString());
         for (int i = 1; i <= queryParameters.size(); i++) {
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
index d9257fc..04d2470 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
@@ -88,12 +88,12 @@ public class TaskTest extends AbstractTest {
         assertNotNull(tasks);
         assertTrue(tasks.isEmpty());
 
-        assertEquals(5, taskDAO.count(TaskType.PROPAGATION, null, null, null, null));
+        assertEquals(6, taskDAO.count(TaskType.PROPAGATION, null, null, null, null));
     }
 
     @Test
     public void findAll() {
-        assertEquals(5, taskDAO.findAll(TaskType.PROPAGATION).size());
+        assertEquals(6, taskDAO.findAll(TaskType.PROPAGATION).size());
         assertEquals(1, taskDAO.findAll(TaskType.NOTIFICATION).size());
         assertEquals(3, taskDAO.findAll(TaskType.SCHEDULED).size());
         assertEquals(10, taskDAO.findAll(TaskType.PULL).size());
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 7bfcd49..b657243 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -1125,6 +1125,11 @@ under the License.
   <Task DTYPE="PropagationTask" id="316285cc-ae52-4ea2-a33b-7355e189ac3f" operation="DELETE"
         objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
         attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"type","value":["type"]}]'/>
+  <!--SYNCOPE-1641 to be purged-->
+  <Task DTYPE="PropagationTask" id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" operation="UPDATE"
+        objectClassName="__ACCOUNT__" resource_id="ws-target-resource-1" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
+        attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
+  <TaskExec id="c3290f8b-caf9-4a85-84fb-fb619b65cd49" task_id="025c956d-ea88-4bd7-9e44-2f35e0aa7055" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
   <Task DTYPE="PullTask" remediation="0" id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" name="CSV (update matching; assign unmatching)" resource_id="resource-csv"
         destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
         pullMode="INCREMENTAL" unmatchingRule="ASSIGN" matchingRule="UPDATE" active="1"
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index a61a70e..1f26de8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -275,7 +275,7 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
     @Test
     public void purgePropagations() {
         try {
-            taskService.purgePropagations(null, null);
+            taskService.purgePropagations(null, null, null);
             fail();
         } catch (WebServiceException e) {
             assertNotNull(e);
@@ -284,12 +284,29 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
         Calendar oneWeekAgo = Calendar.getInstance();
         oneWeekAgo.add(Calendar.WEEK_OF_YEAR, -1);
         Response response = taskService.purgePropagations(
-                oneWeekAgo.getTime(), Collections.singletonList(ExecStatus.SUCCESS));
+                oneWeekAgo.getTime(), List.of(ExecStatus.SUCCESS),
+                List.of(RESOURCE_NAME_WS1));
         assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
 
         List<PropagationTaskTO> deleted = response.readEntity(new GenericType<List<PropagationTaskTO>>() {
         });
         assertNotNull(deleted);
+        // only ws-target-resource-1 PROPAGATION tasks should have been deleted
+        assertEquals(1, deleted.size());
+        assertTrue(deleted.stream().allMatch(d -> RESOURCE_NAME_WS1.equals(d.getResource())));
+        // check that other propagation tasks haven't been affected
+        assertFalse(taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION)
+                .anyTypeKind(AnyTypeKind.USER)
+                .page(0).size(10)
+                .build()).getResult().isEmpty());
+        // delete all remaining SUCCESS tasks
+        response = taskService.purgePropagations(
+                oneWeekAgo.getTime(), List.of(ExecStatus.SUCCESS), List.of());
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+
+        deleted = response.readEntity(new GenericType<List<PropagationTaskTO>>() {
+        });
+        assertNotNull(deleted);
     }
 
     @Test