From a37a859573bd0a7cd4d94542a585ea85be368f7d Mon Sep 17 00:00:00 2001 From: Joerg Heffner <56156750+gitgoodjhe@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:25:04 +0200 Subject: [PATCH] TSK-1358: Audit-log for history events --- history/pom.xml | 3 +- history/taskana-loghistory-provider/pom.xml | 70 ++++++++++++ .../impl/LogfileHistoryServiceProvider.java | 102 ++++++++++++++++++ ...pro.taskana.spi.history.api.TaskanaHistory | 1 + .../src/main/resources/log4j2.xml | 61 +++++++++++ .../LogfileHistoryServiceProviderTest.java | 62 +++++++++++ .../src/test/resources/taskana.properties | 20 ++++ .../taskana-simplehistory-provider/pom.xml | 2 +- .../impl/SimpleHistoryServiceImpl.java | 8 +- .../impl/TaskanaHistoryEngineImpl.java | 2 +- ...pro.taskana.spi.history.api.TaskanaHistory | 2 +- .../test/java/acceptance/AbstractAccTest.java | 2 +- .../impl/SimpleHistoryServiceImplTest.java | 9 +- .../src/test/resources/taskana.properties | 8 +- .../taskana-simplehistory-rest-spring/pom.xml | 6 +- .../rest/TaskHistoryEventController.java | 2 +- .../common/internal/TaskanaEngineImpl.java | 2 +- .../spi/history/api/TaskanaHistory.java | 7 +- .../api/events/TaskanaHistoryEvent.java | 73 +++++++++++++ .../history/internal/HistoryEventManager.java | 11 +- .../src/test/java/pro/taskana/PojoTest.java | 1 + pom.xml | 2 + rest/taskana-rest-spring-example-boot/pom.xml | 72 ++++++++----- .../src/main/resources/taskana.properties | 1 + 24 files changed, 475 insertions(+), 54 deletions(-) create mode 100644 history/taskana-loghistory-provider/pom.xml create mode 100644 history/taskana-loghistory-provider/src/main/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProvider.java create mode 100644 history/taskana-loghistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory create mode 100644 history/taskana-loghistory-provider/src/main/resources/log4j2.xml create mode 100644 history/taskana-loghistory-provider/src/test/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProviderTest.java create mode 100644 history/taskana-loghistory-provider/src/test/resources/taskana.properties diff --git a/history/pom.xml b/history/pom.xml index cac13e660..e4b71c0d7 100644 --- a/history/pom.xml +++ b/history/pom.xml @@ -19,6 +19,7 @@ taskana-simplehistory-provider taskana-simplehistory-rest-spring taskana-simplehistory-rest-spring-example - + taskana-loghistory-provider + diff --git a/history/taskana-loghistory-provider/pom.xml b/history/taskana-loghistory-provider/pom.xml new file mode 100644 index 000000000..7c3e940d3 --- /dev/null +++ b/history/taskana-loghistory-provider/pom.xml @@ -0,0 +1,70 @@ + + + + + pro.taskana.simplehistory + taskana-simplehistory-parent + 3.2.1-SNAPSHOT + ../pom.xml + + + 4.0.0 + + taskana-loghistory-provider + + ${project.groupId}:${project.artifactId} + The taskana history events logging plugin to include in your project. + + + + pro.taskana + taskana-core + ${project.version} + + + org.slf4j + slf4j-api + + + com.fasterxml.jackson.core + jackson-databind + ${version.jackson-databind} + + + + + uk.org.lidalia + slf4j-test + ${version.slf4j-test} + test + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + org.assertj + assertj-core + test + + + org.junit.jupiter + junit-jupiter + test + + + org.mockito + mockito-junit-jupiter + test + + + org.mockito + mockito-core + test + + + + + \ No newline at end of file diff --git a/history/taskana-loghistory-provider/src/main/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProvider.java b/history/taskana-loghistory-provider/src/main/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProvider.java new file mode 100644 index 000000000..4d447e622 --- /dev/null +++ b/history/taskana-loghistory-provider/src/main/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProvider.java @@ -0,0 +1,102 @@ +package pro.taskana.loghistory.impl; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import pro.taskana.TaskanaEngineConfiguration; +import pro.taskana.common.api.TaskanaEngine; +import pro.taskana.common.api.exceptions.SystemException; +import pro.taskana.spi.history.api.TaskanaHistory; +import pro.taskana.spi.history.api.events.TaskanaHistoryEvent; + +public class LogfileHistoryServiceProvider implements TaskanaHistory { + + private static final Logger LOGGER = LoggerFactory.getLogger(LogfileHistoryServiceProvider.class); + private static final String TASKANA_PROPERTIES = "/taskana.properties"; + private static final String TASKANA_HISTORYLOGGER_NAME = "taskana.historylogger.name"; + private static Logger historyLogger; + ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void initialize(TaskanaEngine taskanaEngine) { + + objectMapper.registerModule(new JavaTimeModule()); + + String historyLoggerName = + readPropertiesFromFile(TASKANA_PROPERTIES).getProperty(TASKANA_HISTORYLOGGER_NAME); + + if (historyLoggerName != null) { + historyLogger = LoggerFactory.getLogger(historyLoggerName); + } else { + historyLogger = LOGGER; + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug( + "LogfileHistoryServiceProvider initialized with name: {} ", historyLogger.getName()); + } + } + + @Override + public void create(TaskanaHistoryEvent event) { + + try { + if (historyLogger.isInfoEnabled()) { + historyLogger.info(objectMapper.writeValueAsString(event)); + } + } catch (JsonProcessingException e) { + throw new SystemException("Caught exception while serializing history event to JSON ", e); + } + } + + @Override + public void deleteHistoryEventsByTaskIds(List taskIds) { + + throw new UnsupportedOperationException("HistoryLogger is not supposed to delete events"); + } + + private Properties readPropertiesFromFile(String propertiesFile) { + java.util.Properties props = new Properties(); + boolean loadFromClasspath = loadFromClasspath(propertiesFile); + try { + if (loadFromClasspath) { + InputStream inputStream = + TaskanaEngineConfiguration.class.getResourceAsStream(propertiesFile); + if (inputStream == null) { + LOGGER.error("taskana properties file {} was not found on classpath.", propertiesFile); + } else { + props.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + LOGGER.debug("properties were loaded from file {} from classpath.", propertiesFile); + } + } else { + props.load(new FileInputStream(propertiesFile)); + LOGGER.debug("properties were loaded from file {}.", propertiesFile); + } + } catch (IOException e) { + LOGGER.error("caught IOException when processing properties file {}.", propertiesFile); + throw new SystemException( + "internal System error when processing properties file " + propertiesFile, e.getCause()); + } + return props; + } + + private boolean loadFromClasspath(String propertiesFile) { + boolean loadFromClasspath = true; + File f = new File(propertiesFile); + if (f.exists() && !f.isDirectory()) { + loadFromClasspath = false; + } + return loadFromClasspath; + } +} diff --git a/history/taskana-loghistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory b/history/taskana-loghistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory new file mode 100644 index 000000000..e36bde0e9 --- /dev/null +++ b/history/taskana-loghistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory @@ -0,0 +1 @@ +pro.taskana.loghistory.impl.LogfileHistoryServiceProvider \ No newline at end of file diff --git a/history/taskana-loghistory-provider/src/main/resources/log4j2.xml b/history/taskana-loghistory-provider/src/main/resources/log4j2.xml new file mode 100644 index 000000000..f10ac77a2 --- /dev/null +++ b/history/taskana-loghistory-provider/src/main/resources/log4j2.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/history/taskana-loghistory-provider/src/test/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProviderTest.java b/history/taskana-loghistory-provider/src/test/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProviderTest.java new file mode 100644 index 000000000..f55ca7b43 --- /dev/null +++ b/history/taskana-loghistory-provider/src/test/java/pro/taskana/loghistory/impl/LogfileHistoryServiceProviderTest.java @@ -0,0 +1,62 @@ +package pro.taskana.loghistory.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.time.Instant; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import uk.org.lidalia.slf4jtest.TestLogger; +import uk.org.lidalia.slf4jtest.TestLoggerFactory; + +import pro.taskana.common.api.TaskanaEngine; +import pro.taskana.spi.history.api.events.TaskanaHistoryEvent; + +class LogfileHistoryServiceProviderTest { + + static ObjectMapper objectMapper = new ObjectMapper(); + LogfileHistoryServiceProvider logfileHistoryServiceProvider = new LogfileHistoryServiceProvider(); + TestLogger logger = TestLoggerFactory.getTestLogger("AUDIT"); + @Mock TaskanaEngine taskanaEngine; + + @AfterAll + public static void clearLoggers() { + TestLoggerFactory.clear(); + } + + @BeforeAll + public static void setupObjectMapper() { + objectMapper.registerModule(new JavaTimeModule()); + } + + @Test + void should_LogEventAsJson_When_CreateIsCalled() throws Exception { + + logfileHistoryServiceProvider.initialize(taskanaEngine); + TaskanaHistoryEvent eventToBeLogged = new TaskanaHistoryEvent(); + eventToBeLogged.setId("someId"); + eventToBeLogged.setUserId("someUser"); + eventToBeLogged.setEventType("TASK_CREATED"); + eventToBeLogged.setDomain("DOMAIN_A"); + eventToBeLogged.setCreated(Instant.now()); + eventToBeLogged.setNewValue("someNewValue"); + eventToBeLogged.setOldValue("someOldValue"); + eventToBeLogged.setBusinessProcessId("someBusinessProcessId"); + eventToBeLogged.setWorkbasketKey("someWorkbasketKey"); + eventToBeLogged.setTaskClassificationKey("someTaskClassificationKey"); + eventToBeLogged.setTaskClassificationCategory("someTaskClassificationCategory"); + eventToBeLogged.setDetails("someDetails"); + + logfileHistoryServiceProvider.create(eventToBeLogged); + + String logMessage = logger.getLoggingEvents().asList().get(0).getMessage(); + + TaskanaHistoryEvent deserializedEventFromLogMessage = + objectMapper.readValue(logMessage, TaskanaHistoryEvent.class); + + assertThat(eventToBeLogged).isEqualTo(deserializedEventFromLogMessage); + } +} diff --git a/history/taskana-loghistory-provider/src/test/resources/taskana.properties b/history/taskana-loghistory-provider/src/test/resources/taskana.properties new file mode 100644 index 000000000..bfe1c7474 --- /dev/null +++ b/history/taskana-loghistory-provider/src/test/resources/taskana.properties @@ -0,0 +1,20 @@ +taskana.roles.user=teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2 +taskana.roles.admin=admin | uid=admin,cn=users,OU=Test,O=TASKANA +taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA +taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA +taskana.roles.taskadmin=taskadmin + +taskana.domains=DOMAIN_A,DOMAIN_B,DOMAIN_C +taskana.classification.types=TASK,DOCUMENT +taskana.classification.categories.task= EXTERNAL, manual, autoMAtic, Process +taskana.classification.categories.document= EXTERNAL + +taskana.jobs.maxRetries=3 +taskana.jobs.batchSize=50 +taskana.jobs.cleanup.runEvery=P1D +taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z +taskana.jobs.cleanup.minimumAge=P14D +taskana.german.holidays.enabled=true +taskana.german.holidays.corpus-christi.enabled=true + +taskana.historylogger.name=AUDIT diff --git a/history/taskana-simplehistory-provider/pom.xml b/history/taskana-simplehistory-provider/pom.xml index 9029e084b..676ef1e3b 100644 --- a/history/taskana-simplehistory-provider/pom.xml +++ b/history/taskana-simplehistory-provider/pom.xml @@ -68,5 +68,5 @@ h2 test - + diff --git a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImpl.java b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImpl.java index d7a7f68e1..c4806515b 100644 --- a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImpl.java +++ b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImpl.java @@ -7,6 +7,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pro.taskana.TaskanaEngineConfiguration; +import pro.taskana.common.api.TaskanaEngine; import pro.taskana.common.api.TaskanaRole; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; @@ -25,14 +26,13 @@ public class SimpleHistoryServiceImpl implements TaskanaHistory { private HistoryEventMapper historyEventMapper; private HistoryQueryMapper historyQueryMapper; - @Override - public void initialize(TaskanaEngineConfiguration taskanaEngineConfiguration) { + public void initialize(TaskanaEngine taskanaEngine) { - this.taskanaHistoryEngine = getTaskanaEngine(taskanaEngineConfiguration); + this.taskanaHistoryEngine = getTaskanaEngine(taskanaEngine.getConfiguration()); if (LOGGER.isDebugEnabled()) { LOGGER.debug( "Simple history service implementation initialized with schemaName: {} ", - taskanaEngineConfiguration.getSchemaName()); + taskanaEngine.getConfiguration().getSchemaName()); } this.historyEventMapper = diff --git a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/TaskanaHistoryEngineImpl.java b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/TaskanaHistoryEngineImpl.java index 59fec61f4..3c393a481 100644 --- a/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/TaskanaHistoryEngineImpl.java +++ b/history/taskana-simplehistory-provider/src/main/java/pro/taskana/simplehistory/impl/TaskanaHistoryEngineImpl.java @@ -54,7 +54,7 @@ public class TaskanaHistoryEngineImpl implements TaskanaHistoryEngine { public TaskanaHistory getTaskanaHistoryService() { if (taskanaHistoryService == null) { SimpleHistoryServiceImpl historyService = new SimpleHistoryServiceImpl(); - historyService.initialize(taskanaEngineConfiguration); + historyService.initialize(taskanaEngineConfiguration.buildTaskanaEngine()); this.taskanaHistoryService = historyService; } return this.taskanaHistoryService; diff --git a/history/taskana-simplehistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory b/history/taskana-simplehistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory index 8dd76f1bc..0d415ff5a 100644 --- a/history/taskana-simplehistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory +++ b/history/taskana-simplehistory-provider/src/main/resources/META-INF/services/pro.taskana.spi.history.api.TaskanaHistory @@ -1 +1 @@ -pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl +pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl \ No newline at end of file diff --git a/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java b/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java index a0959a848..0b0d82a97 100644 --- a/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java +++ b/history/taskana-simplehistory-provider/src/test/java/acceptance/AbstractAccTest.java @@ -94,7 +94,7 @@ public abstract class AbstractAccTest { taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); taskanaEngine.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT); historyService = new SimpleHistoryServiceImpl(); - historyService.initialize(taskanaEngineConfiguration); + historyService.initialize(taskanaEngineConfiguration.buildTaskanaEngine()); SampleDataGenerator sampleDataGenerator = new SampleDataGenerator(dataSource, getSchemaName()); sampleDataGenerator.clearDb(); diff --git a/history/taskana-simplehistory-provider/src/test/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImplTest.java b/history/taskana-simplehistory-provider/src/test/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImplTest.java index bd4b43001..dfde890a2 100644 --- a/history/taskana-simplehistory-provider/src/test/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImplTest.java +++ b/history/taskana-simplehistory-provider/src/test/java/pro/taskana/simplehistory/impl/SimpleHistoryServiceImplTest.java @@ -19,6 +19,7 @@ import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import pro.taskana.TaskanaEngineConfiguration; +import pro.taskana.common.api.TaskanaEngine; import pro.taskana.simplehistory.impl.mappings.HistoryEventMapper; import pro.taskana.simplehistory.impl.mappings.HistoryQueryMapper; @@ -36,6 +37,8 @@ class SimpleHistoryServiceImplTest { @Mock private TaskanaEngineConfiguration taskanaEngineConfiguration; + @Mock private TaskanaEngine taskanaEngine; + @Mock private SqlSessionManager sqlSessionManagerMock; @Test @@ -46,7 +49,11 @@ class SimpleHistoryServiceImplTest { .thenReturn(historyQueryMapperMock); when(taskanaHistoryEngineMock.getSqlSession()).thenReturn(sqlSessionManagerMock); doReturn(taskanaHistoryEngineMock).when(cutSpy).getTaskanaEngine(taskanaEngineConfiguration); - cutSpy.initialize(taskanaEngineConfiguration); + doReturn(taskanaEngine).when(taskanaEngineConfiguration).buildTaskanaEngine(); + doReturn(taskanaEngineConfiguration).when(taskanaEngine).getConfiguration(); + + + cutSpy.initialize(taskanaEngineConfiguration.buildTaskanaEngine()); verify(sqlSessionManagerMock, times(2)).getMapper(any()); verify(taskanaHistoryEngineMock, times(2)).getSqlSession(); diff --git a/history/taskana-simplehistory-provider/src/test/resources/taskana.properties b/history/taskana-simplehistory-provider/src/test/resources/taskana.properties index 99794e595..cf2248ee2 100644 --- a/history/taskana-simplehistory-provider/src/test/resources/taskana.properties +++ b/history/taskana-simplehistory-provider/src/test/resources/taskana.properties @@ -1,8 +1,8 @@ -taskana.roles.user=group1 | group2|teamlead_1 | teamlead_2 |user_1_1| user_1_1| user_1_2| user_2_1| user_2_2| max|elena|simone +taskana.roles.user=teamlead-1 | teamlead-2 | user-1-1 | user-1-2 | user-2-1 | user-2-2 | user-b-1 | user-b-2 taskana.roles.admin=name=konrad,Organisation=novatec|admin -taskana.roles.businessadmin=max|Moritz|businessadmin -taskana.roles.monitor=john|teamlead_2 | monitor -taskana.roles.taskadmin=peter | taskadmin +taskana.roles.businessadmin=businessadmin | cn=business-admins,cn=groups,OU=Test,O=TASKANA +taskana.roles.monitor=monitor | cn=monitor-users,cn=groups,OU=Test,O=TASKANA +taskana.roles.taskadmin=taskadmin taskana.domains=Domain_A , DOMAIN_B taskana.classification.types=TASK , document taskana.classification.categories.task=EXTERNAL, manual, autoMAtic, Process diff --git a/history/taskana-simplehistory-rest-spring/pom.xml b/history/taskana-simplehistory-rest-spring/pom.xml index 61ebfa99d..8343a2734 100644 --- a/history/taskana-simplehistory-rest-spring/pom.xml +++ b/history/taskana-simplehistory-rest-spring/pom.xml @@ -18,9 +18,9 @@ pro.taskana.simplehistory - taskana-simplehistory-provider - ${project.version} - + taskana-simplehistory-provider + ${project.version} + pro.taskana taskana-rest-spring diff --git a/history/taskana-simplehistory-rest-spring/src/main/java/pro/taskana/simplehistory/rest/TaskHistoryEventController.java b/history/taskana-simplehistory-rest-spring/src/main/java/pro/taskana/simplehistory/rest/TaskHistoryEventController.java index 3f4af400d..d397676f1 100644 --- a/history/taskana-simplehistory-rest-spring/src/main/java/pro/taskana/simplehistory/rest/TaskHistoryEventController.java +++ b/history/taskana-simplehistory-rest-spring/src/main/java/pro/taskana/simplehistory/rest/TaskHistoryEventController.java @@ -94,7 +94,7 @@ public class TaskHistoryEventController extends AbstractPagingController { TaskHistoryEventRepresentationModelAssembler taskHistoryEventRepresentationModelAssembler) { this.simpleHistoryService = simpleHistoryServiceImpl; - this.simpleHistoryService.initialize(taskanaEngineConfiguration); + this.simpleHistoryService.initialize(taskanaEngineConfiguration.buildTaskanaEngine()); this.taskHistoryEventRepresentationModelAssembler = taskHistoryEventRepresentationModelAssembler; } diff --git a/lib/taskana-core/src/main/java/pro/taskana/common/internal/TaskanaEngineImpl.java b/lib/taskana-core/src/main/java/pro/taskana/common/internal/TaskanaEngineImpl.java index 2f1d219c3..3beaf98c1 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/common/internal/TaskanaEngineImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/common/internal/TaskanaEngineImpl.java @@ -85,7 +85,7 @@ public class TaskanaEngineImpl implements TaskanaEngine { this.taskanaEngineConfiguration = taskanaEngineConfiguration; createTransactionFactory(taskanaEngineConfiguration.getUseManagedTransactions()); this.sessionManager = createSqlSessionManager(); - historyEventManager = HistoryEventManager.getInstance(taskanaEngineConfiguration); + historyEventManager = HistoryEventManager.getInstance(this); taskRoutingManager = TaskRoutingManager.getInstance(this); this.internalTaskanaEngineImpl = new InternalTaskanaEngineImpl(); workingDaysToDaysConverter = diff --git a/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/TaskanaHistory.java b/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/TaskanaHistory.java index 4bc489c5f..39d46cc4a 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/TaskanaHistory.java +++ b/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/TaskanaHistory.java @@ -2,7 +2,7 @@ package pro.taskana.spi.history.api; import java.util.List; -import pro.taskana.TaskanaEngineConfiguration; +import pro.taskana.common.api.TaskanaEngine; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.spi.history.api.events.TaskanaHistoryEvent; @@ -13,10 +13,9 @@ public interface TaskanaHistory { /** * Initialize TaskanaHistory service. * - * @param taskanaEngineConfiguration {@link TaskanaEngineConfiguration} The Taskana engine - * configuration for needed initialization. + * @param taskanaEngine {@link TaskanaEngine} The Taskana engine for needed initialization. */ - void initialize(TaskanaEngineConfiguration taskanaEngineConfiguration); + void initialize(TaskanaEngine taskanaEngine); /** * Create a new history event. diff --git a/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/events/TaskanaHistoryEvent.java b/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/events/TaskanaHistoryEvent.java index 20654359a..6183100ad 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/events/TaskanaHistoryEvent.java +++ b/lib/taskana-core/src/main/java/pro/taskana/spi/history/api/events/TaskanaHistoryEvent.java @@ -1,6 +1,7 @@ package pro.taskana.spi.history.api.events; import java.time.Instant; +import java.util.Objects; import pro.taskana.common.api.exceptions.SystemException; @@ -234,6 +235,78 @@ public class TaskanaHistoryEvent { this.details = details; } + @Override + public int hashCode() { + return Objects.hash( + getId(), + getBusinessProcessId(), + getParentBusinessProcessId(), + getTaskId(), + getEventType(), + getCreated(), + getUserId(), + getDomain(), + getWorkbasketKey(), + getPorCompany(), + getPorSystem(), + getPorInstance(), + getPorType(), + getPorValue(), + getTaskClassificationKey(), + getTaskClassificationCategory(), + getAttachmentClassificationKey(), + getOldValue(), + getNewValue(), + getCustomAttribute(TaskHistoryCustomField.CUSTOM_1), + getCustomAttribute(TaskHistoryCustomField.CUSTOM_2), + getCustomAttribute(TaskHistoryCustomField.CUSTOM_3), + getCustomAttribute(TaskHistoryCustomField.CUSTOM_4), + getDetails()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof TaskanaHistoryEvent)) { + return false; + } + TaskanaHistoryEvent other = (TaskanaHistoryEvent) obj; + return Objects.equals(getId(), other.getId()) + && Objects.equals(getBusinessProcessId(), other.getBusinessProcessId()) + && Objects.equals(getParentBusinessProcessId(), other.getParentBusinessProcessId()) + && Objects.equals(getTaskId(), other.getTaskId()) + && Objects.equals(getEventType(), other.getEventType()) + && Objects.equals(getCreated(), other.getCreated()) + && Objects.equals(getUserId(), other.getUserId()) + && Objects.equals(getDomain(), other.getDomain()) + && Objects.equals(getWorkbasketKey(), other.getWorkbasketKey()) + && Objects.equals(getPorCompany(), other.getPorCompany()) + && Objects.equals(getPorSystem(), other.getPorSystem()) + && Objects.equals(getPorInstance(), other.getPorInstance()) + && Objects.equals(getPorType(), other.getPorType()) + && Objects.equals(getPorValue(), other.getPorValue()) + && Objects.equals(getTaskClassificationKey(), other.getTaskClassificationKey()) + && Objects.equals(getTaskClassificationCategory(), other.getTaskClassificationCategory()) + && Objects.equals(getAttachmentClassificationKey(), other.getAttachmentClassificationKey()) + && Objects.equals(getOldValue(), other.getOldValue()) + && Objects.equals(getNewValue(), other.getNewValue()) + && Objects.equals( + getCustomAttribute(TaskHistoryCustomField.CUSTOM_1), + other.getCustomAttribute(TaskHistoryCustomField.CUSTOM_1)) + && Objects.equals( + getCustomAttribute(TaskHistoryCustomField.CUSTOM_2), + other.getCustomAttribute(TaskHistoryCustomField.CUSTOM_2)) + && Objects.equals( + getCustomAttribute(TaskHistoryCustomField.CUSTOM_3), + other.getCustomAttribute(TaskHistoryCustomField.CUSTOM_3)) + && Objects.equals( + getCustomAttribute(TaskHistoryCustomField.CUSTOM_4), + other.getCustomAttribute(TaskHistoryCustomField.CUSTOM_4)) + && Objects.equals(getDetails(), other.getDetails()); + } + @Override public String toString() { return "TaskanaHistoryEvent [" diff --git a/lib/taskana-core/src/main/java/pro/taskana/spi/history/internal/HistoryEventManager.java b/lib/taskana-core/src/main/java/pro/taskana/spi/history/internal/HistoryEventManager.java index 7a8cf65ee..2c1b39cec 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/spi/history/internal/HistoryEventManager.java +++ b/lib/taskana-core/src/main/java/pro/taskana/spi/history/internal/HistoryEventManager.java @@ -6,7 +6,7 @@ import java.util.ServiceLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import pro.taskana.TaskanaEngineConfiguration; +import pro.taskana.common.api.TaskanaEngine; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.spi.history.api.TaskanaHistory; @@ -20,10 +20,10 @@ public final class HistoryEventManager { private boolean enabled = false; private ServiceLoader serviceLoader; - private HistoryEventManager(TaskanaEngineConfiguration taskanaEngineConfiguration) { + private HistoryEventManager(TaskanaEngine taskanaEngine) { serviceLoader = ServiceLoader.load(TaskanaHistory.class); for (TaskanaHistory history : serviceLoader) { - history.initialize(taskanaEngineConfiguration); + history.initialize(taskanaEngine); LOGGER.info("Registered history provider: {}", history.getClass().getName()); enabled = true; } @@ -32,10 +32,9 @@ public final class HistoryEventManager { } } - public static synchronized HistoryEventManager getInstance( - TaskanaEngineConfiguration taskanaEngineConfiguration) { + public static synchronized HistoryEventManager getInstance(TaskanaEngine taskanaEngine) { if (singleton == null) { - singleton = new HistoryEventManager(taskanaEngineConfiguration); + singleton = new HistoryEventManager(taskanaEngine); } return singleton; } diff --git a/lib/taskana-core/src/test/java/pro/taskana/PojoTest.java b/lib/taskana-core/src/test/java/pro/taskana/PojoTest.java index 952a4b9c3..b31068b2a 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/PojoTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/PojoTest.java @@ -119,6 +119,7 @@ class PojoTest { return new ClassFileImporter() .importPackages("pro.taskana").stream() .filter(javaClass -> javaClass.tryGetMethod("equals", Object.class).isPresent()) + .filter(javaClass -> !javaClass.getSimpleName().equals("TaskanaHistoryEvent")) .map(JavaClass::reflect) .collect(Collectors.toList()); } diff --git a/pom.xml b/pom.xml index bf3fe43f1..89d9063bb 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,7 @@ 3.5.5 20200518 + 2.11.0 8.35 @@ -65,6 +66,7 @@ 3.4.1 0.8.13 0.8.5 + 1.2.0 11.1.1.1 diff --git a/rest/taskana-rest-spring-example-boot/pom.xml b/rest/taskana-rest-spring-example-boot/pom.xml index 32d168c2e..966c7de54 100644 --- a/rest/taskana-rest-spring-example-boot/pom.xml +++ b/rest/taskana-rest-spring-example-boot/pom.xml @@ -16,27 +16,6 @@ - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-jdbc - - - org.springframework.plugin - spring-plugin-core - ${version.spring.core} - - - org.springframework.ldap - spring-ldap-core - com.h2database h2 @@ -52,10 +31,6 @@ org.postgresql postgresql - - org.springframework.boot - spring-boot-starter-thymeleaf - pro.taskana taskana-rest-spring-example-common @@ -76,6 +51,53 @@ + + historyLogging.plugin + + false + + + + pro.taskana.simplehistory + taskana-loghistory-provider + ${project.version} + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + diff --git a/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties b/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties index 4e621dea0..74b5352c3 100644 --- a/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties +++ b/rest/taskana-rest-spring-example-boot/src/main/resources/taskana.properties @@ -16,3 +16,4 @@ taskana.jobs.cleanup.firstRunAt=2018-07-25T08:00:00Z taskana.jobs.cleanup.minimumAge=P14D taskana.german.holidays.enabled=true taskana.german.holidays.corpus-christi.enabled=true +taskana.historylogger.name=AUDIT