Clearing up interactions across Remediation, Audit and Delegation
diff --git a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java
index 8460a95..ffeab22 100644
--- a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java
+++ b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/RemediationLogic.java
@@ -20,6 +20,7 @@
import java.lang.reflect.Method;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
@@ -46,7 +47,7 @@
import org.springframework.transaction.annotation.Transactional;
@Component
-public class RemediationLogic extends AbstractTransactionalLogic<RemediationTO> {
+public class RemediationLogic extends AbstractLogic<RemediationTO> {
@Autowired
private UserLogic userLogic;
@@ -81,111 +82,80 @@
@PreAuthorize("hasRole('" + IdMEntitlement.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);
- }
+ Remediation remediation = Optional.ofNullable(remediationDAO.find(key)).
+ orElseThrow(() -> new NotFoundException(key));
return binder.getRemediationTO(remediation);
}
@PreAuthorize("hasRole('" + IdMEntitlement.REMEDIATION_DELETE + "')")
+ @Transactional
public void delete(final String key) {
- Remediation remediation = remediationDAO.find(key);
- if (remediation == null) {
- LOG.error("Could not find remediation '" + key + '\'');
+ Optional.ofNullable(remediationDAO.find(key)).
+ orElseThrow(() -> new NotFoundException(key));
- throw new NotFoundException(key);
- }
-
- remediationDAO.delete(remediation);
+ remediationDAO.delete(key);
}
@PreAuthorize("hasRole('" + IdMEntitlement.REMEDIATION_REMEDY + "')")
public ProvisioningResult<?> remedy(final String key, final AnyCR anyCR, 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.getAnyType().getKind()) {
- case USER:
- default:
+ switch (read(key).getAnyType()) {
+ case "USER":
result = userLogic.create((UserCR) anyCR, nullPriorityAsync);
break;
- case GROUP:
+ case "GROUP":
result = groupLogic.create((GroupCR) anyCR, nullPriorityAsync);
break;
- case ANY_OBJECT:
+ default:
result = anyObjectLogic.create((AnyObjectCR) anyCR, nullPriorityAsync);
}
- remediationDAO.delete(remediation);
+ remediationDAO.delete(key);
return result;
}
@PreAuthorize("hasRole('" + IdMEntitlement.REMEDIATION_REMEDY + "')")
public ProvisioningResult<?> remedy(final String key, final AnyUR anyUR, 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.getAnyType().getKind()) {
- case USER:
- default:
+ switch (read(key).getAnyType()) {
+ case "USER":
result = userLogic.update((UserUR) anyUR, nullPriorityAsync);
break;
- case GROUP:
+ case "GROUP":
result = groupLogic.update((GroupUR) anyUR, nullPriorityAsync);
break;
- case ANY_OBJECT:
+ default:
result = anyObjectLogic.update((AnyObjectUR) anyUR, nullPriorityAsync);
}
- remediationDAO.delete(remediation);
+ remediationDAO.delete(key);
return result;
}
@PreAuthorize("hasRole('" + IdMEntitlement.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.getAnyType().getKind()) {
- case USER:
- default:
+ switch (read(key).getAnyType()) {
+ case "USER":
result = userLogic.delete(anyKey, nullPriorityAsync);
break;
- case GROUP:
+ case "GROUP":
result = groupLogic.delete(anyKey, nullPriorityAsync);
break;
- case ANY_OBJECT:
+ default:
result = anyObjectLogic.delete(anyKey, nullPriorityAsync);
}
- remediationDAO.delete(remediation);
+ remediationDAO.delete(key);
return result;
}
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
index 25e0a8a..675f4d3 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
@@ -19,14 +19,11 @@
package org.apache.syncope.core.logic;
import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.core.provisioning.api.AuditManager;
import org.apache.syncope.core.provisioning.api.event.AfterHandlingEvent;
import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
-import org.apache.syncope.core.provisioning.java.job.AfterHandlingJob;
import org.apache.syncope.core.spring.security.AuthContextUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -35,7 +32,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Aspect
public class LogicInvocationHandler {
@@ -48,9 +44,6 @@
@Autowired
private AuditManager auditManager;
- @Autowired
- private SchedulerFactoryBean scheduler;
-
@Around("execution(* org.apache.syncope.core.logic.AbstractLogic+.*(..))")
public Object around(final ProceedingJoinPoint joinPoint) throws Throwable {
Class<?> clazz = joinPoint.getTarget().getClass();
@@ -98,8 +91,7 @@
throw t;
} finally {
if (notificationsAvailable || auditRequested) {
- Map<String, Object> jobMap = new HashMap<>();
- jobMap.put(AfterHandlingEvent.JOBMAP_KEY, new AfterHandlingEvent(
+ AfterHandlingEvent afterHandlingEvent = new AfterHandlingEvent(
AuthContextUtils.getWho(),
AuditElements.EventCategoryType.LOGIC,
category,
@@ -108,8 +100,16 @@
condition,
before,
output,
- input));
- AfterHandlingJob.schedule(scheduler, jobMap);
+ input);
+ AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(), () -> {
+ try {
+ notificationManager.createTasks(afterHandlingEvent);
+ auditManager.audit(afterHandlingEvent);
+ } catch (Throwable t) {
+ LOG.error("While managing Audit and Notifications", t);
+ }
+ return null;
+ });
}
}
}
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
index c0309b3..f8aefa1 100644
--- 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
@@ -29,11 +29,13 @@
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
import org.apache.syncope.core.persistence.jpa.entity.JPARemediation;
import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ReflectionUtils;
@Repository
public class JPARemediationDAO extends AbstractDAO<Remediation> implements RemediationDAO {
+ @Transactional(readOnly = true)
@Override
public Remediation find(final String key) {
return entityManager().find(JPARemediation.class, key);
@@ -122,6 +124,7 @@
entityManager().remove(remediation);
}
+ @Transactional
@Override
public void delete(final String key) {
Remediation remediation = find(key);
@@ -131,5 +134,4 @@
delete(remediation);
}
-
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java
index 4997815..5f8cecc 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/AfterHandlingJob.java
@@ -31,6 +31,7 @@
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
+import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
@@ -53,18 +54,18 @@
@SuppressWarnings("unchecked")
AfterHandlingJob jobInstance = (AfterHandlingJob) ApplicationContextProvider.getBeanFactory().
createBean(AfterHandlingJob.class, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
- String jobName = AfterHandlingJob.class.getName() + SecureRandomUtils.generateRandomUUID();
+ String jobName = AfterHandlingJob.class.getSimpleName() + SecureRandomUtils.generateRandomUUID();
jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
ApplicationContextProvider.getBeanFactory().registerSingleton(jobName, jobInstance);
JobBuilder jobDetailBuilder = JobBuilder.newJob(AfterHandlingJob.class).
- withIdentity(jobName).
+ withIdentity(jobName, Scheduler.DEFAULT_GROUP).
usingJobData(new JobDataMap(jobMap));
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger().
- withIdentity(JobNamer.getTriggerName(jobName)).
+ withIdentity(JobNamer.getTriggerName(jobName), Scheduler.DEFAULT_GROUP).
startNow();
try {
@@ -93,6 +94,8 @@
});
} catch (RuntimeException e) {
throw new JobExecutionException("While handling notification / audit events", e);
+ } finally {
+ ApplicationContextProvider.getBeanFactory().destroySingleton(context.getJobDetail().getKey().getName());
}
}
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
index e9f82fc..49370be 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
@@ -29,6 +29,7 @@
import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
import org.apache.syncope.core.provisioning.api.job.JobManager;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
import org.apache.syncope.core.spring.security.AuthContextUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
@@ -121,6 +122,8 @@
} catch (RuntimeException e) {
LOG.error("While setting memberships", e);
throw new JobExecutionException("While executing memberships", e);
+ } finally {
+ ApplicationContextProvider.getBeanFactory().destroySingleton(context.getJobDetail().getKey().getName());
}
}
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java
index c7b0bea..cdf4483 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SchedulingPullActions.java
@@ -29,6 +29,7 @@
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionException;
+import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
@@ -52,18 +53,18 @@
@SuppressWarnings("unchecked")
T jobInstance = (T) ApplicationContextProvider.getBeanFactory().
createBean(reference, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
- String jobName = getClass().getName() + SecureRandomUtils.generateRandomUUID();
+ String jobName = getClass().getSimpleName() + SecureRandomUtils.generateRandomUUID();
jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain());
ApplicationContextProvider.getBeanFactory().registerSingleton(jobName, jobInstance);
JobBuilder jobDetailBuilder = JobBuilder.newJob(reference).
- withIdentity(jobName).
+ withIdentity(jobName, Scheduler.DEFAULT_GROUP).
usingJobData(new JobDataMap(jobMap));
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger().
- withIdentity(JobNamer.getTriggerName(jobName)).
+ withIdentity(JobNamer.getTriggerName(jobName), Scheduler.DEFAULT_GROUP).
startNow();
try {