diff --git a/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql b/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql index e5f491917..3221bb90a 100644 --- a/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql +++ b/common/taskana-common-data/src/main/resources/sql/clear/clear-db.sql @@ -13,5 +13,6 @@ DELETE FROM CLASSIFICATION; DELETE FROM OBJECT_REFERENCE; DELETE FROM SCHEDULED_JOB; DELETE FROM USER_INFO; +DELETE FROM GROUP_INFO; INSERT INTO CONFIGURATION (NAME) VALUES ('MASTER'); COMMIT; diff --git a/common/taskana-common-data/src/main/resources/sql/clear/drop-tables.sql b/common/taskana-common-data/src/main/resources/sql/clear/drop-tables.sql index a7c5a59df..d5e8de944 100644 --- a/common/taskana-common-data/src/main/resources/sql/clear/drop-tables.sql +++ b/common/taskana-common-data/src/main/resources/sql/clear/drop-tables.sql @@ -13,5 +13,6 @@ DROP TABLE CLASSIFICATION; DROP TABLE OBJECT_REFERENCE; DROP TABLE SCHEDULED_JOB; DROP TABLE USER_INFO; +DROP TABLE GROUP_INFO; DROP SEQUENCE SCHEDULED_JOB_SEQ; COMMIT; diff --git a/common/taskana-common/src/main/resources/sql/db2/taskana-schema-db2.sql b/common/taskana-common/src/main/resources/sql/db2/taskana-schema-db2.sql index 638943455..bb430efaf 100644 --- a/common/taskana-common/src/main/resources/sql/db2/taskana-schema-db2.sql +++ b/common/taskana-common/src/main/resources/sql/db2/taskana-schema-db2.sql @@ -9,7 +9,7 @@ CREATE TABLE TASKANA_SCHEMA_VERSION ); -- The VERSION value must match the value of TaskanaEngineConfiguration.TASKANA_SCHEMA_VERSION INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) -VALUES ('5.1.0', CURRENT_TIMESTAMP); +VALUES ('5.2.0', CURRENT_TIMESTAMP); CREATE TABLE CLASSIFICATION ( @@ -342,6 +342,12 @@ CREATE TABLE USER_INFO PRIMARY KEY (USER_ID) ); +CREATE TABLE GROUP_INFO +( + USER_ID VARCHAR(32) NOT NULL, + GROUP_ID VARCHAR(256) NOT NULL, + PRIMARY KEY (USER_ID, GROUP_ID) +); CREATE SEQUENCE SCHEDULED_JOB_SEQ MINVALUE 1 @@ -423,4 +429,4 @@ CREATE INDEX IDX_WORKBASKET_ACCESS_LIST_WORKBASKET_ID ON WORKBASKET_ACCESS_LIST "PERM_CUSTOM_1" ASC, "PERM_DISTRIBUTE" ASC, "PERM_TRANSFER" ASC, "PERM_APPEND" ASC, "PERM_OPEN" ASC, "PERM_READ" ASC, "ACCESS_ID" ASC) ALLOW REVERSE SCANS COLLECT SAMPLED DETAILED STATISTICS; -COMMIT WORK; \ No newline at end of file +COMMIT WORK; diff --git a/common/taskana-common/src/main/resources/sql/db2/taskana_schema_update_5.1.0_to_5.2.0_db2.sql b/common/taskana-common/src/main/resources/sql/db2/taskana_schema_update_5.1.0_to_5.2.0_db2.sql new file mode 100644 index 000000000..e869a5c07 --- /dev/null +++ b/common/taskana-common/src/main/resources/sql/db2/taskana_schema_update_5.1.0_to_5.2.0_db2.sql @@ -0,0 +1,10 @@ +-- this script updates the TASKANA database schema from version 5.1.0 to version 5.2.0. + +INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.2.0', CURRENT_TIMESTAMP); + +CREATE TABLE GROUP_INFO +( + USER_ID VARCHAR(32) NOT NULL, + GROUP_ID VARCHAR(256) NOT NULL, + PRIMARY KEY (USER_ID, GROUP_ID) +); diff --git a/common/taskana-common/src/main/resources/sql/h2/taskana-schema-h2.sql b/common/taskana-common/src/main/resources/sql/h2/taskana-schema-h2.sql index 0d6a4cd7f..7a388ded1 100644 --- a/common/taskana-common/src/main/resources/sql/h2/taskana-schema-h2.sql +++ b/common/taskana-common/src/main/resources/sql/h2/taskana-schema-h2.sql @@ -16,7 +16,7 @@ CREATE TABLE TASKANA_SCHEMA_VERSION ); -- The VERSION value must match the value of TaskanaEngineConfiguration.TASKANA_SCHEMA_VERSION INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) -VALUES ('5.1.0', CURRENT_TIMESTAMP); +VALUES ('5.2.0', CURRENT_TIMESTAMP); CREATE TABLE CLASSIFICATION ( @@ -348,6 +348,12 @@ CREATE TABLE USER_INFO PRIMARY KEY (USER_ID) ); +CREATE TABLE GROUP_INFO +( + USER_ID VARCHAR(32) NOT NULL, + GROUP_ID VARCHAR(256) NOT NULL, + PRIMARY KEY (USER_ID, GROUP_ID) +); CREATE SEQUENCE SCHEDULED_JOB_SEQ MINVALUE 1 diff --git a/common/taskana-common/src/main/resources/sql/h2/taskana_schema_update_5.1.0_to_5.2.0_h2.sql b/common/taskana-common/src/main/resources/sql/h2/taskana_schema_update_5.1.0_to_5.2.0_h2.sql new file mode 100644 index 000000000..e869a5c07 --- /dev/null +++ b/common/taskana-common/src/main/resources/sql/h2/taskana_schema_update_5.1.0_to_5.2.0_h2.sql @@ -0,0 +1,10 @@ +-- this script updates the TASKANA database schema from version 5.1.0 to version 5.2.0. + +INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.2.0', CURRENT_TIMESTAMP); + +CREATE TABLE GROUP_INFO +( + USER_ID VARCHAR(32) NOT NULL, + GROUP_ID VARCHAR(256) NOT NULL, + PRIMARY KEY (USER_ID, GROUP_ID) +); diff --git a/common/taskana-common/src/main/resources/sql/postgres/taskana-schema-postgres.sql b/common/taskana-common/src/main/resources/sql/postgres/taskana-schema-postgres.sql index 370aa2a94..0fa686674 100644 --- a/common/taskana-common/src/main/resources/sql/postgres/taskana-schema-postgres.sql +++ b/common/taskana-common/src/main/resources/sql/postgres/taskana-schema-postgres.sql @@ -12,7 +12,7 @@ CREATE TABLE TASKANA_SCHEMA_VERSION ); -- The VERSION value must match the value of TaskanaEngineConfiguration.TASKANA_SCHEMA_VERSION INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) -VALUES ('5.1.0', CURRENT_TIMESTAMP); +VALUES ('5.2.0', CURRENT_TIMESTAMP); CREATE TABLE CLASSIFICATION ( @@ -345,6 +345,12 @@ CREATE TABLE USER_INFO PRIMARY KEY (USER_ID) ); +CREATE TABLE GROUP_INFO +( + USER_ID VARCHAR(32) NOT NULL, + GROUP_ID VARCHAR(256) NOT NULL, + PRIMARY KEY (USER_ID, GROUP_ID) +); CREATE SEQUENCE SCHEDULED_JOB_SEQ MINVALUE 1 diff --git a/common/taskana-common/src/main/resources/sql/postgres/taskana_schema_update_5.1.0_to_5.2.0_postgres.sql b/common/taskana-common/src/main/resources/sql/postgres/taskana_schema_update_5.1.0_to_5.2.0_postgres.sql new file mode 100644 index 000000000..35d590752 --- /dev/null +++ b/common/taskana-common/src/main/resources/sql/postgres/taskana_schema_update_5.1.0_to_5.2.0_postgres.sql @@ -0,0 +1,12 @@ +-- this script updates the TASKANA database schema from version 5.1.0 to version 5.2.0. + +SET search_path = %schemaName%; + +INSERT INTO TASKANA_SCHEMA_VERSION (VERSION, CREATED) VALUES ('5.2.0', CURRENT_TIMESTAMP); + +CREATE TABLE GROUP_INFO +( + USER_ID VARCHAR(32) NOT NULL, + GROUP_ID VARCHAR(256) NOT NULL, + PRIMARY KEY (USER_ID, GROUP_ID) +); diff --git a/lib/taskana-core-test/archunit_store/caaac46d-650a-4955-a7c9-21d0bdd9e5e4 b/lib/taskana-core-test/archunit_store/5cb8b13e-0834-4d4a-82b2-98ffbe0a62ab similarity index 100% rename from lib/taskana-core-test/archunit_store/caaac46d-650a-4955-a7c9-21d0bdd9e5e4 rename to lib/taskana-core-test/archunit_store/5cb8b13e-0834-4d4a-82b2-98ffbe0a62ab diff --git a/lib/taskana-core-test/archunit_store/338916cd-65eb-4545-a7be-6c7f534fde1e b/lib/taskana-core-test/archunit_store/c090f321-461a-42f5-8bda-450994737ca7 similarity index 100% rename from lib/taskana-core-test/archunit_store/338916cd-65eb-4545-a7be-6c7f534fde1e rename to lib/taskana-core-test/archunit_store/c090f321-461a-42f5-8bda-450994737ca7 diff --git a/lib/taskana-core-test/archunit_store/3faafb71-7c1c-4a76-b3f4-952994afc15d b/lib/taskana-core-test/archunit_store/da0a823c-abf2-4622-a420-044ce06dc6c0 similarity index 99% rename from lib/taskana-core-test/archunit_store/3faafb71-7c1c-4a76-b3f4-952994afc15d rename to lib/taskana-core-test/archunit_store/da0a823c-abf2-4622-a420-044ce06dc6c0 index df18623df..9e5504131 100644 --- a/lib/taskana-core-test/archunit_store/3faafb71-7c1c-4a76-b3f4-952994afc15d +++ b/lib/taskana-core-test/archunit_store/da0a823c-abf2-4622-a420-044ce06dc6c0 @@ -85504,7 +85504,9 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 2. Dependencies of Slice pro.taskana.common.internal.TaskanaEngineImpl\ - Method calls constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> in (TaskanaEngineImpl.java:206)\ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39) + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:177)\ + - Method calls method in (UserServiceImpl.java:197) Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ Slice pro.taskana.common.internal.TaskanaEngineImpl -> \ Slice pro.taskana.user.internal.UserServiceImpl -> \ @@ -85516,12 +85518,12 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 2. Dependencies of Slice pro.taskana.common.internal.TaskanaEngineImpl\ - Method calls constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> in (TaskanaEngineImpl.java:206)\ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:64)\ - - Method calls method in (UserServiceImpl.java:79)\ - - Method calls method in (UserServiceImpl.java:94)\ - - Method calls method in (UserServiceImpl.java:111)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:72)\ + - Method calls method in (UserServiceImpl.java:88)\ + - Method calls method in (UserServiceImpl.java:110)\ + - Method calls method in (UserServiceImpl.java:133)\ 4. Dependencies of Slice pro.taskana.common.api.TaskanaEngine\ - Method has return type in (TaskanaEngine.java:0) Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ @@ -85538,17 +85540,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.common.api.TaskanaEngine\ @@ -85568,17 +85573,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.history.internal.HistoryEventManager\ @@ -85601,17 +85609,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.history.internal.HistoryEventManager\ @@ -85645,17 +85656,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.routing.internal.TaskRoutingManager\ @@ -85678,17 +85692,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.routing.internal.TaskRoutingManager\ @@ -85716,17 +85733,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.AfterRequestChangesManager\ @@ -85749,17 +85769,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.AfterRequestChangesManager\ @@ -85786,17 +85809,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.AfterRequestReviewManager\ @@ -85819,17 +85845,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.AfterRequestReviewManager\ @@ -85856,17 +85885,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.BeforeRequestChangesManager\ @@ -85889,17 +85921,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.BeforeRequestChangesManager\ @@ -85926,17 +85961,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.BeforeRequestReviewManager\ @@ -85959,17 +85997,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.BeforeRequestReviewManager\ @@ -85996,17 +86037,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.ReviewRequiredManager\ @@ -86029,17 +86073,20 @@ Cycle detected: Slice pro.taskana.TaskanaEngineConfiguration -> \ 3. Dependencies of Slice pro.taskana.user.internal.UserServiceImpl\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice pro.taskana.common.internal.InternalTaskanaEngine\ - Method has return type in (InternalTaskanaEngine.java:0)\ 5. Dependencies of Slice pro.taskana.spi.task.internal.ReviewRequiredManager\ diff --git a/lib/taskana-core-test/archunit_store/d13a8a46-5605-4062-8870-8f8de71f7b07 b/lib/taskana-core-test/archunit_store/f5ab0e52-6a11-49c9-b359-8abd1f62775f similarity index 99% rename from lib/taskana-core-test/archunit_store/d13a8a46-5605-4062-8870-8f8de71f7b07 rename to lib/taskana-core-test/archunit_store/f5ab0e52-6a11-49c9-b359-8abd1f62775f index 03db85020..2987690ac 100644 --- a/lib/taskana-core-test/archunit_store/d13a8a46-5605-4062-8870-8f8de71f7b07 +++ b/lib/taskana-core-test/archunit_store/f5ab0e52-6a11-49c9-b359-8abd1f62775f @@ -5827,17 +5827,20 @@ Cycle detected: Slice classification.internal -> \ 4. Dependencies of Slice user.internal\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 5. Dependencies of Slice common.internal\ - Method calls constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.spi.priority.internal.PriorityServiceManager, pro.taskana.classification.internal.ClassificationMapper, pro.taskana.task.internal.TaskMapper)> in (TaskanaEngineImpl.java:185)\ - Method references class object in (TaskanaEngineImpl.java:188)\ @@ -6271,17 +6274,20 @@ Cycle detected: Slice classification.internal -> \ 5. Dependencies of Slice user.internal\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 6. Dependencies of Slice common.internal\ - Method calls constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.spi.priority.internal.PriorityServiceManager, pro.taskana.classification.internal.ClassificationMapper, pro.taskana.task.internal.TaskMapper)> in (TaskanaEngineImpl.java:185)\ - Method references class object in (TaskanaEngineImpl.java:188)\ @@ -6731,17 +6737,20 @@ Cycle detected: Slice classification.internal -> \ 3. Dependencies of Slice user.internal\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130)\ + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156)\ 4. Dependencies of Slice common.internal\ - Method calls constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.spi.priority.internal.PriorityServiceManager, pro.taskana.classification.internal.ClassificationMapper, pro.taskana.task.internal.TaskMapper)> in (TaskanaEngineImpl.java:185)\ - Method references class object in (TaskanaEngineImpl.java:188)\ @@ -17035,6 +17044,7 @@ Cycle detected: Slice common.api -> \ - Method throws type in (UserService.java:0)\ - Method throws type in (UserService.java:0)\ - Method throws type in (UserService.java:0)\ + - Method throws type in (UserService.java:0)\ - Method throws type in (UserService.java:0)\ 3. Dependencies of Slice common.api.exceptions\ - Constructor (java.lang.String, [Lpro.taskana.common.api.TaskanaRole;)> depends on component type in (MismatchedRoleException.java:0)\ @@ -17596,17 +17606,20 @@ Cycle detected: Slice common.internal -> \ 3. Dependencies of Slice user.internal\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130) + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156) Cycle detected: Slice common.internal -> \ Slice task.internal -> \ Slice workbasket.internal -> \ @@ -17770,17 +17783,20 @@ Cycle detected: Slice common.internal -> \ 2. Dependencies of Slice user.internal\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> has parameter of type in (UserServiceImpl.java:0)\ - Field has type in (UserServiceImpl.java:0)\ - - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:37)\ - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:39)\ - - Method calls method in (UserServiceImpl.java:50)\ - - Method calls method in (UserServiceImpl.java:63)\ - - Method calls method in (UserServiceImpl.java:78)\ - - Method calls method in (UserServiceImpl.java:82)\ - - Method calls method in (UserServiceImpl.java:93)\ - - Method calls method in (UserServiceImpl.java:97)\ - - Method calls method in (UserServiceImpl.java:110)\ - - Method calls method in (UserServiceImpl.java:125)\ - - Method calls method in (UserServiceImpl.java:130) + - Constructor (pro.taskana.common.internal.InternalTaskanaEngine, pro.taskana.user.internal.UserMapper)> calls method in (UserServiceImpl.java:41)\ + - Method calls method in (UserServiceImpl.java:52)\ + - Method calls method in (UserServiceImpl.java:58)\ + - Method calls method in (UserServiceImpl.java:71)\ + - Method calls method in (UserServiceImpl.java:87)\ + - Method calls method in (UserServiceImpl.java:92)\ + - Method calls method in (UserServiceImpl.java:93)\ + - Method calls method in (UserServiceImpl.java:96)\ + - Method calls method in (UserServiceImpl.java:109)\ + - Method calls method in (UserServiceImpl.java:113)\ + - Method calls method in (UserServiceImpl.java:132)\ + - Method calls method in (UserServiceImpl.java:148)\ + - Method calls method in (UserServiceImpl.java:156) Cycle detected: Slice common.internal -> \ Slice workbasket.internal -> \ Slice common.internal\ diff --git a/lib/taskana-core-test/archunit_store/stored.rules b/lib/taskana-core-test/archunit_store/stored.rules index 33b4336b5..f491c4b72 100644 --- a/lib/taskana-core-test/archunit_store/stored.rules +++ b/lib/taskana-core-test/archunit_store/stored.rules @@ -1,6 +1,6 @@ # -#Mon Oct 17 04:50:12 CEST 2022 -slices\ matching\ 'pro.taskana.(**)'\ should\ be\ free\ of\ cycles=d13a8a46-5605-4062-8870-8f8de71f7b07 -methods\ that\ are\ annotated\ with\ @Test\ or\ annotated\ with\ @TestFactory\ or\ annotated\ with\ @TestTemplate\ and\ are\ not\ declared\ in\ acceptance.ArchitectureTest\ should\ be\ package\ private\ and\ should\ have\ name\ matching\ '^should_[A-Z][^_]+(_(For|When)_[A-Z][^_]+)?$'=338916cd-65eb-4545-a7be-6c7f534fde1e -slices\ assigned\ from\ every\ single\ class\ should\ be\ free\ of\ cycles=3faafb71-7c1c-4a76-b3f4-952994afc15d -no\ classes\ should\ use\ field\ injection,\ because\ field\ injection\ is\ considered\ harmful;\ use\ constructor\ injection\ or\ setter\ injection\ instead;\ see\ https\://stackoverflow.com/q/39890849\ for\ detailed\ explanations=caaac46d-650a-4955-a7c9-21d0bdd9e5e4 +#Wed Oct 19 12:37:50 CEST 2022 +slices\ matching\ 'pro.taskana.(**)'\ should\ be\ free\ of\ cycles=f5ab0e52-6a11-49c9-b359-8abd1f62775f +methods\ that\ are\ annotated\ with\ @Test\ or\ annotated\ with\ @TestFactory\ or\ annotated\ with\ @TestTemplate\ and\ are\ not\ declared\ in\ acceptance.ArchitectureTest\ should\ be\ package\ private\ and\ should\ have\ name\ matching\ '^should_[A-Z][^_]+(_(For|When)_[A-Z][^_]+)?$'=c090f321-461a-42f5-8bda-450994737ca7 +slices\ assigned\ from\ every\ single\ class\ should\ be\ free\ of\ cycles=da0a823c-abf2-4622-a420-044ce06dc6c0 +no\ classes\ should\ use\ field\ injection,\ because\ field\ injection\ is\ considered\ harmful;\ use\ constructor\ injection\ or\ setter\ injection\ instead;\ see\ https\://stackoverflow.com/q/39890849\ for\ detailed\ explanations=5cb8b13e-0834-4d4a-82b2-98ffbe0a62ab diff --git a/lib/taskana-core-test/src/test/java/acceptance/user/UserServiceAccTest.java b/lib/taskana-core-test/src/test/java/acceptance/user/UserServiceAccTest.java index 538188f2e..298a1663e 100644 --- a/lib/taskana-core-test/src/test/java/acceptance/user/UserServiceAccTest.java +++ b/lib/taskana-core-test/src/test/java/acceptance/user/UserServiceAccTest.java @@ -8,9 +8,9 @@ import static pro.taskana.testapi.DefaultTestEntities.defaultTestWorkbasket; import static pro.taskana.testapi.DefaultTestEntities.randomTestUser; import static pro.taskana.testapi.builder.UserBuilder.newUser; -import java.util.Arrays; -import java.util.Iterator; import java.util.List; +import java.util.Set; +import java.util.UUID; import java.util.stream.Stream; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.DynamicTest; @@ -26,6 +26,7 @@ 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.MismatchedRoleException; +import pro.taskana.common.internal.util.Triplet; import pro.taskana.testapi.TaskanaEngineConfigurationModifier; import pro.taskana.testapi.TaskanaInject; import pro.taskana.testapi.TaskanaIntegrationTest; @@ -49,10 +50,11 @@ class UserServiceAccTest { @TaskanaInject TaskanaEngine taskanaEngine; private WorkbasketAccessItem createAccessItem( - User user, Workbasket workbasket, WorkbasketPermission... permissions) throws Exception { + String accessId, Workbasket workbasket, WorkbasketPermission... permissions) + throws Exception { WorkbasketAccessItemBuilder builder = WorkbasketAccessItemBuilder.newWorkbasketAccessItem() - .accessId(user.getId()) + .accessId(accessId) .workbasketId(workbasket.getId()); for (WorkbasketPermission permission : permissions) { builder.permission(permission); @@ -83,6 +85,11 @@ class UserServiceAccTest { final User userToGet = newUser() .id("max-mustermann") + .groups( + Set.of( + "cn=ksc-users,cn=groups,OU=Test,O=TASKANA", + "cn=Organisationseinheit KSC 1,cn=Organisationseinheit" + + " KSC,cn=organisation,OU=Test,O=TASKANA")) .firstName("Max") .lastName("Mustermann") .fullName("Max Mustermann") @@ -99,7 +106,10 @@ class UserServiceAccTest { User userInDatabase = userService.getUser(userToGet.getId()); - assertThat(userInDatabase).hasNoNullFieldsOrProperties().isEqualTo(userToGet); + assertThat(userInDatabase) + .hasNoNullFieldsOrProperties() + .isNotSameAs(userToGet) + .isEqualTo(userToGet); } } @@ -122,24 +132,96 @@ class UserServiceAccTest { @WithAccessId(user = "businessadmin") @Test - void should_SetTheLongAndFullNameAccordingToRules_When_CreatingUserWithThoseFieldsEmpty() - throws Exception { + void should_InsertUserInDatabase_When_CreatingUserWithGroups() throws Exception { User userToCreate = userService.newUser(); - userToCreate.setId("martina"); + userToCreate.setId("anton2"); + userToCreate.setFirstName("Anton"); + userToCreate.setLastName("Miller"); + userToCreate.setGroups(Set.of("groupX", "groupY")); + userService.createUser(userToCreate); + + User userInDatabase = userService.getUser(userToCreate.getId()); + assertThat(userToCreate).isNotSameAs(userInDatabase).isEqualTo(userInDatabase); + } + + @WithAccessId(user = "businessadmin") + @TestFactory + Stream + should_AutomaticallySetTheLongName_When_CreatingUserWithEmptyOrNullLongName() { + Stream longNames = Stream.of(null, ""); + + ThrowingConsumer test = + longName -> { + User userToCreate = userService.newUser(); + userToCreate.setId(UUID.randomUUID().toString().replace("-", "")); + userToCreate.setFirstName("Martina"); + userToCreate.setLastName("Schmidt"); + userToCreate.setLongName(longName); + + User updatedUser = userService.createUser(userToCreate); + + assertThat(updatedUser.getLongName()) + .isEqualTo("Schmidt, Martina - (%s)", userToCreate.getId()); + }; + + return DynamicTest.stream(longNames, l -> "for " + l, test); + } + + @WithAccessId(user = "businessadmin") + @TestFactory + Stream + should_AutomaticallySetTheFullName_When_CreatingUserWithEmptyOrNullFullName() { + Stream fullNames = Stream.of(null, ""); + + ThrowingConsumer test = + fullName -> { + User userToCreate = userService.newUser(); + userToCreate.setId(UUID.randomUUID().toString().replace("-", "")); + userToCreate.setFirstName("Martina"); + userToCreate.setLastName("Schmidt"); + userToCreate.setFullName(fullName); + + User updatedUser = userService.createUser(userToCreate); + + assertThat(updatedUser.getFullName()).isEqualTo("Schmidt, Martina"); + }; + + return DynamicTest.stream(fullNames, l -> "for " + l, test); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepLongName_When_CreatingUserWithLongNameDefined() throws Exception { + User userToCreate = userService.newUser(); + userToCreate.setId("user-1"); userToCreate.setFirstName("Martina"); userToCreate.setLastName("Schmidt"); + userToCreate.setLongName("long name"); - User createdUser = userService.createUser(userToCreate); + User updatedUser = userService.createUser(userToCreate); - assertThat(createdUser.getLongName()).isEqualTo("Schmidt, Martina - (martina)"); - assertThat(createdUser.getFullName()).isEqualTo("Schmidt, Martina"); + assertThat(updatedUser.getLongName()).isEqualTo("long name"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepFullName_When_CreatingUserWithFullNameDefined() throws Exception { + User userToCreate = userService.newUser(); + userToCreate.setId("user-2"); + userToCreate.setFirstName("Martina"); + userToCreate.setLastName("Schmidt"); + userToCreate.setFullName("full name"); + + User updatedUser = userService.createUser(userToCreate); + + assertThat(updatedUser.getFullName()).isEqualTo("full name"); } @WithAccessId(user = "businessadmin") @Test void should_ThrowInvalidArgumentException_When_TryingToCreateUserWithFirstNameNull() { User userToCreate = userService.newUser(); - userToCreate.setId("user-1"); + userToCreate.setId("user-3"); userToCreate.setFirstName(null); userToCreate.setLastName("Schmidt"); @@ -154,8 +236,8 @@ class UserServiceAccTest { @Test void should_ThrowInvalidArgumentException_When_TryingToCreateUserWithLastNameNull() { User userToCreate = userService.newUser(); - userToCreate.setId("user-2"); - userToCreate.setFirstName("User 1"); + userToCreate.setId("user-4"); + userToCreate.setFirstName("User 4"); userToCreate.setLastName(null); ThrowingCallable callable = () -> userService.createUser(userToCreate); @@ -168,7 +250,7 @@ class UserServiceAccTest { @WithAccessId(user = "businessadmin") @TestFactory Stream should_ThrowInvalidArgumentException_When_TryingToCreateUserWithNotSetId() { - Iterator iterator = Arrays.asList("", null).iterator(); + Stream userIds = Stream.of("", null); ThrowingConsumer test = userId -> { @@ -181,10 +263,10 @@ class UserServiceAccTest { assertThatThrownBy(callable) .isInstanceOf(InvalidArgumentException.class) - .hasMessage("UserId must not be empty when creating User."); + .hasMessage("UserId must not be empty when creating or updating User."); }; - return DynamicTest.stream(iterator, c -> "for " + c, test); + return DynamicTest.stream(userIds, c -> "for " + c, test); } @WithAccessId(user = "businessadmin") @@ -214,7 +296,7 @@ class UserServiceAccTest { @Test void should_ThrowNotAuthorizedException_When_TryingToCreateUserWithoutAdminRole() { User userToCreate = userService.newUser(); - userToCreate.setId("user-3"); + userToCreate.setId("user-5"); userToCreate.setFirstName("firstName"); userToCreate.setLastName("lastName"); ThrowingCallable callable = () -> userService.createUser(userToCreate); @@ -224,6 +306,22 @@ class UserServiceAccTest { assertThat(ex.getRoles()) .isEqualTo(new TaskanaRole[] {TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN}); } + + @WithAccessId(user = "businessadmin") + @Test + void should_MakeAccessIdsLowerCase_When_ConfigurationPropertyIsSet() throws Exception { + User userToCreate = userService.newUser(); + userToCreate.setId("USER-ID-WITH-CAPS"); + userToCreate.setFirstName("firstName"); + userToCreate.setLastName("lastName"); + userToCreate.setGroups(Set.of("GROUP1-ID-WITH-CAPS", "Group2-Id-With-Caps")); + + User userInDatabase = userService.createUser(userToCreate); + + assertThat(userInDatabase.getId()).isEqualTo("user-id-with-caps"); + assertThat(userInDatabase.getGroups()) + .containsExactlyInAnyOrder("group1-id-with-caps", "group2-id-with-caps"); + } } @Nested @@ -232,7 +330,7 @@ class UserServiceAccTest { @WithAccessId(user = "businessadmin") @Test - void should_UpdateUserInDatabase_When_IdExisting() throws Exception { + void should_UpdateUserInDatabase() throws Exception { User userToUpdate = randomTestUser().buildAndStore(userService); userToUpdate.setFirstName("Anton"); @@ -242,6 +340,33 @@ class UserServiceAccTest { assertThat(userInDatabase).isNotSameAs(userToUpdate).isEqualTo(userToUpdate); } + @WithAccessId(user = "businessadmin") + @TestFactory + Stream should_UpdateGroups() { + Stream, Set>> testCases = + Stream.of( + Triplet.of( + "User has no groups before updating", Set.of(), Set.of("group1", "group2")), + Triplet.of("new groups differ all", Set.of("group1"), Set.of("group2", "group3")), + Triplet.of("some new groups differ", Set.of("group1"), Set.of("group1", "group2")), + Triplet.of("new groups are all the same", Set.of("group1"), Set.of("group1"))); + + ThrowingConsumer, Set>> test = + t -> { + Set existingGroups = t.getMiddle(); + Set newGroups = t.getMiddle(); + User userToUpdate = randomTestUser().groups(existingGroups).buildAndStore(userService); + + userToUpdate.setGroups(newGroups); + userService.updateUser(userToUpdate); + + User userInDatabase = userService.getUser(userToUpdate.getId()); + assertThat(userInDatabase.getGroups()).containsExactlyInAnyOrderElementsOf(newGroups); + }; + + return DynamicTest.stream(testCases, Triplet::getLeft, test); + } + @WithAccessId(user = "user-1-1") @Test void should_ThrowNotAuthorizedException_When_TryingToUpdateUserWithNoAdminRole() @@ -260,6 +385,213 @@ class UserServiceAccTest { .isEqualTo(new TaskanaRole[] {TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN}); } + @WithAccessId(user = "businessadmin") + @TestFactory + Stream + should_AutomaticallySetTheFullName_When_UpdatingUserWithEmptyOrNullFullName() { + Stream fullNames = Stream.of(null, ""); + + ThrowingConsumer test = + fullName -> { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setFirstName("Martina"); + userToUpdate.setLastName("Schmidt"); + userToUpdate.setFullName(fullName); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getFullName()).isEqualTo("Schmidt, Martina"); + }; + + return DynamicTest.stream(fullNames, l -> "for " + l, test); + } + + @WithAccessId(user = "businessadmin") + @TestFactory + Stream + should_AutomaticallySetTheLongName_When_UpdatingUserWithEmptyOrNullLongName() { + Stream longNames = Stream.of(null, ""); + + ThrowingConsumer test = + longName -> { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setFirstName("Martina"); + userToUpdate.setLastName("Schmidt"); + userToUpdate.setLongName(longName); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getLongName()) + .isEqualTo("Schmidt, Martina - (%s)", userToUpdate.getId()); + }; + + return DynamicTest.stream(longNames, l -> "for " + l, test); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_AutomaticallySetTheFullAndLongName_When_UpdatingFirstName() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setFirstName("Martina"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getFullName()).isEqualTo("%s, Martina", updatedUser.getLastName()); + assertThat(updatedUser.getLongName()) + .isEqualTo("%s, Martina - (%s)", userToUpdate.getLastName(), userToUpdate.getId()); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_AutomaticallySetTheFullAndLongName_When_UpdatingLastName() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setLastName("Schmidt"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getFullName()).isEqualTo("Schmidt, %s", updatedUser.getFirstName()); + assertThat(updatedUser.getLongName()) + .isEqualTo("Schmidt, %s - (%s)", userToUpdate.getFirstName(), userToUpdate.getId()); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepFullName_When_UpdatingFirstNameWithFullNameDefined() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setFirstName("Martina"); + userToUpdate.setFullName("full name"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getFullName()).isEqualTo("full name"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepFullName_When_UpdatingLastNameWithFullNameDefined() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setLastName("Schmidt"); + userToUpdate.setFullName("full name"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getFullName()).isEqualTo("full name"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepFullName_When_UpdatingFirstAndLastNameWithFullNameDefined() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setFirstName("Martina"); + userToUpdate.setLastName("Schmidt"); + userToUpdate.setFullName("full name"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getFullName()).isEqualTo("full name"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepLongName_When_UpdatingFirstNameWithLongNameDefined() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setFirstName("Martina"); + userToUpdate.setLongName("long name"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getLongName()).isEqualTo("long name"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepLongName_When_UpdatingLastNameWithLongNameDefined() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setLastName("Schmidt"); + userToUpdate.setLongName("long name"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getLongName()).isEqualTo("long name"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_KeepLongName_When_UpdatingFirstAndLastNameWithLongNameDefined() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setFirstName("Martina"); + userToUpdate.setLastName("Schmidt"); + userToUpdate.setLongName("long name"); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getLongName()).isEqualTo("long name"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_MakeGroupIdsLowerCase_When_UpdatingUserWithUpperCaseGroups() throws Exception { + User userToUpdate = randomTestUser().buildAndStore(userService); + userToUpdate.setGroups(Set.of("GROUP1-ID-WITH-CAPS", "Group2-Id-With-Caps")); + + User updatedUser = userService.updateUser(userToUpdate); + + assertThat(updatedUser.getGroups()) + .containsExactlyInAnyOrder("group1-id-with-caps", "group2-id-with-caps"); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_ThrowInvalidArgumentException_When_TryingToUpdateUserWithFirstNameNull() { + User userToUpdate = userService.newUser(); + userToUpdate.setId("user-3"); + userToUpdate.setFirstName(null); + userToUpdate.setLastName("Schmidt"); + + ThrowingCallable callable = () -> userService.updateUser(userToUpdate); + + assertThatThrownBy(callable) + .isInstanceOf(InvalidArgumentException.class) + .hasMessage("First and last name of User must be set or empty."); + } + + @WithAccessId(user = "businessadmin") + @Test + void should_ThrowInvalidArgumentException_When_TryingToUpdateUserWithLastNameNull() { + User userToUpdate = userService.newUser(); + userToUpdate.setId("user-4"); + userToUpdate.setFirstName("User 4"); + userToUpdate.setLastName(null); + + ThrowingCallable callable = () -> userService.updateUser(userToUpdate); + + assertThatThrownBy(callable) + .isInstanceOf(InvalidArgumentException.class) + .hasMessage("First and last name of User must be set or empty."); + } + + @WithAccessId(user = "businessadmin") + @TestFactory + Stream should_ThrowInvalidArgumentException_When_TryingToUpdateUserWithNotSetId() { + Stream userIds = Stream.of("", null); + + ThrowingConsumer test = + userId -> { + User userToUpdate = userService.newUser(); + userToUpdate.setFirstName("firstName"); + userToUpdate.setLastName("lastName"); + userToUpdate.setId(userId); + + ThrowingCallable callable = () -> userService.updateUser(userToUpdate); + + assertThatThrownBy(callable) + .isInstanceOf(InvalidArgumentException.class) + .hasMessage("UserId must not be empty when creating or updating User."); + }; + + return DynamicTest.stream(userIds, c -> "for " + c, test); + } + @WithAccessId(user = "businessadmin") @Test void should_ThrowUserNotFoundException_When_TryingToUpdateUserWithNonExistingId() { @@ -284,7 +616,7 @@ class UserServiceAccTest { @WithAccessId(user = "businessadmin") @Test - void should_DeleteUserFromDatabase_When_IdExisting() throws Exception { + void should_DeleteUserFromDatabase() throws Exception { User userToDelete = randomTestUser().buildAndStore(userService); userService.deleteUser(userToDelete.getId()); @@ -298,6 +630,20 @@ class UserServiceAccTest { .isEqualTo(userToDelete.getId()); } + @WithAccessId(user = "businessadmin") + @Test + void should_DeleteGroupsFromDatabase_When_UserHadGroups() throws Exception { + User userToDelete = + randomTestUser().groups(Set.of("group1", "group2")).buildAndStore(userService); + + userService.deleteUser(userToDelete.getId()); + + // verify that groups are deleted by creating a new user with the same id and check its groups + User newUserWithSameId = randomTestUser().id(userToDelete.getId()).buildAndStore(userService); + User userInDatabase = userService.getUser(newUserWithSameId.getId()); + assertThat(userInDatabase.getGroups()).isEmpty(); + } + @WithAccessId(user = "businessadmin") @Test void should_ThrowUserNotFoundException_When_TryingToDeleteUserWithNonExistingId() { @@ -336,7 +682,7 @@ class UserServiceAccTest { User user = randomTestUser().buildAndStore(userService, "businessadmin"); Workbasket workbasket = defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); - createAccessItem(user, workbasket, WorkbasketPermission.READ); + createAccessItem(user.getId(), workbasket, WorkbasketPermission.READ); User userInDatabase = userService.getUser(user.getId()); @@ -361,7 +707,24 @@ class UserServiceAccTest { User user = randomTestUser().buildAndStore(userService, "businessadmin"); Workbasket workbasket = defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); - createAccessItem(user, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + createAccessItem( + user.getId(), workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + + User userInDatabase = userService.getUser(user.getId()); + + assertThat(userInDatabase.getDomains()).containsExactly(workbasket.getDomain()); + } + + @WithAccessId(user = "user-1-1") + @Test + void should_ReturnOneDomain_When_GroupHasSufficientMinimalPermissionsToAssignDomains() + throws Exception { + String groupId = UUID.randomUUID().toString(); + User user = + randomTestUser().groups(Set.of(groupId)).buildAndStore(userService, "businessadmin"); + Workbasket workbasket = + defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); + createAccessItem(groupId, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); User userInDatabase = userService.getUser(user.getId()); @@ -376,7 +739,8 @@ class UserServiceAccTest { Workbasket workbasket = defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); WorkbasketAccessItem wai = - createAccessItem(user, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + createAccessItem( + user.getId(), workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); User userInDatabase = userService.getUser(user.getId()); @@ -392,6 +756,29 @@ class UserServiceAccTest { assertThat(userInDatabase.getDomains()).isEmpty(); } + @WithAccessId(user = "businessadmin") + @Test + void should_ReturnEmptyDomains_When_GroupHasSufficientPermissionsAndThenGroupIsUpdated() + throws Exception { + String groupId = UUID.randomUUID().toString(); + User user = randomTestUser().groups(Set.of(groupId)).buildAndStore(userService); + Workbasket workbasket = defaultTestWorkbasket().buildAndStore(workbasketService); + createAccessItem(groupId, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + + User userInDatabase = userService.getUser(user.getId()); + + assertThat(userInDatabase.getDomains()).containsExactly(workbasket.getDomain()); + + // then user is updated and other group is assigned + + user.setGroups(Set.of("new group")); + userService.updateUser(user); + + userInDatabase = userService.getUser(user.getId()); + + assertThat(userInDatabase.getDomains()).isEmpty(); + } + @WithAccessId(user = "user-1-1") @Test void should_ReturnMultipleDomains_When_UserHasSufficientMinimalPermissionsForMultipleDomains() @@ -403,8 +790,34 @@ class UserServiceAccTest { defaultTestWorkbasket() .domain("DOMAIN_B") .buildAndStore(workbasketService, "businessadmin"); - createAccessItem(user, workbasket1, WorkbasketPermission.OPEN, WorkbasketPermission.READ); - createAccessItem(user, workbasket2, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + createAccessItem( + user.getId(), workbasket1, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + createAccessItem( + user.getId(), workbasket2, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + + User userInDatabase = userService.getUser(user.getId()); + + assertThat(userInDatabase.getDomains()) + .containsExactlyInAnyOrder(workbasket1.getDomain(), workbasket2.getDomain()); + } + + @WithAccessId(user = "user-1-1") + @Test + void + should_ReturnMultipleDomains_When_UserAndGroupHaveSufficientMinimalPermsForMultipleDomains() + throws Exception { + String groupId = UUID.randomUUID().toString(); + User user = + randomTestUser().groups(Set.of(groupId)).buildAndStore(userService, "businessadmin"); + Workbasket workbasket1 = + defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); + Workbasket workbasket2 = + defaultTestWorkbasket() + .domain("DOMAIN_B") + .buildAndStore(workbasketService, "businessadmin"); + createAccessItem( + user.getId(), workbasket1, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + createAccessItem(groupId, workbasket2, WorkbasketPermission.OPEN, WorkbasketPermission.READ); User userInDatabase = userService.getUser(user.getId()); @@ -432,7 +845,24 @@ class UserServiceAccTest { User user = randomTestUser().buildAndStore(userService, "businessadmin"); Workbasket workbasket = defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); - createAccessItem(user, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + createAccessItem( + user.getId(), workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + + User userInDatabase = userService.getUser(user.getId()); + + assertThat(userInDatabase.getDomains()).isEmpty(); + } + + @WithAccessId(user = "user-1-1") + @Test + void should_ReturnEmptyDomains_When_GroupHasInsufficientMinimalPermissionsToAssignDomains() + throws Exception { + String groupId = UUID.randomUUID().toString(); + User user = + randomTestUser().groups(Set.of(groupId)).buildAndStore(userService, "businessadmin"); + Workbasket workbasket = + defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); + createAccessItem(groupId, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); User userInDatabase = userService.getUser(user.getId()); @@ -446,11 +876,29 @@ class UserServiceAccTest { User user = randomTestUser().buildAndStore(userService, "businessadmin"); Workbasket workbasket = defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); - createAccessItem(user, workbasket, WorkbasketPermission.APPEND); + createAccessItem( + user.getId(), workbasket, WorkbasketPermission.READ, WorkbasketPermission.APPEND); User userInDatabase = userService.getUser(user.getId()); - assertThat(userInDatabase.getDomains()).isEmpty(); + assertThat(userInDatabase.getDomains()).containsExactly(workbasket.getDomain()); + } + + @WithAccessId(user = "user-1-1") + @Test + void should_ReturnOneDomain_When_GroupHasSufficientMinimalPermissionsToAssignDomains() + throws Exception { + String groupId = UUID.randomUUID().toString(); + User user = + randomTestUser().groups(Set.of(groupId)).buildAndStore(userService, "businessadmin"); + Workbasket workbasket = + defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); + createAccessItem( + groupId, workbasket, WorkbasketPermission.READ, WorkbasketPermission.APPEND); + + User userInDatabase = userService.getUser(user.getId()); + + assertThat(userInDatabase.getDomains()).containsExactly(workbasket.getDomain()); } } @@ -473,7 +921,23 @@ class UserServiceAccTest { User user = randomTestUser().buildAndStore(userService, "businessadmin"); Workbasket workbasket = defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); - createAccessItem(user, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + createAccessItem( + user.getId(), workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); + + User userInDatabase = userService.getUser(user.getId()); + + assertThat(userInDatabase.getDomains()).isEmpty(); + } + + @WithAccessId(user = "user-1-1") + @Test + void should_ReturnEmptyDomains_When_PropertyIsNotSetAndGroupHasPermission() throws Exception { + String groupId = UUID.randomUUID().toString(); + User user = + randomTestUser().groups(Set.of(groupId)).buildAndStore(userService, "businessadmin"); + Workbasket workbasket = + defaultTestWorkbasket().buildAndStore(workbasketService, "businessadmin"); + createAccessItem(groupId, workbasket, WorkbasketPermission.OPEN, WorkbasketPermission.READ); User userInDatabase = userService.getUser(user.getId()); 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 097f5864a..6f88c41bf 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 @@ -81,7 +81,7 @@ import pro.taskana.workbasket.internal.WorkbasketServiceImpl; public class TaskanaEngineImpl implements TaskanaEngine { // must match the VERSION value in table - private static final String MINIMAL_TASKANA_SCHEMA_VERSION = "5.0.0"; + private static final String MINIMAL_TASKANA_SCHEMA_VERSION = "5.2.0"; private static final Logger LOGGER = LoggerFactory.getLogger(TaskanaEngineImpl.class); private static final SessionStack SESSION_STACK = new SessionStack(); private final TaskRoutingManager taskRoutingManager; diff --git a/lib/taskana-core/src/main/java/pro/taskana/spi/user/api/RefreshUserPostprocessor.java b/lib/taskana-core/src/main/java/pro/taskana/spi/user/api/RefreshUserPostprocessor.java index 229dbbb3a..e643bd1a3 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/spi/user/api/RefreshUserPostprocessor.java +++ b/lib/taskana-core/src/main/java/pro/taskana/spi/user/api/RefreshUserPostprocessor.java @@ -11,7 +11,7 @@ public interface RefreshUserPostprocessor { /** * Processes a {@linkplain User} after its refresh. * - * @param userToProcess {@linkplain User} the User to preprocess + * @param userToProcess {@linkplain User} the User to postprocess * @return the {@linkplain User} after it has been processed */ User processUserAfterRefresh(User userToProcess); diff --git a/lib/taskana-core/src/main/java/pro/taskana/user/api/UserService.java b/lib/taskana-core/src/main/java/pro/taskana/user/api/UserService.java index 01e4bf1be..11b84bf52 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/user/api/UserService.java +++ b/lib/taskana-core/src/main/java/pro/taskana/user/api/UserService.java @@ -74,8 +74,10 @@ public interface UserService { * pro.taskana.common.api.TaskanaRole#BUSINESS_ADMIN business-admin} * @throws UserNotFoundException if there does not exist a {@linkplain User} with the specified * {@linkplain User#getId() id} inside the database + * @throws InvalidArgumentException if some fields are not set properly */ - User updateUser(User userToUpdate) throws UserNotFoundException, NotAuthorizedException; + User updateUser(User userToUpdate) + throws UserNotFoundException, NotAuthorizedException, InvalidArgumentException; /** * Deletes a {@linkplain User}. diff --git a/lib/taskana-core/src/main/java/pro/taskana/user/api/models/User.java b/lib/taskana-core/src/main/java/pro/taskana/user/api/models/User.java index 685a8fdff..36a31c6fc 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/user/api/models/User.java +++ b/lib/taskana-core/src/main/java/pro/taskana/user/api/models/User.java @@ -21,6 +21,20 @@ public interface User { */ void setId(String id); + /** + * Returns the groups of the User. + * + * @return userGroups + */ + Set getGroups(); + + /** + * Sets the groups of the User. + * + * @param groups the groups of the User + */ + void setGroups(Set groups); + /** * Returns the first name of the User. * diff --git a/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapper.java b/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapper.java index be523aafe..d8af72f23 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapper.java @@ -1,5 +1,6 @@ package pro.taskana.user.internal; +import java.util.Set; import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.InsertProvider; import org.apache.ibatis.annotations.Param; @@ -27,12 +28,21 @@ public interface UserMapper { @Result(property = "data", column = "DATA") UserImpl findById(@Param("id") String id); + @SelectProvider(type = UserMapperSqlProvider.class, method = "findGroupsById") + Set findGroupsById(String id); + @InsertProvider(type = UserMapperSqlProvider.class, method = "insert") void insert(User user); + @InsertProvider(type = UserMapperSqlProvider.class, method = "insertGroups") + void insertGroups(User user); + @UpdateProvider(type = UserMapperSqlProvider.class, method = "update") void update(User user); @DeleteProvider(type = UserMapperSqlProvider.class, method = "delete") void delete(String id); + + @DeleteProvider(type = UserMapperSqlProvider.class, method = "deleteGroups") + void deleteGroups(String id); } diff --git a/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapperSqlProvider.java b/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapperSqlProvider.java index fba0fbd93..9c52af3b9 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapperSqlProvider.java +++ b/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserMapperSqlProvider.java @@ -5,14 +5,13 @@ import static pro.taskana.common.internal.util.SqlProviderUtil.DB2_WITH_UR; import static pro.taskana.common.internal.util.SqlProviderUtil.OPENING_SCRIPT_TAG; public class UserMapperSqlProvider { - private static final String USER_INFO = "USER_INFO "; + private static final String USER_INFO_COLUMNS = "USER_ID, FIRST_NAME, LASTNAME, FULL_NAME, LONG_NAME, E_MAIL, PHONE, MOBILE_PHONE, " + "ORG_LEVEL_4, ORG_LEVEL_3, ORG_LEVEL_2, ORG_LEVEL_1, DATA "; private static final String USER_INFO_VALUES = "#{id}, #{firstName}, #{lastName}, #{fullName}, #{longName}, #{email}, #{phone}, " + "#{mobilePhone}, #{orgLevel4}, #{orgLevel3}, #{orgLevel2}, #{orgLevel1}, #{data} "; - private static final String WHERE_USER_ID = "WHERE USER_ID = #{id} "; private UserMapperSqlProvider() {} @@ -20,35 +19,48 @@ public class UserMapperSqlProvider { return OPENING_SCRIPT_TAG + "SELECT " + USER_INFO_COLUMNS - + "FROM " - + USER_INFO - + WHERE_USER_ID + + "FROM USER_INFO " + + "WHERE USER_ID = #{id} " + + DB2_WITH_UR + + CLOSING_SCRIPT_TAG; + } + + public static String findGroupsById() { + return OPENING_SCRIPT_TAG + + "SELECT GROUP_ID FROM GROUP_INFO WHERE USER_ID = #{id} " + DB2_WITH_UR + CLOSING_SCRIPT_TAG; } public static String insert() { - return "INSERT INTO " - + USER_INFO - + "( " - + USER_INFO_COLUMNS - + ") VALUES(" - + USER_INFO_VALUES - + ")"; + return "INSERT INTO USER_INFO ( " + USER_INFO_COLUMNS + ") VALUES(" + USER_INFO_VALUES + ")"; + } + + public static String insertGroups() { + return OPENING_SCRIPT_TAG + + "INSERT INTO GROUP_INFO " + + "(USER_ID, GROUP_ID) VALUES " + + "" + + "#{id}, #{group}" + + " " + + CLOSING_SCRIPT_TAG; } public static String update() { - return "UPDATE " - + USER_INFO + return "UPDATE USER_INFO " + "SET FIRST_NAME = #{firstName}, " + "LASTNAME = #{lastName}, FULL_NAME = #{fullName}, LONG_NAME = #{longName}, " + "E_MAIL = #{email}, PHONE = #{phone}, MOBILE_PHONE = #{mobilePhone}, " + "ORG_LEVEL_4 = #{orgLevel4}, ORG_LEVEL_3 = #{orgLevel3}, " + "ORG_LEVEL_2 = #{orgLevel2}, ORG_LEVEL_1 = #{orgLevel1}, DATA = #{data} " - + WHERE_USER_ID; + + "WHERE USER_ID = #{id} "; } public static String delete() { - return "DELETE FROM " + USER_INFO + WHERE_USER_ID; + return "DELETE FROM USER_INFO WHERE USER_ID = #{id} "; + } + + public static String deleteGroups() { + return "DELETE FROM GROUP_INFO WHERE USER_ID = #{id} "; } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserServiceImpl.java index b5e41e58a..5fa4f4fa2 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/user/internal/UserServiceImpl.java @@ -6,10 +6,12 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.apache.ibatis.exceptions.PersistenceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import pro.taskana.TaskanaEngineConfiguration; import pro.taskana.common.api.BaseQuery.SortDirection; import pro.taskana.common.api.TaskanaRole; import pro.taskana.common.api.exceptions.InvalidArgumentException; @@ -52,7 +54,13 @@ public class UserServiceImpl implements UserService { throw new UserNotFoundException(id); } - user.setDomains(determineDomains(user.getId())); + Set groups = + internalTaskanaEngine.executeInDatabaseConnection(() -> userMapper.findGroupsById(id)); + if (groups != null) { + user.setGroups(groups); + } + + user.setDomains(determineDomains(user)); return user; } @@ -62,24 +70,32 @@ public class UserServiceImpl implements UserService { internalTaskanaEngine .getEngine() .checkRoleMembership(TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN); - validateAndPopulateFields(userToCreate); + validateFields(userToCreate); + standardCreateActions(userToCreate); insertIntoDatabase(userToCreate); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Method createUser() created User '{}'.", userToCreate); } - return userToCreate; } @Override - public User updateUser(User userToUpdate) throws UserNotFoundException, NotAuthorizedException { + public User updateUser(User userToUpdate) + throws UserNotFoundException, NotAuthorizedException, InvalidArgumentException { internalTaskanaEngine .getEngine() .checkRoleMembership(TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN); - getUser(userToUpdate.getId()); + validateFields(userToUpdate); + standardUpdateActions(getUser(userToUpdate.getId()), userToUpdate); internalTaskanaEngine.executeInDatabaseConnection(() -> userMapper.update(userToUpdate)); + internalTaskanaEngine.executeInDatabaseConnection( + () -> userMapper.deleteGroups(userToUpdate.getId())); + if (userToUpdate.getGroups() != null && !userToUpdate.getGroups().isEmpty()) { + internalTaskanaEngine.executeInDatabaseConnection( + () -> userMapper.insertGroups(userToUpdate)); + } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Method updateUser() updated User '{}'.", userToUpdate); } @@ -94,13 +110,19 @@ public class UserServiceImpl implements UserService { .checkRoleMembership(TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN); getUser(id); - internalTaskanaEngine.executeInDatabaseConnection(() -> userMapper.delete(id)); + internalTaskanaEngine.executeInDatabaseConnection( + () -> { + userMapper.delete(id); + userMapper.deleteGroups(id); + }); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Method deleteUser() deleted User with id '{}'.", id); } } - private Set determineDomains(String... accessIds) { + private Set determineDomains(User user) { + Set accessIds = new HashSet<>(user.getGroups()); + accessIds.add(user.getId()); if (minimalWorkbasketPermissions != null && !minimalWorkbasketPermissions.isEmpty()) { // since WorkbasketService#accessIdsHavePermissions requires some role permissions we have to // execute this query as an admin. Since we're only determining the domains of a given user @@ -113,7 +135,8 @@ public class UserServiceImpl implements UserService { () -> workbasketService .createWorkbasketQuery() - .accessIdsHavePermissions(minimalWorkbasketPermissions, accessIds) + .accessIdsHavePermissions( + minimalWorkbasketPermissions, accessIds.toArray(String[]::new)) .listValues( WorkbasketQueryColumnName.DOMAIN, SortDirection.ASCENDING)))); } @@ -124,6 +147,9 @@ public class UserServiceImpl implements UserService { try { internalTaskanaEngine.openConnection(); userMapper.insert(userToCreate); + if (userToCreate.getGroups() != null && !userToCreate.getGroups().isEmpty()) { + userMapper.insertGroups(userToCreate); + } } catch (PersistenceException e) { throw new UserAlreadyExistException(userToCreate.getId(), e); } finally { @@ -131,19 +157,48 @@ public class UserServiceImpl implements UserService { } } - private void validateAndPopulateFields(User userToCreate) throws InvalidArgumentException { - if (userToCreate.getId() == null || userToCreate.getId().isEmpty()) { - throw new InvalidArgumentException("UserId must not be empty when creating User."); + private void validateFields(User userToValidate) throws InvalidArgumentException { + if (userToValidate.getId() == null || userToValidate.getId().isEmpty()) { + throw new InvalidArgumentException( + "UserId must not be empty when creating or updating User."); } - if (userToCreate.getFirstName() == null || userToCreate.getLastName() == null) { + if (userToValidate.getFirstName() == null || userToValidate.getLastName() == null) { throw new InvalidArgumentException("First and last name of User must be set or empty."); } + } - if (userToCreate.getFullName() == null || userToCreate.getFullName().isEmpty()) { - userToCreate.setFullName(userToCreate.getLastName() + ", " + userToCreate.getFirstName()); + private void standardCreateActions(User user) { + if (user.getFullName() == null || user.getFullName().isEmpty()) { + user.setFullName(user.getLastName() + ", " + user.getFirstName()); } - if (userToCreate.getLongName() == null || userToCreate.getLongName().isEmpty()) { - userToCreate.setLongName(userToCreate.getFullName() + " - (" + userToCreate.getId() + ")"); + if (user.getLongName() == null || user.getLongName().isEmpty()) { + user.setLongName(user.getFullName() + " - (" + user.getId() + ")"); + } + if (TaskanaEngineConfiguration.shouldUseLowerCaseForAccessIds()) { + user.setId(user.getId().toLowerCase()); + user.setGroups( + user.getGroups().stream().map((String::toLowerCase)).collect(Collectors.toSet())); + } + } + + private void standardUpdateActions(User oldUser, User newUser) { + if (!newUser.getFirstName().equals(oldUser.getFirstName()) + || !newUser.getLastName().equals(oldUser.getLastName())) { + if (newUser.getFullName() == null + || newUser.getFullName().isEmpty() + || newUser.getFullName().equals(oldUser.getFullName())) { + newUser.setFullName(newUser.getLastName() + ", " + newUser.getFirstName()); + } + if (newUser.getLongName() == null + || newUser.getLongName().isEmpty() + || newUser.getLongName().equals(oldUser.getLongName())) { + newUser.setLongName(newUser.getFullName() + " - (" + newUser.getId() + ")"); + } + } + if (TaskanaEngineConfiguration.shouldUseLowerCaseForAccessIds()) { + newUser.setId(newUser.getId().toLowerCase()); + newUser.setGroups( + newUser.getGroups().stream().map((String::toLowerCase)).collect(Collectors.toSet())); } } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/user/internal/models/UserImpl.java b/lib/taskana-core/src/main/java/pro/taskana/user/internal/models/UserImpl.java index 9bfa19d4e..d50ebf644 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/user/internal/models/UserImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/user/internal/models/UserImpl.java @@ -1,6 +1,6 @@ package pro.taskana.user.internal.models; -import java.util.HashSet; +import java.util.Collections; import java.util.Objects; import java.util.Set; @@ -8,6 +8,7 @@ import pro.taskana.user.api.models.User; public class UserImpl implements User { private String id; + private Set groups = Collections.emptySet(); private String firstName; private String lastName; private String fullName; @@ -20,12 +21,13 @@ public class UserImpl implements User { private String orgLevel2; private String orgLevel1; private String data; - private Set domains = new HashSet<>(); + private Set domains = Collections.emptySet(); public UserImpl() {} protected UserImpl(UserImpl copyFrom) { this.id = copyFrom.id; + this.groups = copyFrom.groups; this.firstName = copyFrom.firstName; this.lastName = copyFrom.lastName; this.fullName = copyFrom.fullName; @@ -51,6 +53,16 @@ public class UserImpl implements User { this.id = id; } + @Override + public Set getGroups() { + return groups; + } + + @Override + public void setGroups(Set groups) { + this.groups = groups; + } + @Override public String getFirstName() { return firstName; @@ -189,6 +201,7 @@ public class UserImpl implements User { public int hashCode() { return Objects.hash( id, + groups, firstName, lastName, fullName, @@ -217,6 +230,7 @@ public class UserImpl implements User { } UserImpl other = (UserImpl) obj; return Objects.equals(id, other.id) + && Objects.equals(groups, other.groups) && Objects.equals(firstName, other.firstName) && Objects.equals(lastName, other.lastName) && Objects.equals(fullName, other.fullName) @@ -236,9 +250,11 @@ public class UserImpl implements User { public String toString() { return "UserImpl [id=" + id + + ", groups=" + + groups + ", firstName=" + firstName - + ", lastname=" + + ", lastName=" + lastName + ", fullName=" + fullName diff --git a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryImpl.java index 894401097..cc494ebff 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryImpl.java @@ -34,7 +34,7 @@ public class WorkbasketQueryImpl implements WorkbasketQuery { private final List orderBy; private final List orderColumns; private WorkbasketQueryColumnName columnName; - private String[] accessId; + private String[] accessIds; private String[] idIn; private WorkbasketPermission[] permissions; private String[] nameIn; @@ -180,8 +180,8 @@ public class WorkbasketQueryImpl implements WorkbasketQuery { // set up permissions and ids this.permissions = permissions.toArray(WorkbasketPermission[]::new); - this.accessId = accessIds; - lowercaseAccessIds(this.accessId); + this.accessIds = accessIds; + lowercaseAccessIds(this.accessIds); return this; } @@ -423,8 +423,8 @@ public class WorkbasketQueryImpl implements WorkbasketQuery { } } - public String[] getAccessId() { - return accessId; + public String[] getAccessIds() { + return accessIds; } public WorkbasketPermission[] getPermissions() { @@ -618,25 +618,25 @@ public class WorkbasketQueryImpl implements WorkbasketQuery { joinWithAccessList = true; checkReadPermission = true; if (taskanaEngine.getEngine().isUserInRole(TaskanaRole.ADMIN, TaskanaRole.TASK_ADMIN) - && accessId == null) { + && accessIds == null) { checkReadPermission = false; joinWithAccessList = false; } else if (taskanaEngine.getEngine().isUserInRole(TaskanaRole.BUSINESS_ADMIN) && !usedToAugmentTasks) { checkReadPermission = false; - if (accessId == null && (permissions == null || permissions.length == 0)) { + if (accessIds == null && (permissions == null || permissions.length == 0)) { joinWithAccessList = false; } } - // might already be set by accessIdsHavePermission - if (this.accessId == null) { + // might already be set by accessIdsHavePermissions + if (this.accessIds == null) { String[] accessIds = new String[0]; List ucAccessIds = taskanaEngine.getEngine().getCurrentUserContext().getAccessIds(); if (!ucAccessIds.isEmpty()) { accessIds = ucAccessIds.toArray(accessIds); } - this.accessId = accessIds; - lowercaseAccessIds(this.accessId); + this.accessIds = accessIds; + lowercaseAccessIds(this.accessIds); } } } @@ -654,7 +654,7 @@ public class WorkbasketQueryImpl implements WorkbasketQuery { return "WorkbasketQueryImpl [columnName=" + columnName + ", accessId=" - + Arrays.toString(accessId) + + Arrays.toString(accessIds) + ", idIn=" + Arrays.toString(idIn) + ", permission=" diff --git a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryMapper.java b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryMapper.java index ae109df97..1bbae8b58 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketQueryMapper.java @@ -31,7 +31,7 @@ public interface WorkbasketQueryMapper { + "MAX(PERM_CUSTOM_8::int) as MAX_CUSTOM_8, MAX(PERM_CUSTOM_9::int) as MAX_CUSTOM_9, MAX(PERM_CUSTOM_10::int) as MAX_CUSTOM_10, MAX(PERM_CUSTOM_11::int) as MAX_CUSTOM_11, MAX(PERM_CUSTOM_12::int) as MAX_CUSTOM_12 " + "" + "" - + "FROM WORKBASKET_ACCESS_LIST where ACCESS_ID IN (#{item}) group by WORKBASKET_ID ) a " + + "FROM WORKBASKET_ACCESS_LIST where ACCESS_ID IN (#{item}) group by WORKBASKET_ID ) a " + "on (w.ID = a.WID)" + " " + " 1=1 " @@ -175,7 +175,7 @@ public interface WorkbasketQueryMapper { + "MAX(PERM_CUSTOM_8::int) as MAX_CUSTOM_8, MAX(PERM_CUSTOM_9::int) as MAX_CUSTOM_9, MAX(PERM_CUSTOM_10::int) as MAX_CUSTOM_10, MAX(PERM_CUSTOM_11::int) as MAX_CUSTOM_11, MAX(PERM_CUSTOM_12::int) as MAX_CUSTOM_12 " + "" + "" - + "FROM WORKBASKET_ACCESS_LIST where ACCESS_ID IN (#{item}) group by WORKBASKET_ID ) a " + + "FROM WORKBASKET_ACCESS_LIST where ACCESS_ID IN (#{item}) group by WORKBASKET_ID ) a " + "on (w.ID = a.WID)" + " " + " 1=1 " @@ -271,7 +271,7 @@ public interface WorkbasketQueryMapper { + "MAX(PERM_CUSTOM_8::int) as MAX_CUSTOM_8, MAX(PERM_CUSTOM_9::int) as MAX_CUSTOM_9, MAX(PERM_CUSTOM_10::int) as MAX_CUSTOM_10, MAX(PERM_CUSTOM_11::int) as MAX_CUSTOM_11, MAX(PERM_CUSTOM_12::int) as MAX_CUSTOM_12 " + "" + "" - + "FROM WORKBASKET_ACCESS_LIST where ACCESS_ID IN (#{item}) group by WORKBASKET_ID ) a " + + "FROM WORKBASKET_ACCESS_LIST where ACCESS_ID IN (#{item}) group by WORKBASKET_ID ) a " + "on (w.ID = a.WID)" + " " + "" diff --git a/lib/taskana-test-api/src/main/java/pro/taskana/testapi/builder/UserBuilder.java b/lib/taskana-test-api/src/main/java/pro/taskana/testapi/builder/UserBuilder.java index b2ffbd563..a14e19db8 100644 --- a/lib/taskana-test-api/src/main/java/pro/taskana/testapi/builder/UserBuilder.java +++ b/lib/taskana-test-api/src/main/java/pro/taskana/testapi/builder/UserBuilder.java @@ -1,5 +1,7 @@ package pro.taskana.testapi.builder; +import java.util.Set; + import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.user.api.UserService; @@ -22,6 +24,11 @@ public class UserBuilder implements EntityBuilder { return this; } + public UserBuilder groups(Set groups) { + testUser.setGroups(groups); + return this; + } + public UserBuilder firstName(String firstName) { testUser.setFirstName(firstName); return this; diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java index f9edb1a69..a8700f172 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java @@ -4,8 +4,10 @@ import static java.util.function.Predicate.not; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -536,6 +538,7 @@ public class LdapClient { String[] getLookUpUserInfoAttributesToReturn() { return new String[] { getUserIdAttribute(), + getUserMemberOfGroupAttribute(), getUserFirstnameAttribute(), getUserLastnameAttribute(), getUserFullnameAttribute(), @@ -615,6 +618,19 @@ public class LdapClient { } } + private Set getGroupIdsFromContext(final DirContextOperations context) { + String[] groupAttributes = context.getStringAttributes(getUserMemberOfGroupAttribute()); + Set groups = groupAttributes != null ? Set.of(groupAttributes) : Collections.emptySet(); + if (useLowerCaseForAccessIds) { + groups = + groups.stream() + .filter(Objects::nonNull) + .map(String::toLowerCase) + .collect(Collectors.toSet()); + } + return groups; + } + /** Context Mapper for user entries. */ class GroupContextMapper extends AbstractContextMapper { @@ -634,6 +650,7 @@ public class LdapClient { public User doMapFromContext(final DirContextOperations context) { final User user = new UserImpl(); user.setId(getUserIdFromContext(context)); + user.setGroups(getGroupIdsFromContext(context)); user.setFirstName(context.getStringAttribute(getUserFirstnameAttribute())); user.setLastName(context.getStringAttribute(getUserLastnameAttribute())); user.setFullName(context.getStringAttribute(getUserFullnameAttribute())); diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/user/jobs/UserInfoRefreshJob.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/user/jobs/UserInfoRefreshJob.java index 4a5c56981..6ce05fa23 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/user/jobs/UserInfoRefreshJob.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/user/jobs/UserInfoRefreshJob.java @@ -27,7 +27,7 @@ public class UserInfoRefreshJob extends AbstractTaskanaJob { private static final Logger LOGGER = LoggerFactory.getLogger(UserInfoRefreshJob.class); private final SqlConnectionRunner sqlConnectionRunner; - private RefreshUserPostprocessorManager refreshUserPostprocessorManager; + private final RefreshUserPostprocessorManager refreshUserPostprocessorManager; public UserInfoRefreshJob(TaskanaEngine taskanaEngine) { this(taskanaEngine, null, null); @@ -77,7 +77,7 @@ public class UserInfoRefreshJob extends AbstractTaskanaJob { .map(user -> refreshUserPostprocessorManager.processUserAfterRefresh(user)) .collect(Collectors.toList()); addExistingConfigurationDataToUsers(usersAfterProcessing); - clearExistingUsers(); + clearExistingUsersAndGroups(); insertNewUsers(usersAfterProcessing); LOGGER.info("Job to refresh all user info has finished."); @@ -87,13 +87,19 @@ public class UserInfoRefreshJob extends AbstractTaskanaJob { } } - private void clearExistingUsers() { + private void clearExistingUsersAndGroups() { sqlConnectionRunner.runWithConnection( connection -> { - String sql = "DELETE FROM USER_INFO"; + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Trying to delete all users and groups"); + } + String sql = "DELETE FROM USER_INFO; DELETE FROM GROUP_INFO"; PreparedStatement statement = connection.prepareStatement(sql); statement.execute(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Successfully deleted all users and groups"); + } if (!connection.getAutoCommit()) { connection.commit(); @@ -132,7 +138,7 @@ public class UserInfoRefreshJob extends AbstractTaskanaJob { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Trying to set userData {} for user {}", userData, user); } - user.setData(taskanaEngineImpl.getUserService().getUser(user.getId()).getData()); + user.setData(userData); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Successfully set userData {} for user {}", userData, user); } diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssembler.java index d57078403..de61781f4 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssembler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssembler.java @@ -19,6 +19,7 @@ public class UserRepresentationModelAssembler public UserRepresentationModel toModel(User entity) { UserRepresentationModel repModel = new UserRepresentationModel(); repModel.setUserId(entity.getId()); + repModel.setGroups(entity.getGroups()); repModel.setFirstName(entity.getFirstName()); repModel.setLastName(entity.getLastName()); repModel.setFullName(entity.getFullName()); @@ -38,6 +39,7 @@ public class UserRepresentationModelAssembler public User toEntityModel(UserRepresentationModel repModel) { UserImpl user = new UserImpl(); user.setId(repModel.getUserId()); + user.setGroups(repModel.getGroups()); user.setFirstName(repModel.getFirstName()); user.setLastName(repModel.getLastName()); user.setFullName(repModel.getFullName()); diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/models/UserRepresentationModel.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/models/UserRepresentationModel.java index baa6222f7..9265be40d 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/models/UserRepresentationModel.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/user/rest/models/UserRepresentationModel.java @@ -1,6 +1,7 @@ package pro.taskana.user.rest.models; import java.util.Objects; +import java.util.Set; import javax.validation.constraints.NotNull; import org.springframework.hateoas.RepresentationModel; @@ -11,6 +12,8 @@ public class UserRepresentationModel extends RepresentationModel groups; /** The first name of the User. */ protected String firstName; /** The last name of the User. */ @@ -44,6 +47,14 @@ public class UserRepresentationModel extends RepresentationModel getGroups() { + return groups; + } + + public void setGroups(Set groups) { + this.groups = groups; + } + public String getFirstName() { return firstName; } @@ -145,6 +156,7 @@ public class UserRepresentationModel extends RepresentationModel ldapusers = ldapClient.searchUsersInUserRole(); + users.sort(Comparator.comparing(User::getId)); + ldapusers.sort(Comparator.comparing(User::getId)); + + RecursiveComparisonConfiguration comparisonConfiguration = + RecursiveComparisonConfiguration.builder() + .withIgnoredCollectionOrderInFields("groups") + .withIgnoredFields("longName", "data", "orgLevel1", "domains") + .build(); assertThat(users) .hasSize(6) .hasSameSizeAs(ldapusers) - .usingRecursiveFieldByFieldElementComparatorIgnoringFields( - "longName", "data", "orgLevel1") + .usingRecursiveFieldByFieldElementComparator(comparisonConfiguration) .containsExactlyElementsOf(ldapusers); } } @@ -73,7 +77,7 @@ class UserInfoRefreshJobIntTest { @Test @WithAccessId(user = "businessadmin") @Order(2) - void should_PostprocessUser_When_RefrehUserPostprocessorIsActive() throws Exception { + void should_PostprocessUser_When_RefreshUserPostprocessorIsActive() throws Exception { try (Connection connection = taskanaEngine.getConfiguration().getDatasource().getConnection()) { @@ -95,29 +99,14 @@ class UserInfoRefreshJobIntTest { private List getUsers(Connection connection) throws Exception { - List users = new ArrayList<>(); + List users = new ArrayList<>(); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery("SELECT * FROM " + connection.getSchema() + ".USER_INFO"); while (rs.next()) { - User ldapUser = new UserImpl(); - ldapUser.setId(rs.getString("USER_ID")); - ldapUser.setFirstName(rs.getString("FIRST_NAME")); - ldapUser.setLastName(rs.getString("LASTNAME")); - ldapUser.setFullName(rs.getString("FULL_NAME")); - ldapUser.setLongName(rs.getString("LONG_NAME")); - ldapUser.setEmail(rs.getString("E_MAIL")); - ldapUser.setPhone(rs.getString("PHONE")); - ldapUser.setMobilePhone(rs.getString("MOBILE_PHONE")); - ldapUser.setOrgLevel4(rs.getString("ORG_LEVEL_4")); - ldapUser.setOrgLevel3(rs.getString("ORG_LEVEL_3")); - ldapUser.setOrgLevel2(rs.getString("ORG_LEVEL_2")); - ldapUser.setOrgLevel1(rs.getString("ORG_LEVEL_1")); - ldapUser.setData(rs.getString("DATA")); - - users.add(ldapUser); + users.add(rs.getString("USER_ID")); } - return users; + return users.stream().map(wrap(userService::getUser)).collect(Collectors.toList()); } } diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/UserControllerIntTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/UserControllerIntTest.java index 09c9673a6..4b1aaff74 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/UserControllerIntTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/UserControllerIntTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static pro.taskana.common.test.rest.RestHelper.TEMPLATE; +import java.util.Set; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -47,6 +48,7 @@ class UserControllerIntTest { void should_CreateValidUser_When_CallingCreateEndpoint() throws Exception { UserRepresentationModel newUser = new UserRepresentationModel(); newUser.setUserId("12345"); + newUser.setGroups(Set.of("group1", "group2")); newUser.setFirstName("Hans"); newUser.setLastName("Georg"); newUser.setFullName("Georg, Hans"); @@ -75,8 +77,7 @@ class UserControllerIntTest { HttpMethod.GET, auth, ParameterizedTypeReference.forType(UserRepresentationModel.class)); - assertThat(responseEntity.getBody()).isNotNull(); - assertThat(responseEntity.getBody()).isEqualTo(newUser); + assertThat(responseEntity.getBody()).isNotNull().isEqualTo(newUser); } @Test diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssemblerTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssemblerTest.java index c2d97ceb5..72ee5a357 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssemblerTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/user/rest/assembler/UserRepresentationModelAssemblerTest.java @@ -2,6 +2,7 @@ package pro.taskana.user.rest.assembler; import static org.assertj.core.api.Assertions.assertThat; +import java.util.Set; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +28,7 @@ class UserRepresentationModelAssemblerTest { void should_ReturnRepresentationModel_When_ConvertingUserEntityToRepresentationModel() { User user = userService.newUser(); user.setId("user-1-2"); + user.setGroups(Set.of("group1", "group2")); user.setFirstName("Hans"); user.setLastName("Georg"); user.setFullName("Hans Georg"); @@ -48,6 +50,7 @@ class UserRepresentationModelAssemblerTest { void should_ReturnEntity_When_ConvertingUserRepresentationModelToEntity() { UserRepresentationModel repModel = new UserRepresentationModel(); repModel.setUserId("user-1-2"); + repModel.setGroups(Set.of("group1", "group2")); repModel.setFirstName("Hans"); repModel.setLastName("Georg"); repModel.setFullName("Hans Georg"); @@ -69,6 +72,7 @@ class UserRepresentationModelAssemblerTest { void should_BeEqual_When_ConvertingEntityToRepModelAndBackToEntity() { User user = userService.newUser(); user.setId("user-1-2"); + user.setGroups(Set.of("group1", "group2")); user.setFirstName("Hans"); user.setLastName("Georg"); user.setFullName("Hans Georg"); @@ -92,11 +96,11 @@ class UserRepresentationModelAssemblerTest { } private static void testEquality(User entity, UserRepresentationModel repModel) { - assertThat(entity).hasNoNullFieldsOrProperties(); assertThat(entity).hasNoNullFieldsOrProperties(); assertThat(repModel).hasNoNullFieldsOrProperties(); assertThat(entity.getId()).isEqualTo(repModel.getUserId()); + assertThat(entity.getGroups()).isEqualTo(repModel.getGroups()); assertThat(entity.getFirstName()).isEqualTo(repModel.getFirstName()); assertThat(entity.getLastName()).isEqualTo(repModel.getLastName()); assertThat(entity.getFullName()).isEqualTo(repModel.getFullName());