You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ex...@apache.org on 2023/02/27 19:17:43 UTC
[nifi] branch support/nifi-1.x updated: NIFI-11134 Added Label auditing to Flow Configuration History
This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch support/nifi-1.x
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/support/nifi-1.x by this push:
new 443ef1d9e2 NIFI-11134 Added Label auditing to Flow Configuration History
443ef1d9e2 is described below
commit 443ef1d9e2494305c4c72453bded84c657711735
Author: Mark Bean <ma...@gmail.com>
AuthorDate: Fri Feb 10 21:09:35 2023 -0500
NIFI-11134 Added Label auditing to Flow Configuration History
This closes #6949
Co-authored-by: David Handermann <ex...@apache.org>
Signed-off-by: David Handermann <ex...@apache.org>
---
.../java/org/apache/nifi/action/Component.java | 3 +-
.../java/org/apache/nifi/audit/LabelAuditor.java | 177 ++++++++++++++++
.../java/org/apache/nifi/audit/SnippetAuditor.java | 28 +++
.../apache/nifi/web/StandardNiFiServiceFacade.java | 3 +
.../src/main/resources/nifi-web-api-context.xml | 6 +
.../org/apache/nifi/audit/TestLabelAuditor.java | 231 +++++++++++++++++++++
6 files changed, 447 insertions(+), 1 deletion(-)
diff --git a/nifi-api/src/main/java/org/apache/nifi/action/Component.java b/nifi-api/src/main/java/org/apache/nifi/action/Component.java
index e9997d5902..77c84a881e 100644
--- a/nifi-api/src/main/java/org/apache/nifi/action/Component.java
+++ b/nifi-api/src/main/java/org/apache/nifi/action/Component.java
@@ -36,5 +36,6 @@ public enum Component {
ParameterProvider,
AccessPolicy,
User,
- UserGroup;
+ UserGroup,
+ Label;
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/LabelAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/LabelAuditor.java
new file mode 100644
index 0000000000..87986f4d37
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/LabelAuditor.java
@@ -0,0 +1,177 @@
+/*
+ * 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.nifi.audit;
+
+import org.apache.nifi.action.Action;
+import org.apache.nifi.action.Component;
+import org.apache.nifi.action.FlowChangeAction;
+import org.apache.nifi.action.Operation;
+import org.apache.nifi.action.details.ActionDetails;
+import org.apache.nifi.action.details.FlowChangeConfigureDetails;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.controller.label.Label;
+import org.apache.nifi.web.api.dto.LabelDTO;
+import org.apache.nifi.web.dao.LabelDAO;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+import java.util.Objects;
+
+@Aspect
+public class LabelAuditor extends NiFiAuditor {
+ private static final Logger logger = LoggerFactory.getLogger(LabelAuditor.class);
+
+ /**
+ * Audits the creation of a Label.
+ *
+ * @param proceedingJoinPoint Join Point observed
+ * @return Label
+ * @throws Throwable Thrown on failure to proceed with target invocation
+ */
+ @Around("within(org.apache.nifi.web.dao.LabelDAO+) && "
+ + "execution(org.apache.nifi.controller.label.Label createLabel(java.lang.String, org.apache.nifi.web.api.dto.LabelDTO))")
+ public Label createLabelAdvice(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
+ final Label label = (Label) proceedingJoinPoint.proceed();
+ final Action action = generateAuditRecord(label, Operation.Add);
+
+ if (action != null) {
+ saveAction(action, logger);
+ }
+
+ return label;
+ }
+
+ /**
+ * Audits the configuration of a Label.
+ *
+ * @param proceedingJoinPoint Join Point observed
+ * @param labelDTO Data Transfer Object
+ * @param labelDAO Data Access Object
+ * @return Label
+ * @throws Throwable Thrown on failure to proceed with target invocation
+ */
+ @Around("within(org.apache.nifi.web.dao.LabelDAO+) && "
+ + "execution(org.apache.nifi.controller.label.Label updateLabel(org.apache.nifi.web.api.dto.LabelDTO)) && "
+ + "args(labelDTO) && "
+ + "target(labelDAO)")
+ public Label updateLabelAdvice(final ProceedingJoinPoint proceedingJoinPoint, final LabelDTO labelDTO, final LabelDAO labelDAO) throws Throwable {
+ // determine the initial content of label
+ final Label label = labelDAO.getLabel(labelDTO.getId());
+ final String originalLabelValue = label.getValue();
+
+ final Label updatedLabel = (Label) proceedingJoinPoint.proceed();
+
+ // ensure the user was found
+ final NiFiUser user = NiFiUserUtils.getNiFiUser();
+ if (user != null) {
+ final String updatedLabelValue = updatedLabel.getValue();
+ if ((originalLabelValue == null && updatedLabelValue != null)
+ || !Objects.equals(originalLabelValue, updatedLabelValue)) {
+ final FlowChangeAction labelAction = new FlowChangeAction();
+ labelAction.setUserIdentity(user.getIdentity());
+ labelAction.setTimestamp(new Date());
+ labelAction.setSourceId(label.getIdentifier());
+ labelAction.setSourceType(Component.Label);
+ labelAction.setOperation(Operation.Configure);
+ // Source Name is a required field for the database but not applicable for a label; use UUID to create a unique name
+ labelAction.setSourceName(label.getIdentifier());
+
+ final FlowChangeConfigureDetails actionDetails = new FlowChangeConfigureDetails();
+ actionDetails.setName(label.getIdentifier());
+ actionDetails.setValue(updatedLabelValue);
+ actionDetails.setPreviousValue(originalLabelValue);
+ labelAction.setActionDetails(actionDetails);
+
+ saveAction(labelAction, logger);
+ }
+ }
+ return updatedLabel;
+ }
+
+ /**
+ * Audits the removal of a Label.
+ *
+ * @param proceedingJoinPoint Join Point observed
+ * @param labelId Label identifier
+ * @param labelDAO Label Data Access Object
+ * @throws Throwable Thrown on failure to proceed with target invocation
+ */
+ @Around("within(org.apache.nifi.web.dao.LabelDAO+) && "
+ + "execution(void deleteLabel(java.lang.String)) && "
+ + "args(labelId) && "
+ + "target(labelDAO)")
+ public void removeLabelAdvice(final ProceedingJoinPoint proceedingJoinPoint, final String labelId, final LabelDAO labelDAO) throws Throwable {
+ // get the label before removing it
+ final Label label = labelDAO.getLabel(labelId);
+
+ // remove the label
+ proceedingJoinPoint.proceed();
+
+ // if no exceptions were thrown, add removal actions...
+ final Action action = generateAuditRecord(label, Operation.Remove);
+
+ if (action != null) {
+ saveAction(action, logger);
+ }
+ }
+
+ /**
+ * Generates an audit record for the creation of the specified label.
+ *
+ * @param label Label audited
+ * @param operation Operation audited
+ * @return Action description
+ */
+ public Action generateAuditRecord(final Label label, final Operation operation) {
+ return generateAuditRecord(label, operation, null);
+ }
+
+ /**
+ * Generates an audit record for the creation of the specified label.
+ *
+ * @param label Label audited
+ * @param operation Operation audited
+ * @param actionDetails Action Details or null when not provided
+ * @return Action description
+ */
+ public Action generateAuditRecord(final Label label, final Operation operation, final ActionDetails actionDetails) {
+ FlowChangeAction action = null;
+
+ final NiFiUser user = NiFiUserUtils.getNiFiUser();
+ if (user != null) {
+ action = new FlowChangeAction();
+ action.setUserIdentity(user.getIdentity());
+ action.setOperation(operation);
+ action.setTimestamp(new Date());
+ action.setSourceId(label.getIdentifier());
+ // Labels do not have a Name; use UUID to provide a unique name
+ action.setSourceName(label.getIdentifier());
+ action.setSourceType(Component.Label);
+
+ if (actionDetails != null) {
+ action.setActionDetails(actionDetails);
+ }
+ }
+
+ return action;
+ }
+}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
index af3d19ba8e..8b47037daf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
@@ -33,6 +33,7 @@ import org.apache.nifi.connectable.Funnel;
import org.apache.nifi.connectable.Port;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.Snippet;
+import org.apache.nifi.controller.label.Label;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.RemoteProcessGroup;
import org.apache.nifi.authorization.user.NiFiUser;
@@ -47,6 +48,7 @@ import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
import org.apache.nifi.web.api.dto.SnippetDTO;
import org.apache.nifi.web.dao.ConnectionDAO;
import org.apache.nifi.web.dao.FunnelDAO;
+import org.apache.nifi.web.dao.LabelDAO;
import org.apache.nifi.web.dao.PortDAO;
import org.apache.nifi.web.dao.ProcessGroupDAO;
import org.apache.nifi.web.dao.ProcessorDAO;
@@ -78,6 +80,7 @@ public class SnippetAuditor extends NiFiAuditor {
private ProcessorDAO processorDAO;
private FunnelDAO funnelDAO;
private ConnectionDAO connectionDAO;
+ private LabelDAO labelDAO;
private PortAuditor portAuditor;
private RemoteProcessGroupAuditor remoteProcessGroupAuditor;
@@ -85,6 +88,7 @@ public class SnippetAuditor extends NiFiAuditor {
private ProcessorAuditor processorAuditor;
private FunnelAuditor funnelAuditor;
private RelationshipAuditor relationshipAuditor;
+ private LabelAuditor labelAuditor;
/**
* Audits copy/paste.
@@ -328,6 +332,14 @@ public class SnippetAuditor extends NiFiAuditor {
}
}
+ for (String id : snippet.getLabels().keySet()) {
+ final Label label = labelDAO.getLabel(id);
+ final Action action = labelAuditor.generateAuditRecord(label, Operation.Move, createMoveDetails(previousGroupId, groupId, logger));
+ if (action != null) {
+ actions.add(action);
+ }
+ }
+
// save the actions
if (CollectionUtils.isNotEmpty(actions)) {
saveActions(actions, logger);
@@ -390,6 +402,11 @@ public class SnippetAuditor extends NiFiAuditor {
connections.add(connectionDAO.getConnection(id));
}
+ final Set<Label> labels = new HashSet<>();
+ for (String id : snippet.getLabels().keySet()) {
+ labels.add(labelDAO.getLabel(id));
+ }
+
// remove the snippet and components
proceedingJoinPoint.proceed();
@@ -446,6 +463,13 @@ public class SnippetAuditor extends NiFiAuditor {
}
}
+ for (Label label : labels) {
+ final Action action = labelAuditor.generateAuditRecord(label, Operation.Remove);
+ if (action != null) {
+ actions.add(action);
+ }
+ }
+
// save the actions
if (CollectionUtils.isNotEmpty(actions)) {
saveActions(actions, logger);
@@ -481,6 +505,10 @@ public class SnippetAuditor extends NiFiAuditor {
this.remoteProcessGroupAuditor = remoteProcessGroupAuditor;
}
+ public void setLabelAuditor(LabelAuditor labelAuditor) {
+ this.labelAuditor = labelAuditor;
+ }
+
public void setRemoteProcessGroupDAO(RemoteProcessGroupDAO remoteProcessGroupDAO) {
this.remoteProcessGroupDAO = remoteProcessGroupDAO;
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index 9547a6fed6..9cb0f94e50 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -5928,6 +5928,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
case UserGroup:
authorizable = authorizableLookup.getTenant();
break;
+ case Label:
+ authorizable = authorizableLookup.getLabel(sourceId);
+ break;
default:
throw new WebApplicationException(Response.serverError().entity("An unexpected type of component is the source of this action.").build());
}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
index 6c38f0c029..bea03aaf49 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
@@ -707,6 +707,11 @@
<property name="auditService" ref="auditService"/>
<property name="processGroupDAO" ref="processGroupDAO"/>
</bean>
+ <bean id="labelAuditor" class="org.apache.nifi.audit.LabelAuditor">
+ <property name="serviceFacade" ref="serviceFacade"/>
+ <property name="auditService" ref="auditService"/>
+ <property name="processGroupDAO" ref="processGroupDAO"/>
+ </bean>
<bean id="snippetAuditor" class="org.apache.nifi.audit.SnippetAuditor">
<property name="serviceFacade" ref="serviceFacade"/>
<property name="auditService" ref="auditService"/>
@@ -723,6 +728,7 @@
<property name="processGroupAuditor" ref="processGroupAuditor"/>
<property name="processorAuditor" ref="processorAuditor"/>
<property name="relationshipAuditor" ref="relationshipAuditor"/>
+ <property name="labelAuditor" ref="labelAuditor"/>
</bean>
<bean id="controllerServiceAuditor" class="org.apache.nifi.audit.ControllerServiceAuditor">
<property name="serviceFacade" ref="serviceFacade"/>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestLabelAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestLabelAuditor.java
new file mode 100644
index 0000000000..d0bc8a845e
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestLabelAuditor.java
@@ -0,0 +1,231 @@
+/*
+ * 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.nifi.audit;
+
+import org.apache.nifi.action.Action;
+import org.apache.nifi.action.Component;
+import org.apache.nifi.action.Operation;
+import org.apache.nifi.action.details.ActionDetails;
+import org.apache.nifi.action.details.FlowChangeConfigureDetails;
+import org.apache.nifi.admin.service.AuditService;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserDetails;
+import org.apache.nifi.authorization.user.StandardNiFiUser;
+import org.apache.nifi.controller.FlowController;
+import org.apache.nifi.controller.flow.FlowManager;
+import org.apache.nifi.controller.label.StandardLabel;
+import org.apache.nifi.groups.ProcessGroup;
+import org.apache.nifi.web.api.dto.LabelDTO;
+import org.apache.nifi.web.dao.ProcessGroupDAO;
+import org.apache.nifi.web.dao.impl.StandardLabelDAO;
+import org.apache.nifi.controller.label.Label;
+import org.apache.nifi.web.dao.impl.StandardProcessGroupDAO;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.when;
+
+@ExtendWith({SpringExtension.class, MockitoExtension.class})
+@ContextConfiguration(classes = {TestLabelAuditor.AuditorConfiguration.class})
+public class TestLabelAuditor {
+
+ private static final String USER_IDENTITY = "username";
+
+ private static final String GROUP_ID = "group-1";
+
+ private static final String LABEL_ID = "label-1";
+
+ private static final String LABEL = "label";
+
+ private static final String UPDATED_LABEL = "updated-label";
+
+ @Mock
+ AuditService auditService;
+
+ @Mock
+ Authentication authentication;
+
+ @Mock
+ FlowController flowController;
+
+ @Mock
+ FlowManager flowManager;
+
+ @Mock
+ ProcessGroup processGroup;
+
+ @Captor
+ ArgumentCaptor<List<Action>> actionsCaptor;
+
+ @Autowired
+ StandardLabelDAO labelDao;
+
+ @Autowired
+ LabelAuditor labelAuditor;
+
+ @BeforeEach
+ void setAuditor() {
+ final SecurityContext securityContext = SecurityContextHolder.getContext();
+ securityContext.setAuthentication(authentication);
+ final NiFiUser user = new StandardNiFiUser.Builder().identity(USER_IDENTITY).build();
+ final NiFiUserDetails userDetail = new NiFiUserDetails(user);
+ when(authentication.getPrincipal()).thenReturn(userDetail);
+
+ when(flowController.getFlowManager()).thenReturn(flowManager);
+ labelDao.setFlowController(flowController);
+ labelAuditor.setAuditService(auditService);
+ }
+
+ @Test
+ void testCreateLabelAdvice() {
+ final LabelDTO labelDto = getLabelDto();
+ when(flowManager.getGroup(eq(GROUP_ID))).thenReturn(processGroup);
+ when(flowManager.createLabel(eq(LABEL_ID), eq(LABEL))).thenReturn(new StandardLabel(LABEL_ID, LABEL));
+
+ final Label label = labelDao.createLabel(GROUP_ID, labelDto);
+
+ assertNotNull(label);
+ verify(auditService).addActions(actionsCaptor.capture());
+ final List<Action> actions = actionsCaptor.getValue();
+ assertActionFound(actions, Operation.Add);
+ }
+
+ @Test
+ void testRemoveLabelAdvice() {
+ setFindLabel();
+
+ labelDao.deleteLabel(LABEL_ID);
+
+ verify(auditService).addActions(actionsCaptor.capture());
+ final List<Action> actions = actionsCaptor.getValue();
+ assertActionFound(actions, Operation.Remove);
+ }
+
+ @Test
+ void testUpdateLabelAdvice() {
+ setFindLabel();
+
+ final LabelDTO labelDto = getLabelDto();
+ labelDto.setLabel(UPDATED_LABEL);
+
+ labelDao.updateLabel(labelDto);
+
+ verify(auditService).addActions(actionsCaptor.capture());
+ final List<Action> actions = actionsCaptor.getValue();
+ final Action action = assertActionFound(actions, Operation.Configure);
+
+ final ActionDetails actionDetails = action.getActionDetails();
+ assertActionDetailsFound(actionDetails);
+ }
+
+ @Test
+ void testUpdateLabelAdviceLabelUnchanged() {
+ setFindLabel();
+
+ final LabelDTO labelDto = getLabelDto();
+
+ labelDao.updateLabel(labelDto);
+
+ verifyNoInteractions(auditService);
+ }
+
+ private void setFindLabel() {
+ when(flowManager.getRootGroup()).thenReturn(processGroup);
+ final Label label = new StandardLabel(LABEL_ID, LABEL);
+ label.setProcessGroup(processGroup);
+ when(processGroup.findLabel(eq(LABEL_ID))).thenReturn(label);
+ }
+
+ private void assertActionDetailsFound(final ActionDetails actionDetails) {
+ assertInstanceOf(FlowChangeConfigureDetails.class, actionDetails);
+ final FlowChangeConfigureDetails flowChangeConfigureDetails = (FlowChangeConfigureDetails) actionDetails;
+
+ assertEquals(LABEL_ID, flowChangeConfigureDetails.getName());
+ assertEquals(LABEL, flowChangeConfigureDetails.getPreviousValue());
+ assertEquals(UPDATED_LABEL, flowChangeConfigureDetails.getValue());
+ }
+
+ private Action assertActionFound(final List<Action> actions, final Operation operation) {
+ assertNotNull(actions);
+
+ final Optional<Action> actionFound = actions.stream().findFirst();
+ assertTrue(actionFound.isPresent());
+
+ final Action action = actionFound.get();
+ assertEquals(USER_IDENTITY, action.getUserIdentity());
+ assertEquals(operation, action.getOperation());
+ assertEquals(LABEL_ID, action.getSourceId());
+ assertEquals(LABEL_ID, action.getSourceName());
+ assertEquals(Component.Label, action.getSourceType());
+ assertNotNull(action.getTimestamp());
+
+ return action;
+ }
+
+ private LabelDTO getLabelDto() {
+ final LabelDTO labelDto = new LabelDTO();
+ labelDto.setLabel(LABEL);
+ labelDto.setId(LABEL_ID);
+ labelDto.setStyle(Collections.emptyMap());
+ return labelDto;
+ }
+
+ @Configuration
+ @EnableAspectJAutoProxy(proxyTargetClass = true)
+ public static class AuditorConfiguration {
+
+ @Bean
+ public LabelAuditor labelAuditor() {
+ return new LabelAuditor();
+ }
+
+ @Bean
+ public StandardLabelDAO labelDAO() {
+ return new StandardLabelDAO();
+ }
+
+ @Bean
+ public ProcessGroupDAO processGroupDAO() {
+ return new StandardProcessGroupDAO();
+ }
+ }
+}