TSK-1737: created ConfigurationService which manages custom attributes

This commit is contained in:
Mustapha Zorgati 2021-09-29 09:58:48 +02:00
parent 4ae94ff108
commit 05fce27222
31 changed files with 607 additions and 169 deletions

View File

@ -44,7 +44,6 @@ public class DbSchemaCreator {
private DataSource dataSource;
public DbSchemaCreator(DataSource dataSource, String schema) {
super();
this.dataSource = dataSource;
this.schemaName = schema;
}

View File

@ -1,98 +0,0 @@
package pro.taskana.common.internal.configuration;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.jdbc.SqlRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.common.api.exceptions.SystemException;
public class SecurityVerifier {
public static final String SECURITY_FLAG_COLUMN_NAME = "ENFORCE_SECURITY";
public static final String INSERT_SECURITY_FLAG_SQL =
"INSERT INTO %s.CONFIGURATION (" + SECURITY_FLAG_COLUMN_NAME + " ) VALUES (%b)";
public static final String SELECT_SECURITY_FLAG_SQL = "SELECT %s FROM %s.CONFIGURATION";
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityVerifier.class);
private final String schemaName;
private final DataSource dataSource;
public SecurityVerifier(DataSource dataSource, String schema) {
this.dataSource = dataSource;
this.schemaName = schema;
}
public void checkSecureAccess(boolean securityEnabled) {
try (Connection connection = dataSource.getConnection()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(connection.getMetaData().toString());
}
SqlRunner sqlRunner = new SqlRunner(connection);
String querySecurity =
String.format(SELECT_SECURITY_FLAG_SQL, SECURITY_FLAG_COLUMN_NAME, schemaName);
if ((boolean) sqlRunner.selectOne(querySecurity).get(SECURITY_FLAG_COLUMN_NAME)
&& !securityEnabled) {
LOGGER.error("Tried to start TASKANA in unsecured mode while secured mode is enforced!");
throw new SystemException(
"Secured TASKANA mode is enforced, can't start in unsecured mode");
}
} catch (SQLException ex) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
String.format(
"Security-mode is not yet set. Setting security flag to %b", securityEnabled));
}
setInitialSecurityMode(securityEnabled);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Security-mode is enabled");
}
}
private void setInitialSecurityMode(boolean securityEnabled) {
try (Connection connection = dataSource.getConnection()) {
String setSecurityFlagSql =
String.format(INSERT_SECURITY_FLAG_SQL, schemaName, securityEnabled);
try (PreparedStatement preparedStatement = connection.prepareStatement(setSecurityFlagSql)) {
preparedStatement.execute();
if (!connection.getAutoCommit()) {
connection.commit();
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Successfully set security-mode to %b", securityEnabled));
}
} catch (SQLException ex) {
LOGGER.error(
"Caught exception while trying to set the initial TASKANA security mode. "
+ "Aborting start-up process!",
ex);
throw new SystemException(
"Couldn't set initial TASKANA security mode. Aborting start-up process!");
}
} catch (SQLException ex) {
LOGGER.error("Caught exception while trying to retrieve connection from datasource ", ex);
}
}
}

View File

@ -0,0 +1,19 @@
package pro.taskana.common.internal.util;
import pro.taskana.common.api.exceptions.SystemException;
@FunctionalInterface
public interface CheckedRunnable {
static Runnable wrap(CheckedRunnable checkedRunnable) {
return () -> {
try {
checkedRunnable.run();
} catch (Exception e) {
throw new SystemException("Caught exception", e);
}
};
}
void run() throws Exception;
}

View File

@ -0,0 +1,28 @@
package pro.taskana.common.internal.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
public class ResourceUtil {
private ResourceUtil() {
throw new IllegalStateException("utility class");
}
public static String readResourceAsString(Class<?> clazz, String resource) throws IOException {
try (InputStream fileStream = clazz.getResourceAsStream(resource)) {
if (fileStream == null) {
return null;
}
try (Reader inputStreamReader = new InputStreamReader(fileStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(inputStreamReader)) {
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
}
}
}
}

View File

@ -2,7 +2,7 @@ CREATE SCHEMA IF NOT EXISTS %schemaName%;
SET SCHEMA %schemaName%;
-- MOved to h2 jdbc connect string, because of taskana-spring-example project is using two schemas.
-- Moved to h2 jdbc connect string, because of taskana-spring-example project is using two schemas.
-- There the order of the schema setup's (dbcustom, taskana) should be switched then we can set collation
-- here in this file!
-- SET COLLATION DEFAULT_de_DE;

View File

@ -0,0 +1,22 @@
package pro.taskana.common.internal.util;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
public class ResourceUtilTest {
@Test
void should_loadResource() throws Exception {
String resourceAsString = ResourceUtil.readResourceAsString(getClass(), "fileInClasspath.txt");
assertThat(resourceAsString).isEqualTo("This file is in the classpath");
}
@Test
void should_ReturnNull_When_ResourceDoesNotExist() throws Exception {
String resourceAsString = ResourceUtil.readResourceAsString(getClass(), "doesNotExist");
assertThat(resourceAsString).isNull();
}
}

View File

@ -115,11 +115,12 @@ public abstract class AbstractAccTest {
dataSource,
false,
schemaName != null && !schemaName.isEmpty() ? schemaName : getSchemaName());
taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine();
taskanaEngine.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT);
taskanaEngine =
taskanaEngineConfiguration.buildTaskanaEngine(ConnectionManagementMode.AUTOCOMMIT);
taskanaHistoryEngine = TaskanaHistoryEngineImpl.createTaskanaEngine(taskanaEngine);
historyService = new SimpleHistoryServiceImpl();
historyService.initialize(taskanaEngineConfiguration.buildTaskanaEngine());
historyService.initialize(
taskanaEngineConfiguration.buildTaskanaEngine(ConnectionManagementMode.AUTOCOMMIT));
SampleDataGenerator sampleDataGenerator = new SampleDataGenerator(dataSource, getSchemaName());
sampleDataGenerator.clearDb();

View File

@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
import pro.taskana.common.api.CustomHoliday;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.TaskanaEngine.ConnectionManagementMode;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.api.exceptions.WrongCustomHolidayFormatException;
@ -211,6 +212,11 @@ public class TaskanaEngineConfiguration {
return TaskanaEngineImpl.createTaskanaEngine(this);
}
public TaskanaEngine buildTaskanaEngine(ConnectionManagementMode connectionManagementMode)
throws SQLException {
return TaskanaEngineImpl.createTaskanaEngine(this, connectionManagementMode);
}
/**
* This method creates a PooledDataSource, if the needed properties are provided.
*

View File

@ -0,0 +1,13 @@
package pro.taskana.common.api;
import java.util.Map;
import java.util.Optional;
public interface ConfigurationService {
Map<String, Object> getAllCustomAttributes();
void setAllCustomAttributes(Map<String, ?> customAttributes);
Optional<Object> getValue(String attribute);
}

View File

@ -52,6 +52,8 @@ public interface TaskanaEngine {
UserService getUserService();
ConfigurationService getConfigurationService();
/**
* The Taskana configuration.
*

View File

@ -0,0 +1,22 @@
package pro.taskana.common.internal;
import java.util.Map;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface ConfigurationMapper {
@Select("SELECT ENFORCE_SECURITY FROM CONFIGURATION")
Boolean isSecurityEnabled();
@Insert("INSERT INTO CONFIGURATION(ENFORCE_SECURITY) VALUES (#{securityEnabled})")
void setSecurityEnabled(@Param("securityEnabled") boolean securityEnabled);
@Select("SELECT CUSTOM_ATTRIBUTES FROM TASKANA.CONFIGURATION")
Map<String, Object> getAllCustomAttributes();
@Update("UPDATE TASKANA.CONFIGURATION SET CUSTOM_ATTRIBUTES = #{customAttributes}")
void setAllCustomAttributes(@Param("customAttributes") Map<String, ?> customAttributes);
}

View File

@ -0,0 +1,81 @@
package pro.taskana.common.internal;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.common.api.ConfigurationService;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.util.CheckedRunnable;
import pro.taskana.common.internal.util.ResourceUtil;
public class ConfigurationServiceImpl implements ConfigurationService {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationServiceImpl.class);
private final InternalTaskanaEngine internalTaskanaEngine;
private final ConfigurationMapper mapper;
public ConfigurationServiceImpl(
InternalTaskanaEngine internalTaskanaEngine, ConfigurationMapper mapper) {
this.internalTaskanaEngine = internalTaskanaEngine;
this.mapper = mapper;
}
public void checkSecureAccess(boolean securityEnabled) {
Boolean isSecurityEnabled =
internalTaskanaEngine.executeInDatabaseConnection(mapper::isSecurityEnabled);
if (isSecurityEnabled == null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Security-mode is not yet set. Setting security flag to {}", securityEnabled);
}
mapper.setSecurityEnabled(securityEnabled);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Successfully set security mode to {}", securityEnabled);
}
} else if (isSecurityEnabled && !securityEnabled) {
LOGGER.error("Tried to start TASKANA in unsecured mode while secured mode is enforced!");
throw new SystemException("Secured TASKANA mode is enforced, can't start in unsecured mode");
}
}
public void setupDefaultCustomAttributes() {
internalTaskanaEngine.executeInDatabaseConnection(
CheckedRunnable.wrap(
() -> {
if (mapper.getAllCustomAttributes() == null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("custom attributes are not set. Setting default value");
}
setAllCustomAttributes(generateDefaultCustomAttributes());
}
}));
}
@Override
public Map<String, Object> getAllCustomAttributes() {
return internalTaskanaEngine.executeInDatabaseConnection(mapper::getAllCustomAttributes);
}
@Override
public void setAllCustomAttributes(Map<String, ?> customAttributes) {
internalTaskanaEngine.executeInDatabaseConnection(
() -> mapper.setAllCustomAttributes(customAttributes));
}
@Override
public Optional<Object> getValue(String attribute) {
return Optional.ofNullable(getAllCustomAttributes().get(attribute));
}
private Map<String, Object> generateDefaultCustomAttributes() throws IOException {
JSONObject jsonObject =
new JSONObject(
ResourceUtil.readResourceAsString(getClass(), "defaultCustomAttributes.json"));
return jsonObject.toMap();
}
}

View File

@ -17,7 +17,7 @@ import pro.taskana.spi.task.internal.CreateTaskPreprocessorManager;
public interface InternalTaskanaEngine {
/**
* Opens the connection to the database. Has to be called at the begin of each Api call that
* Opens the connection to the database. Has to be called at the beginning of each Api call that
* accesses the database
*/
void openConnection();

View File

@ -30,6 +30,7 @@ import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.internal.ClassificationMapper;
import pro.taskana.classification.internal.ClassificationQueryMapper;
import pro.taskana.classification.internal.ClassificationServiceImpl;
import pro.taskana.common.api.ConfigurationService;
import pro.taskana.common.api.JobService;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.TaskanaRole;
@ -43,7 +44,6 @@ import pro.taskana.common.api.security.CurrentUserContext;
import pro.taskana.common.api.security.UserPrincipal;
import pro.taskana.common.internal.configuration.DB;
import pro.taskana.common.internal.configuration.DbSchemaCreator;
import pro.taskana.common.internal.configuration.SecurityVerifier;
import pro.taskana.common.internal.persistence.InstantTypeHandler;
import pro.taskana.common.internal.persistence.MapTypeHandler;
import pro.taskana.common.internal.security.CurrentUserContextImpl;
@ -85,19 +85,20 @@ public class TaskanaEngineImpl implements TaskanaEngine {
private final WorkingDaysToDaysConverter workingDaysToDaysConverter;
private final HistoryEventManager historyEventManager;
private final CurrentUserContext currentUserContext;
private final ConfigurationServiceImpl configurationService;
protected TaskanaEngineConfiguration taskanaEngineConfiguration;
protected TransactionFactory transactionFactory;
protected SqlSessionManager sessionManager;
protected ConnectionManagementMode mode = ConnectionManagementMode.PARTICIPATE;
protected Connection connection = null;
protected ConnectionManagementMode mode;
protected Connection connection;
protected TaskanaEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration)
protected TaskanaEngineImpl(
TaskanaEngineConfiguration taskanaEngineConfiguration,
ConnectionManagementMode connectionManagementMode)
throws SQLException {
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
createTransactionFactory(taskanaEngineConfiguration.getUseManagedTransactions());
this.sessionManager = createSqlSessionManager();
initializeDbSchema(taskanaEngineConfiguration);
this.internalTaskanaEngineImpl = new InternalTaskanaEngineImpl();
this.mode = connectionManagementMode;
internalTaskanaEngineImpl = new InternalTaskanaEngineImpl();
workingDaysToDaysConverter =
new WorkingDaysToDaysConverter(
taskanaEngineConfiguration.isGermanPublicHolidaysEnabled(),
@ -105,18 +106,31 @@ public class TaskanaEngineImpl implements TaskanaEngine {
taskanaEngineConfiguration.getCustomHolidays());
currentUserContext =
new CurrentUserContextImpl(TaskanaEngineConfiguration.shouldUseLowerCaseForAccessIds());
createTransactionFactory(taskanaEngineConfiguration.getUseManagedTransactions());
sessionManager = createSqlSessionManager();
configurationService =
new ConfigurationServiceImpl(
internalTaskanaEngineImpl, sessionManager.getMapper(ConfigurationMapper.class));
initializeDbSchema(taskanaEngineConfiguration);
// IMPORTANT: SPI has to be initialized last (and in this order) in order
// to provide a fully initialized TaskanaEngine instance during the SPI initialization!
historyEventManager = new HistoryEventManager(this);
taskRoutingManager = new TaskRoutingManager(this);
priorityServiceManager = new PriorityServiceManager();
createTaskPreprocessorManager = new CreateTaskPreprocessorManager();
historyEventManager = new HistoryEventManager(this);
taskRoutingManager = new TaskRoutingManager(this);
}
public static TaskanaEngine createTaskanaEngine(
TaskanaEngineConfiguration taskanaEngineConfiguration) throws SQLException {
return new TaskanaEngineImpl(taskanaEngineConfiguration);
return createTaskanaEngine(taskanaEngineConfiguration, ConnectionManagementMode.PARTICIPATE);
}
public static TaskanaEngine createTaskanaEngine(
TaskanaEngineConfiguration taskanaEngineConfiguration,
ConnectionManagementMode connectionManagementMode)
throws SQLException {
return new TaskanaEngineImpl(taskanaEngineConfiguration, connectionManagementMode);
}
@Override
@ -171,6 +185,11 @@ public class TaskanaEngineImpl implements TaskanaEngine {
internalTaskanaEngineImpl, sessionManager.getMapper(UserMapper.class));
}
@Override
public ConfigurationService getConfigurationService() {
return configurationService;
}
@Override
public TaskanaEngineConfiguration getConfiguration() {
return this.taskanaEngineConfiguration;
@ -330,6 +349,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
configuration.addMapper(AttachmentMapper.class);
configuration.addMapper(JobMapper.class);
configuration.addMapper(UserMapper.class);
configuration.addMapper(ConfigurationMapper.class);
SqlSessionFactory localSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
return SqlSessionManager.newInstance(localSessionFactory);
}
@ -346,9 +366,8 @@ public class TaskanaEngineImpl implements TaskanaEngine {
"The Database Schema Version doesn't match the expected minimal version "
+ MINIMAL_TASKANA_SCHEMA_VERSION);
}
new SecurityVerifier(
taskanaEngineConfiguration.getDatasource(), taskanaEngineConfiguration.getSchemaName())
.checkSecureAccess(taskanaEngineConfiguration.isSecurityEnabled());
configurationService.checkSecureAccess(taskanaEngineConfiguration.isSecurityEnabled());
configurationService.setupDefaultCustomAttributes();
}
/**

View File

@ -0,0 +1,106 @@
{
"nameHighPrio": "High Prio",
"nameMediumPrio": "Medium P",
"nameLowPrio": "Low Prio",
"intervalHighPrio": [
100,
200
],
"intervalMediumPrio": [
21,
100
],
"intervalLowPrio": [
1,
20
],
"colorHighPrio": "#ff0000",
"colorLowPrio": "#5FAD00",
"colorMediumPrio": "#FFEE00",
"filter": {
"Filter": {
"custom-1": [
"true"
],
"custom-5": [
"3"
]
},
"Filter neu": {
"custom-5": [
"7",
"5"
]
},
"Filter Doppelt": {
"custom-5": [
"1",
"2",
"90"
]
}
},
"schema": {
"Priority-Report": {
"displayName": "Priority Report",
"members": {
"nameHighPrio": {
"displayName": "High Prio Name",
"type": "text",
"min": 1
},
"nameMediumPrio": {
"displayName": "Medium Prio Name",
"type": "text",
"min": 1,
"max": 8
},
"nameLowPrio": {
"displayName": "Low Prio Name",
"type": "text",
"min": 2,
"max": 64
},
"intervalHighPrio": {
"displayName": "High Prio Interval",
"type": "interval",
"min": 0,
"max": 300
},
"intervalMediumPrio": {
"displayName": "Medium Prio Interval",
"type": "interval",
"min": -5,
"max": 300
},
"intervalLowPrio": {
"displayName": "Low Prio Interval",
"type": "interval",
"min": 0
},
"colorHighPrio": {
"displayName": "High Prio Color",
"type": "color"
},
"colorMediumPrio": {
"displayName": "Medium Prio Color",
"type": "color"
},
"colorLowPrio": {
"displayName": "Low Prio Color",
"type": "color"
}
}
},
"Filter": {
"displayName": "Filter for Task-Priority-Report",
"members": {
"filter": {
"displayName": "Filter values",
"type": "json",
"min": 1
}
}
}
}
}

View File

@ -56,8 +56,8 @@ public abstract class AbstractAccTest {
if (dropTables) {
sampleDataGenerator.dropDb();
}
taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine();
taskanaEngine.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT);
taskanaEngine =
taskanaEngineConfiguration.buildTaskanaEngine(ConnectionManagementMode.AUTOCOMMIT);
converter = taskanaEngine.getWorkingDaysToDaysConverter();
sampleDataGenerator.clearDb();
sampleDataGenerator.generateTestData();

View File

@ -0,0 +1,90 @@
package acceptance.config;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Map;
import java.util.Optional;
import org.json.JSONObject;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import testapi.TaskanaInject;
import testapi.TaskanaIntegrationTest;
import pro.taskana.common.internal.ConfigurationMapper;
import pro.taskana.common.internal.ConfigurationServiceImpl;
import pro.taskana.common.internal.util.ResourceUtil;
@TaskanaIntegrationTest
public class ConfigurationServiceImplAccTest {
@TaskanaInject ConfigurationServiceImpl configurationService;
@TaskanaInject ConfigurationMapper configurationMapper;
@Nested
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@TestInstance(Lifecycle.PER_CLASS)
class CustomAttribute {
@Test
@Order(1)
void
should_SetDefaultCustomAttributesDuringTaskanaInitialization_When_NoCustomAttributesAreSet()
throws Exception {
Map<String, Object> expectedCustomAttributes =
new JSONObject(
ResourceUtil.readResourceAsString(
ConfigurationServiceImpl.class, "defaultCustomAttributes.json"))
.toMap();
Map<String, Object> allCustomAttributes = configurationMapper.getAllCustomAttributes();
assertThat(allCustomAttributes).isEqualTo(expectedCustomAttributes);
}
@Test
void should_NotSetDefaultCustomAttributes_When_CustomAttributesAreAlreadySet() {
Map<String, String> foo = Map.of("foo", "bar");
configurationService.setAllCustomAttributes(foo);
configurationService.setupDefaultCustomAttributes();
Map<String, Object> allCustomAttributes = configurationService.getAllCustomAttributes();
assertThat(allCustomAttributes).isEqualTo(foo);
}
@Test
void should_SetCustomAttributes() {
Map<String, String> foo = Map.of("foo1", "bar");
configurationService.setAllCustomAttributes(foo);
Map<String, Object> allCustomAttributes = configurationService.getAllCustomAttributes();
assertThat(allCustomAttributes).isEqualTo(foo);
}
@Test
void should_RetrieveCustomAttributes() {
Map<String, String> foo = Map.of("foo2", "bar");
configurationService.setAllCustomAttributes(foo);
Optional<Object> customAttribute = configurationService.getValue("foo2");
assertThat(customAttribute).hasValue("bar");
}
@Test
void should_ReturnNull_When_CustomAttributeDoesNotExist() {
Map<String, String> foo = Map.of("foo3", "bar");
configurationService.setAllCustomAttributes(foo);
Optional<Object> customAttribute = configurationService.getValue("doesNotExist");
assertThat(customAttribute).isEmpty();
}
}
}

View File

@ -15,7 +15,6 @@ import org.junit.jupiter.api.Test;
import pro.taskana.TaskanaEngineConfiguration;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.configuration.DbSchemaCreator;
import pro.taskana.common.internal.configuration.SecurityVerifier;
import pro.taskana.common.test.config.DataSourceGenerator;
import pro.taskana.sampledata.SampleDataGenerator;
@ -89,9 +88,7 @@ class TaskanaSecurityConfigAccTest {
String selectSecurityFlagSql =
String.format(
SecurityVerifier.SELECT_SECURITY_FLAG_SQL,
SecurityVerifier.SECURITY_FLAG_COLUMN_NAME,
DataSourceGenerator.getSchemaName());
"SELECT ENFORCE_SECURITY FROM %s.CONFIGURATION", DataSourceGenerator.getSchemaName());
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(selectSecurityFlagSql);
@ -110,9 +107,8 @@ class TaskanaSecurityConfigAccTest {
String sql =
String.format(
SecurityVerifier.INSERT_SECURITY_FLAG_SQL,
DataSourceGenerator.getSchemaName(),
securityFlag);
"INSERT INTO %s.CONFIGURATION (ENFORCE_SECURITY) VALUES (%b)",
DataSourceGenerator.getSchemaName(), securityFlag);
Statement statement = connection.createStatement();
statement.execute(sql);

View File

@ -8,6 +8,7 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import javax.sql.DataSource;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.internal.stubbing.answers.CallsRealMethods;
@ -23,6 +24,7 @@ import pro.taskana.common.internal.jobs.PlainJavaTransactionProvider;
import pro.taskana.common.test.config.DataSourceGenerator;
import pro.taskana.task.internal.jobs.TaskCleanupJob;
@Disabled
class JobRunnerAccTest extends AbstractAccTest {
private final JobServiceImpl jobService = (JobServiceImpl) taskanaEngine.getJobService();
@ -38,8 +40,8 @@ class JobRunnerAccTest extends AbstractAccTest {
runInThread(
() -> {
try {
TaskanaEngine taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine();
taskanaEngine.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT);
TaskanaEngine taskanaEngine =
taskanaEngineConfiguration.buildTaskanaEngine(ConnectionManagementMode.AUTOCOMMIT);
DataSource dataSource = DataSourceGenerator.getDataSource();
// We have to slow down the transaction.
// This is necessary to guarantee the execution of

View File

@ -4,8 +4,10 @@ import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated;
import static testapi.util.ExtensionCommunicator.getClassLevelStore;
import static testapi.util.ExtensionCommunicator.isTopLevelClass;
import acceptance.TaskanaEngineProxy;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
@ -20,11 +22,15 @@ import testapi.util.ServiceProviderExtractor;
import pro.taskana.TaskanaEngineConfiguration;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.internal.ClassificationServiceImpl;
import pro.taskana.common.api.ConfigurationService;
import pro.taskana.common.api.JobService;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.TaskanaEngine.ConnectionManagementMode;
import pro.taskana.common.api.WorkingDaysToDaysConverter;
import pro.taskana.common.api.security.CurrentUserContext;
import pro.taskana.common.internal.ConfigurationMapper;
import pro.taskana.common.internal.ConfigurationServiceImpl;
import pro.taskana.common.internal.InternalTaskanaEngine;
import pro.taskana.common.internal.JobServiceImpl;
import pro.taskana.common.internal.TaskanaEngineImpl;
import pro.taskana.common.internal.security.CurrentUserContextImpl;
@ -64,9 +70,9 @@ public class TaskanaInitializationExtension implements TestInstancePostProcessor
.forEach(
(spi, serviceProviders) ->
staticMock.when(() -> SpiLoader.load(spi)).thenReturn(serviceProviders));
taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine();
taskanaEngine =
taskanaEngineConfiguration.buildTaskanaEngine(ConnectionManagementMode.AUTOCOMMIT);
}
taskanaEngine.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT);
store.put(STORE_TASKANA_ENTITY_MAP, generateTaskanaEntityMap(taskanaEngine));
}
@ -85,17 +91,21 @@ public class TaskanaInitializationExtension implements TestInstancePostProcessor
return new TaskanaEngineConfiguration(dataSource, false, schemaName);
}
private static Map<Class<?>, Object> generateTaskanaEntityMap(TaskanaEngine taskanaEngine) {
private static Map<Class<?>, Object> generateTaskanaEntityMap(TaskanaEngine taskanaEngine)
throws Exception {
TaskService taskService = taskanaEngine.getTaskService();
TaskanaEngineProxy taskanaEngineProxy = new TaskanaEngineProxy(taskanaEngine);
MonitorService monitorService = taskanaEngine.getMonitorService();
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
ClassificationService classificationService = taskanaEngine.getClassificationService();
JobService jobService = taskanaEngine.getJobService();
CurrentUserContext currentUserContext = taskanaEngine.getCurrentUserContext();
SqlSession sqlSession = taskanaEngineProxy.getSqlSession();
return Map.ofEntries(
Map.entry(TaskanaEngineConfiguration.class, taskanaEngine.getConfiguration()),
Map.entry(TaskanaEngineImpl.class, taskanaEngine),
Map.entry(TaskanaEngine.class, taskanaEngine),
Map.entry(InternalTaskanaEngine.class, taskanaEngineProxy.getEngine()),
Map.entry(TaskService.class, taskService),
Map.entry(TaskServiceImpl.class, taskService),
Map.entry(MonitorService.class, monitorService),
@ -104,10 +114,13 @@ public class TaskanaInitializationExtension implements TestInstancePostProcessor
Map.entry(WorkbasketServiceImpl.class, workbasketService),
Map.entry(ClassificationService.class, classificationService),
Map.entry(ClassificationServiceImpl.class, classificationService),
Map.entry(ConfigurationService.class, taskanaEngine.getConfigurationService()),
Map.entry(ConfigurationServiceImpl.class, taskanaEngine.getConfigurationService()),
Map.entry(JobService.class, jobService),
Map.entry(JobServiceImpl.class, jobService),
Map.entry(CurrentUserContext.class, currentUserContext),
Map.entry(CurrentUserContextImpl.class, currentUserContext),
Map.entry(WorkingDaysToDaysConverter.class, taskanaEngine.getWorkingDaysToDaysConverter()));
Map.entry(WorkingDaysToDaysConverter.class, taskanaEngine.getWorkingDaysToDaysConverter()),
Map.entry(ConfigurationMapper.class, sqlSession.getMapper(ConfigurationMapper.class)));
}
}

View File

@ -9,10 +9,14 @@ import testapi.TaskanaIntegrationTest;
import pro.taskana.TaskanaEngineConfiguration;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.internal.ClassificationServiceImpl;
import pro.taskana.common.api.ConfigurationService;
import pro.taskana.common.api.JobService;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.WorkingDaysToDaysConverter;
import pro.taskana.common.api.security.CurrentUserContext;
import pro.taskana.common.internal.ConfigurationMapper;
import pro.taskana.common.internal.ConfigurationServiceImpl;
import pro.taskana.common.internal.InternalTaskanaEngine;
import pro.taskana.common.internal.JobServiceImpl;
import pro.taskana.common.internal.TaskanaEngineImpl;
import pro.taskana.common.internal.security.CurrentUserContextImpl;
@ -31,6 +35,7 @@ class TaskanaDependencyInjectionExtensionTest {
@TaskanaInject TaskanaEngine taskanaEngine;
@TaskanaInject TaskanaEngine taskanaEngine2;
@TaskanaInject TaskanaEngineImpl taskanaEngineImpl;
@TaskanaInject InternalTaskanaEngine internalTaskanaEngine;
@TaskanaInject ClassificationService classificationService;
@TaskanaInject ClassificationServiceImpl classificationServiceImpl;
@TaskanaInject WorkbasketService workbasketService;
@ -41,9 +46,12 @@ class TaskanaDependencyInjectionExtensionTest {
@TaskanaInject MonitorServiceImpl monitorServiceImpl;
@TaskanaInject JobService jobService;
@TaskanaInject JobServiceImpl jobServiceImpl;
@TaskanaInject ConfigurationService configurationService;
@TaskanaInject ConfigurationServiceImpl configurationServiceImpl;
@TaskanaInject WorkingDaysToDaysConverter workingDaysToDaysConverter;
@TaskanaInject CurrentUserContext currentUserContext;
@TaskanaInject CurrentUserContextImpl currentUserContextImpl;
@TaskanaInject ConfigurationMapper configurationMapper;
@Test
void should_NotInjectTaskanaEngineConfiguration_When_FieldIsNotAnnotated() {
@ -73,6 +81,12 @@ class TaskanaDependencyInjectionExtensionTest {
assertThat(taskanaEngineImpl).isSameAs(this.taskanaEngineImpl).isNotNull();
}
@Test
void should_InjectInternalTaskanaEngine_When_FieldIsAnnotatedOrDeclaredAsParameter(
InternalTaskanaEngine internalTaskanaEngine) {
assertThat(internalTaskanaEngine).isSameAs(this.internalTaskanaEngine).isNotNull();
}
@Test
void should_InjectClassificationService_When_FieldIsAnnotatedOrDeclaredAsParameter(
ClassificationService classificationService) {
@ -132,6 +146,18 @@ class TaskanaDependencyInjectionExtensionTest {
assertThat(jobServiceImpl).isSameAs(this.jobServiceImpl).isNotNull();
}
@Test
void should_InjectConfigurationService_When_FieldIsAnnotatedOrDeclaredAsParameter(
ConfigurationService configurationService) {
assertThat(configurationService).isSameAs(this.configurationService).isNotNull();
}
@Test
void should_InjectConfigurationServiceImpl_When_FieldIsAnnotatedOrDeclaredAsParameter(
ConfigurationServiceImpl configurationServiceImpl) {
assertThat(configurationServiceImpl).isSameAs(this.configurationServiceImpl).isNotNull();
}
@Test
void should_InjectWorkingDaysToDaysConverter_When_FieldIsAnnotatedOrDeclaredAsParameter(
WorkingDaysToDaysConverter workingDaysToDaysConverter) {
@ -149,4 +175,10 @@ class TaskanaDependencyInjectionExtensionTest {
CurrentUserContextImpl currentUserContextImpl) {
assertThat(currentUserContextImpl).isSameAs(this.currentUserContextImpl).isNotNull();
}
@Test
void should_InjectConfigurationMapper_When_FieldIsAnnotatedOrDeclaredAsParameter(
ConfigurationMapper configurationMapper) {
assertThat(configurationMapper).isSameAs(this.configurationMapper).isNotNull();
}
}

View File

@ -28,10 +28,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>pro.taskana</groupId>
<artifactId>taskana-spring</artifactId>
@ -44,6 +41,17 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>

View File

@ -4,6 +4,7 @@ import java.sql.SQLException;
import javax.sql.DataSource;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.TaskanaEngine.ConnectionManagementMode;
import pro.taskana.common.internal.SpringTaskanaEngineImpl;
/** This class configures the TaskanaEngineConfiguration for spring. */
@ -41,7 +42,7 @@ public class SpringTaskanaEngineConfiguration extends TaskanaEngineConfiguration
@Override
public TaskanaEngine buildTaskanaEngine() throws SQLException {
this.useManagedTransactions = true;
return new SpringTaskanaEngineImpl(this);
return new SpringTaskanaEngineImpl(this, ConnectionManagementMode.PARTICIPATE);
}
public void setDataSource(DataSource dataSource) {

View File

@ -9,9 +9,10 @@ import pro.taskana.SpringTaskanaEngineConfiguration;
/** This class configures the TaskanaEngine for spring. */
public class SpringTaskanaEngineImpl extends TaskanaEngineImpl {
public SpringTaskanaEngineImpl(SpringTaskanaEngineConfiguration taskanaEngineConfiguration)
public SpringTaskanaEngineImpl(
SpringTaskanaEngineConfiguration taskanaEngineConfiguration, ConnectionManagementMode mode)
throws SQLException {
super(taskanaEngineConfiguration);
super(taskanaEngineConfiguration, mode);
}
@PostConstruct

View File

@ -1,16 +1,13 @@
package pro.taskana.example.rest.controllers;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.stream.Collectors;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import pro.taskana.common.internal.util.ResourceUtil;
@Controller
public class ResourcesController {
@ -32,14 +29,10 @@ public class ResourcesController {
// }
private String readResourceAsString(String resource) throws IOException {
try (InputStream fileStream = getClass().getResourceAsStream(resource)) {
if (fileStream == null) {
return "{}";
}
try (Reader inputStreamReader = new InputStreamReader(fileStream);
BufferedReader reader = new BufferedReader(inputStreamReader)) {
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
}
String resourceAsString = ResourceUtil.readResourceAsString(getClass(), resource);
if (resourceAsString == null) {
return "{}";
}
return resourceAsString;
}
}

View File

@ -15,7 +15,9 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import pro.taskana.SpringTaskanaEngineConfiguration;
import pro.taskana.TaskanaEngineConfiguration;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.common.api.ConfigurationService;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.security.CurrentUserContext;
import pro.taskana.monitor.api.MonitorService;
import pro.taskana.task.api.TaskService;
import pro.taskana.user.api.UserService;
@ -58,6 +60,16 @@ public class RestConfiguration {
return taskanaEngine.getUserService();
}
@Bean
public ConfigurationService configurationService(TaskanaEngine taskanaEngine) {
return taskanaEngine.getConfigurationService();
}
@Bean
public CurrentUserContext currentUserContext(TaskanaEngine taskanaEngine) {
return taskanaEngine.getCurrentUserContext();
}
@Bean
@ConditionalOnMissingBean(TaskanaEngine.class)
public TaskanaEngine getTaskanaEngine(TaskanaEngineConfiguration taskanaEngineConfiguration)

View File

@ -14,6 +14,7 @@ public final class RestEndpoints {
public static final String URL_CLASSIFICATION_CATEGORIES_BY_TYPES =
API_V1 + "classifications-by-type";
public static final String URL_HISTORY_ENABLED = API_V1 + "history-provider-enabled";
public static final String URL_CUSTOM_ATTRIBUTES = API_V1 + "/config/custom-attributes";
// access id endpoints
public static final String URL_ACCESS_ID = API_V1 + "access-ids";

View File

@ -2,15 +2,21 @@ package pro.taskana.common.rest;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import pro.taskana.TaskanaEngineConfiguration;
import pro.taskana.common.api.ConfigurationService;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.security.CurrentUserContext;
import pro.taskana.common.rest.models.CustomAttributesRepresentationModel;
import pro.taskana.common.rest.models.TaskanaUserInfoRepresentationModel;
import pro.taskana.common.rest.models.VersionRepresentationModel;
@ -20,13 +26,20 @@ import pro.taskana.common.rest.models.VersionRepresentationModel;
public class TaskanaEngineController {
private final TaskanaEngineConfiguration taskanaEngineConfiguration;
private final TaskanaEngine taskanaEngine;
private final CurrentUserContext currentUserContext;
private final ConfigurationService configurationService;
@Autowired
TaskanaEngineController(
TaskanaEngineConfiguration taskanaEngineConfiguration, TaskanaEngine taskanaEngine) {
TaskanaEngineConfiguration taskanaEngineConfiguration,
TaskanaEngine taskanaEngine,
CurrentUserContext currentUserContext,
ConfigurationService configurationService) {
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
this.taskanaEngine = taskanaEngine;
this.currentUserContext = currentUserContext;
this.configurationService = configurationService;
}
/**
@ -35,6 +48,7 @@ public class TaskanaEngineController {
* @return An array with the domain-names as strings
*/
@GetMapping(path = RestEndpoints.URL_DOMAIN)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<String>> getDomains() {
return ResponseEntity.ok(taskanaEngineConfiguration.getDomains());
}
@ -48,6 +62,7 @@ public class TaskanaEngineController {
* @return the classification categories for the requested type.
*/
@GetMapping(path = RestEndpoints.URL_CLASSIFICATION_CATEGORIES)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<String>> getClassificationCategories(
@RequestParam(required = false) String type) {
if (type != null) {
@ -62,6 +77,7 @@ public class TaskanaEngineController {
* @return the configured classification types.
*/
@GetMapping(path = RestEndpoints.URL_CLASSIFICATION_TYPES)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<String>> getClassificationTypes() {
return ResponseEntity.ok(taskanaEngineConfiguration.getClassificationTypes());
}
@ -73,6 +89,7 @@ public class TaskanaEngineController {
* @return the configured classification categories
*/
@GetMapping(path = RestEndpoints.URL_CLASSIFICATION_CATEGORIES_BY_TYPES)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<Map<String, List<String>>> getClassificationCategoriesByTypeMap() {
return ResponseEntity.ok(taskanaEngineConfiguration.getClassificationCategoriesByTypeMap());
}
@ -83,15 +100,14 @@ public class TaskanaEngineController {
* @return the information of the current user.
*/
@GetMapping(path = RestEndpoints.URL_CURRENT_USER)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<TaskanaUserInfoRepresentationModel> getCurrentUserInfo() {
TaskanaUserInfoRepresentationModel resource = new TaskanaUserInfoRepresentationModel();
resource.setUserId(taskanaEngine.getCurrentUserContext().getUserid());
resource.setGroupIds(taskanaEngine.getCurrentUserContext().getGroupIds());
for (TaskanaRole role : taskanaEngineConfiguration.getRoleMap().keySet()) {
if (taskanaEngine.isUserInRole(role)) {
resource.getRoles().add(role);
}
}
resource.setUserId(currentUserContext.getUserid());
resource.setGroupIds(currentUserContext.getGroupIds());
taskanaEngineConfiguration.getRoleMap().keySet().stream()
.filter(taskanaEngine::isUserInRole)
.forEach(resource.getRoles()::add);
return ResponseEntity.ok(resource);
}
@ -101,16 +117,33 @@ public class TaskanaEngineController {
* @return true, when the history is enabled, otherwise false
*/
@GetMapping(path = RestEndpoints.URL_HISTORY_ENABLED)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<Boolean> getIsHistoryProviderEnabled() {
return ResponseEntity.ok(taskanaEngine.isHistoryEnabled());
}
@GetMapping(path = RestEndpoints.URL_CUSTOM_ATTRIBUTES)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<CustomAttributesRepresentationModel> getCustomAttributes() {
Map<String, Object> allCustomAttributes = configurationService.getAllCustomAttributes();
return ResponseEntity.ok(new CustomAttributesRepresentationModel(allCustomAttributes));
}
@PutMapping(path = RestEndpoints.URL_CUSTOM_ATTRIBUTES)
@Transactional(rollbackFor = Exception.class)
public ResponseEntity<CustomAttributesRepresentationModel> setCustomAttributes(
@RequestBody CustomAttributesRepresentationModel customAttributes) {
configurationService.setAllCustomAttributes(customAttributes.getCustomAttributes());
return ResponseEntity.ok(customAttributes);
}
/**
* Get the current application version.
*
* @return The current version.
*/
@GetMapping(path = RestEndpoints.URL_VERSION)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<VersionRepresentationModel> currentVersion() {
VersionRepresentationModel resource = new VersionRepresentationModel();
resource.setVersion(TaskanaEngineConfiguration.class.getPackage().getImplementationVersion());

View File

@ -0,0 +1,20 @@
package pro.taskana.common.rest.models;
import java.beans.ConstructorProperties;
import java.util.Map;
import org.springframework.hateoas.RepresentationModel;
public class CustomAttributesRepresentationModel
extends RepresentationModel<CustomAttributesRepresentationModel> {
private final Map<String, Object> customAttributes;
@ConstructorProperties({"customAttributes"})
public CustomAttributesRepresentationModel(Map<String, Object> customAttributes) {
this.customAttributes = customAttributes;
}
public Map<String, Object> getCustomAttributes() {
return customAttributes;
}
}

View File

@ -12,6 +12,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.rest.models.CustomAttributesRepresentationModel;
import pro.taskana.common.rest.models.TaskanaUserInfoRepresentationModel;
import pro.taskana.common.test.rest.RestHelper;
import pro.taskana.common.test.rest.TaskanaSpringBootTest;
@ -32,7 +33,7 @@ class TaskanaEngineControllerIntTest {
@Test
void testDomains() {
String url = restHelper.toUrl(RestEndpoints.URL_DOMAIN);
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<List<String>> response =
TEMPLATE.exchange(
@ -43,7 +44,7 @@ class TaskanaEngineControllerIntTest {
@Test
void testClassificationTypes() {
String url = restHelper.toUrl(RestEndpoints.URL_CLASSIFICATION_TYPES);
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<List<String>> response =
TEMPLATE.exchange(
@ -54,7 +55,7 @@ class TaskanaEngineControllerIntTest {
@Test
void testClassificationCategories() {
String url = restHelper.toUrl(RestEndpoints.URL_CLASSIFICATION_CATEGORIES);
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<List<String>> response =
TEMPLATE.exchange(
@ -66,7 +67,7 @@ class TaskanaEngineControllerIntTest {
@Test
void testGetCurrentUserInfo() {
String url = restHelper.toUrl(RestEndpoints.URL_CURRENT_USER);
HttpEntity<Object> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<TaskanaUserInfoRepresentationModel> response =
TEMPLATE.exchange(
@ -81,4 +82,19 @@ class TaskanaEngineControllerIntTest {
assertThat(response.getBody().getRoles()).contains(TaskanaRole.BUSINESS_ADMIN);
assertThat(response.getBody().getRoles()).doesNotContain(TaskanaRole.ADMIN);
}
@Test
void should_ReturnCustomAttributes() {
String url = restHelper.toUrl(RestEndpoints.URL_CUSTOM_ATTRIBUTES);
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ResponseEntity<CustomAttributesRepresentationModel> response =
TEMPLATE.exchange(
url,
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(CustomAttributesRepresentationModel.class));
assertThat(response.getBody()).isNotNull();
}
}

View File

@ -38,8 +38,8 @@ public abstract class AbstractAccTest {
dbSchemaCreator.run();
sampleDataGenerator.clearDb();
sampleDataGenerator.generateTestData();
taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine();
taskanaEngine.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT);
taskanaEngine =
taskanaEngineConfiguration.buildTaskanaEngine(ConnectionManagementMode.AUTOCOMMIT);
converter = taskanaEngine.getWorkingDaysToDaysConverter();
}