diff --git a/README.adoc b/README.adoc index 4b96f57b2b..92615b494f 100644 --- a/README.adoc +++ b/README.adoc @@ -82,7 +82,8 @@ cd operatorfabric-core . Launch our demo docker-compose file + ---- -./config/docker/docker-compose.sh +cd ./config/docker +./docker-compose.sh ---- . After a little while, log into the application UI at *localhost:2002/ui/* using admin/test as credentials. diff --git a/VERSION b/VERSION index 00e28c7445..b62f96aa2f 100755 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0.RELEASE +2.1.0.RELEASE diff --git a/bin/run_all.sh b/bin/run_all.sh index fc38dd0dee..d573970160 100755 --- a/bin/run_all.sh +++ b/bin/run_all.sh @@ -118,7 +118,7 @@ startProject(){ cd $OF_HOME java -Xss512k -XX:MaxRAM=512m $debugOptions \ -jar $projectBuildPath/libs/$1-$version.jar \ - $applicationOptions 2>&1 > $projectBuildPath/logs/$(date -I).log & + $applicationOptions 2>&1 > $projectBuildPath/logs/$(date \+"%y-%m-%d").log & # set +x echo $! > $projectBuildPath/PIDFILE @@ -166,7 +166,7 @@ stopCommand(){ for ((i=0; i<${#dependentProjects[*]}; )); do stopProject ${dependentProjects[i]} ${dependentProjects[i+1]} - i=$((i+"$PRJ_STRC_FIELDS")) + i=$((i+$PRJ_STRC_FIELDS)) done } @@ -192,7 +192,7 @@ hardstopCommand(){ for ((i=0; i<${#dependentProjects[*]}; )); do hardstopProject ${dependentProjects[i]} ${dependentProjects[i+1]} - i=$((i+"$PRJ_STRC_FIELDS")) + i=$((i+$PRJ_STRC_FIELDS)) done } diff --git a/client/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/model/TypeOfStateEnum.java b/client/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/model/TypeOfStateEnum.java new file mode 100644 index 0000000000..cff34fd347 --- /dev/null +++ b/client/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/model/TypeOfStateEnum.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2018-2021, RTE (http://www.rte-france.com) + * See AUTHORS.txt + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + * This file is part of the OperatorFabric project. + */ + +package org.lfenergy.operatorfabric.businessconfig.model; + +/** + * Type of state + *
+ *
INPROGRESS
In progress
+ *
FINISHED
Finished
+ *
CANCELED
Canceled
+ *
+ * Note : This enum is created by hand because Swagger can't handle enums. It should match the corresponding + * enum definition in the Cards API. + * + * + */ +public enum TypeOfStateEnum { + INPROGRESS, FINISHED, CANCELED +} + diff --git a/client/businessconfig/src/main/modeling/config.json b/client/businessconfig/src/main/modeling/config.json index 65fdd8dd78..e74ee4f015 100755 --- a/client/businessconfig/src/main/modeling/config.json +++ b/client/businessconfig/src/main/modeling/config.json @@ -16,6 +16,7 @@ "ActionEnum": "org.lfenergy.operatorfabric.businessconfig.model.ActionEnum", "ResponseBtnColorEnum": "org.lfenergy.operatorfabric.businessconfig.model.ResponseBtnColorEnum", "LinkTypeEnum": "org.lfenergy.operatorfabric.businessconfig.model.LinkTypeEnum", + "TypeOfStateEnum": "org.lfenergy.operatorfabric.businessconfig.model.TypeOfStateEnum", "EpochDate": "java.time.Instant", "LongInteger": "java.lang.Long" } diff --git a/config/dev/docker-compose.yml b/config/dev/docker-compose.yml index 36c8594766..ca37db1af9 100755 --- a/config/dev/docker-compose.yml +++ b/config/dev/docker-compose.yml @@ -26,7 +26,7 @@ services: - "89:8080" - "90:9990" web-ui: - image: "lfeoperatorfabric/of-web-ui:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-web-ui:2.1.0.RELEASE" #user: ${USER_ID}:${USER_GID} ports: - "2002:80" @@ -38,6 +38,6 @@ services: - "./nginx.conf:/etc/nginx/conf.d/default.conf" - "./loggingResults:/etc/nginx/html/logging" ext-app: - image: "lfeoperatorfabric/of-external-app:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-external-app:2.1.0.RELEASE" ports: - "8090:8090" diff --git a/config/dev/nginx.conf.template b/config/dev/nginx.conf.template index 6b9c67d86c..7ca8893dd7 100644 --- a/config/dev/nginx.conf.template +++ b/config/dev/nginx.conf.template @@ -111,75 +111,7 @@ server { proxy_pass http://${MY_DOCKER_HOST}:2103/users; } - location ~ "^/users/(.*)" { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://${MY_DOCKER_HOST}:2103/$1; - } - - location /groups { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://${MY_DOCKER_HOST}:2103/groups; - } - - location ~ "^/groups/(.*)" { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://${MY_DOCKER_HOST}:2103/$1; - } - - location /entities { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://${MY_DOCKER_HOST}:2103/entities; - } - - location ~ "^/entities/(.*)" { + location ~ "^/users/(.*)" { # enables `ng serve` mode if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; diff --git a/config/dev/web-ui.json b/config/dev/web-ui.json index 1a454cf2fe..5056800b7b 100644 --- a/config/dev/web-ui.json +++ b/config/dev/web-ui.json @@ -1,5 +1,7 @@ { "title": "OperatorFabric (Dev Mode)", + "environmentName": "DEV ENV", + "environmentColor": "green", "checkPerimeterForResponseCard": true, "archive": { "filters": { diff --git a/config/docker/docker-compose.sh b/config/docker/docker-compose.sh index 576d47d5b3..1e3bffa846 100755 --- a/config/docker/docker-compose.sh +++ b/config/docker/docker-compose.sh @@ -1,7 +1,21 @@ #!/bin/bash +echo "Usage: " +echo " 1: ./docker-compose.sh" +echo " 2: ./docker-compose.sh " + echo USER_ID="$(id -u)" > .env echo USER_GID="$(id -g)" >> .env # create directory for bundle storage if not existing mkdir -p businessconfig-storage +if [ "$#" -eq 0 ]; then + echo CONFIG_PATH=./ >> .env + echo SPRING_PROFILES_ACTIVE=docker >> .env +else + EXTERNAL_CONFIGURATION_FILE=$1 + CONFIG_PATH=$(dirname "$1") + cat ${EXTERNAL_CONFIGURATION_FILE} >> .env + echo CONFIG_PATH="$CONFIG_PATH" >> .env +fi +cat .env docker-compose up -d diff --git a/config/docker/docker-compose.yml b/config/docker/docker-compose.yml index 7c91ede53b..fa60811700 100755 --- a/config/docker/docker-compose.yml +++ b/config/docker/docker-compose.yml @@ -28,19 +28,22 @@ services: # - "90:9990" users: container_name: users - image: "lfeoperatorfabric/of-users-business-service:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-users-business-service:2.1.0.RELEASE" user: ${USER_ID}:${USER_GID} ports: - "2103:8080" # Debug port closed for security reasons, be careful if you open it # - "4103:5005" + environment: + - SPRING_PROFILES_ACTIVE volumes: - "../certificates:/certificates_to_add" - "./users-docker.yml:/config/application.yml" - "./common-docker.yml:/config/common-docker.yml" + - ${CONFIG_PATH}:/external-config businessconfig: container_name: businessconfig - image: "lfeoperatorfabric/of-businessconfig-business-service:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-businessconfig-business-service:2.1.0.RELEASE" depends_on: - mongodb user: ${USER_ID}:${USER_GID} @@ -48,14 +51,17 @@ services: - "2100:8080" # Debug port closed for security reasons, be careful if you open it # - "4100:5005" + environment: + - SPRING_PROFILES_ACTIVE volumes: - "../certificates:/certificates_to_add" - "./businessconfig-storage:/businessconfig-storage" - "./common-docker.yml:/config/common-docker.yml" - "./businessconfig-docker.yml:/config/application-docker.yml" + - ${CONFIG_PATH}:/external-config cards-publication: container_name: cards-publication - image: "lfeoperatorfabric/of-cards-publication-business-service:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-cards-publication-business-service:2.1.0.RELEASE" depends_on: - mongodb user: ${USER_ID}:${USER_GID} @@ -63,24 +69,30 @@ services: - "2102:8080" # Debug port closed for security reasons, be careful if you open it # - "4102:5005" + environment: + - SPRING_PROFILES_ACTIVE volumes: - "../certificates:/certificates_to_add" - "./common-docker.yml:/config/common-docker.yml" - "./cards-publication-docker.yml:/config/application-docker.yml" + - ${CONFIG_PATH}:/external-config cards-consultation: container_name: cards-consultation - image: "lfeoperatorfabric/of-cards-consultation-business-service:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-cards-consultation-business-service:2.1.0.RELEASE" user: ${USER_ID}:${USER_GID} ports: - "2104:8080" # Debug port closed for security reasons, be careful if you open it # - "4104:5005" + environment: + - SPRING_PROFILES_ACTIVE volumes: - "../certificates:/certificates_to_add" - "./common-docker.yml:/config/common-docker.yml" - "./cards-consultation-docker.yml:/config/application-docker.yml" + - ${CONFIG_PATH}:/external-config web-ui: - image: "lfeoperatorfabric/of-web-ui:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-web-ui:2.1.0.RELEASE" ports: - "2002:80" depends_on: @@ -93,6 +105,6 @@ services: - "./nginx.conf:/etc/nginx/conf.d/default.conf" ext-app: # External application example, must not be activated in production mode - image: "lfeoperatorfabric/of-external-app:2.0.0.RELEASE" + image: "lfeoperatorfabric/of-external-app:2.1.0.RELEASE" ports: - "8090:8090" diff --git a/config/docker/nginx-cors-permissive.conf b/config/docker/nginx-cors-permissive.conf index 2607a933f3..6afac828d0 100644 --- a/config/docker/nginx-cors-permissive.conf +++ b/config/docker/nginx-cors-permissive.conf @@ -127,74 +127,6 @@ server { proxy_pass http://users:8080/users; } - location /groups { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://users:8080/groups; - } - - location ~ "^/groups/(.*)" { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://users:8080/$1; - } - - location /entities { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://users:8080/entities; - } - - location ~ "^/entities/(.*)" { - # enables `ng serve` mode - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Credentials' 'true'; - add_header 'Access-Control-Allow-Methods' '*'; - add_header 'Access-Control-Allow-Headers' '*'; - add_header 'Content-Length' 0; - add_header 'Vary' 'Origin'; - add_header 'Vary' 'Access-Control-Request-Method' ; - add_header 'Vary' 'Access-Control-Request-Headers'; - return 204; - } - proxy_set_header Host $http_host; - proxy_pass http://users:8080/$1; - } - location /cards/ { # enables `ng serve` mode if ($request_method = 'OPTIONS') { diff --git a/config/docker/nginx.conf b/config/docker/nginx.conf index ee9aca4b4a..1d7d65f73e 100644 --- a/config/docker/nginx.conf +++ b/config/docker/nginx.conf @@ -50,23 +50,6 @@ server { location ~ "^/users/(.*)" { proxy_set_header Host $http_host; proxy_pass http://users:8080/$1; - } - location ~ "^/entities/(.*)" { - proxy_set_header Host $http_host; - proxy_pass http://users:8080/$1; - } - location /entities { - proxy_set_header Host $http_host; - proxy_pass http://users:8080/entities; - } - - location ~ "^/groups/(.*)" { - proxy_set_header Host $http_host; - proxy_pass http://users:8080/$1; - } - location /groups { - proxy_set_header Host $http_host; - proxy_pass http://users:8080/groups; } location /cards/ { proxy_set_header Host $http_host; diff --git a/config/docker/web-ui.json b/config/docker/web-ui.json index a9b5cf5462..8c46b5ade8 100644 --- a/config/docker/web-ui.json +++ b/config/docker/web-ui.json @@ -1,4 +1,6 @@ { + "environmentName": "TEST ENV", + "environmentColor": "blue", "checkPerimeterForResponseCard": true, "archive": { "filters": { diff --git a/services/core/businessconfig/build.gradle b/services/core/businessconfig/build.gradle index 2b35360501..e08c51d4d4 100755 --- a/services/core/businessconfig/build.gradle +++ b/services/core/businessconfig/build.gradle @@ -47,6 +47,20 @@ task copyProcessGroupsFile(type: Exec){ args "-c", "cp processgroups.json $project.projectDir/build/test-data/" } +task copyProcessGroupsFile2(type: Exec) { + description 'copy processgroups_with_duplicate_in_same_group.json file for businessconfig party configuration data for tests in build/test-data' + workingDir "$project.projectDir/src/test/data/" + executable "bash" + args "-c", "cp processgroups_with_duplicate_in_same_group.json $project.projectDir/build/test-data/" +} + +task copyProcessGroupsFile3(type: Exec) { + description 'copy processgroups_with_duplicate_in_different_groups.json file for businessconfig party configuration data for tests in build/test-data' + workingDir "$project.projectDir/src/test/data/" + executable "bash" + args "-c", "cp processgroups_with_duplicate_in_different_groups.json $project.projectDir/build/test-data/" +} + task createDevData(type: Copy){ description 'prepare data in build/test-data for running bootRun task during development' from 'src/main/docker/volume/businessconfig-storage' @@ -86,8 +100,10 @@ createDevData.dependsOn prepareDevDataDir compressBundle1Data.dependsOn prepareTestDataDir compressBundle2Data.dependsOn prepareTestDataDir copyProcessGroupsFile.dependsOn prepareTestDataDir -test.dependsOn prepareTestDataDir,compressBundle1Data,compressBundle2Data,copyProcessGroupsFile -unitTest.dependsOn prepareTestDataDir,compressBundle1Data,compressBundle2Data,copyProcessGroupsFile +copyProcessGroupsFile2.dependsOn prepareTestDataDir +copyProcessGroupsFile3.dependsOn prepareTestDataDir +test.dependsOn prepareTestDataDir,compressBundle1Data,compressBundle2Data,copyProcessGroupsFile,copyProcessGroupsFile2,copyProcessGroupsFile3 +unitTest.dependsOn prepareTestDataDir,compressBundle1Data,compressBundle2Data,copyProcessGroupsFile,copyProcessGroupsFile2,copyProcessGroupsFile3 bootRun.dependsOn createDevData // <<<<< Test data tasks diff --git a/services/core/businessconfig/src/main/docker/Dockerfile b/services/core/businessconfig/src/main/docker/Dockerfile index 09d933de60..3edfe32b9f 100755 --- a/services/core/businessconfig/src/main/docker/Dockerfile +++ b/services/core/businessconfig/src/main/docker/Dockerfile @@ -12,6 +12,9 @@ RUN apk add bash curl --no-cache ENV http_proxy="" ENV https_proxy="" ENV HTTP_PROXY_AUTH="" +ENV SPRING_CONFIG_NAME common,application,businessconfig +ENV SPRING_PROFILES_ACTIVE docker +ENV SPRING_CONFIG_LOCATION ./config/,./external-config/ RUN env COPY add-certificates.sh /add-certificates.sh COPY java-config-docker-entrypoint.sh /docker-entrypoint.sh diff --git a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/1/config.json b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/1/config.json index 404f2755a9..22269b71e2 100755 --- a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/1/config.json +++ b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/1/config.json @@ -12,9 +12,6 @@ "firstState": { "name": "state.label", "color": "blue", - "detailTitle": { - "key": "template.title" - }, "templateName": "operation", "acknowledgmentAllowed": "Never" } diff --git a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/config.json b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/config.json index 404f2755a9..22269b71e2 100755 --- a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/config.json +++ b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/TEST/config.json @@ -12,9 +12,6 @@ "firstState": { "name": "state.label", "color": "blue", - "detailTitle": { - "key": "template.title" - }, "templateName": "operation", "acknowledgmentAllowed": "Never" } diff --git a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/config.json b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/config.json index db1ee3456b..0efc8daddc 100755 --- a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/config.json +++ b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/config.json @@ -15,9 +15,6 @@ "firstState": { "name": "firstState.label", "color": "blue", - "detailTitle": { - "key": "template1.title" - }, "templateName": "template1", "acknowledgmentAllowed": "Never" } diff --git a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/v1/config.json b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/v1/config.json index db1ee3456b..0efc8daddc 100755 --- a/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/v1/config.json +++ b/services/core/businessconfig/src/main/docker/volume/businessconfig-storage/first/v1/config.json @@ -15,9 +15,6 @@ "firstState": { "name": "firstState.label", "color": "blue", - "detailTitle": { - "key": "template1.title" - }, "templateName": "template1", "acknowledgmentAllowed": "Never" } diff --git a/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/controllers/BusinessconfigController.java b/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/controllers/BusinessconfigController.java index bcfa9bf1aa..496cfbd243 100644 --- a/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/controllers/BusinessconfigController.java +++ b/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/controllers/BusinessconfigController.java @@ -12,15 +12,14 @@ package org.lfenergy.operatorfabric.businessconfig.controllers; import lombok.extern.slf4j.Slf4j; -import org.lfenergy.operatorfabric.springtools.error.model.ApiError; -import org.lfenergy.operatorfabric.springtools.error.model.ApiErrorException; -import org.lfenergy.operatorfabric.businessconfig.model.*; import org.lfenergy.operatorfabric.businessconfig.model.Process; +import org.lfenergy.operatorfabric.businessconfig.model.*; import org.lfenergy.operatorfabric.businessconfig.services.ProcessesService; +import org.lfenergy.operatorfabric.springtools.error.model.ApiError; +import org.lfenergy.operatorfabric.springtools.error.model.ApiErrorException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @@ -32,7 +31,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; -import java.util.Map; /** * BusinessconfigController, documented at {@link BusinessconfigApi} diff --git a/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/model/ProcessStatesData.java b/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/model/ProcessStatesData.java index 40e4bbe7f2..55d7380501 100644 --- a/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/model/ProcessStatesData.java +++ b/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/model/ProcessStatesData.java @@ -12,7 +12,6 @@ import lombok.*; -import java.util.ArrayList; import java.util.List; @Data @@ -27,10 +26,10 @@ public class ProcessStatesData implements ProcessStates { private String description; private Boolean showDetailCardHeader; private UserCard userCard; - private I18n detailTitle; private String templateName; @Singular private List styles; + private TypeOfStateEnum type; @Override public Response getResponse() { @@ -47,4 +46,10 @@ public void setResponse(Response responseData) { @Override public void setAcknowledgmentAllowed(AcknowledgmentAllowedEnum acknowledgmentAllowed) { this.acknowledgmentAllowed = acknowledgmentAllowed; } + + @Override + public TypeOfStateEnum getType() { return this.type; } + + @Override + public void setType(TypeOfStateEnum type) { this.type = type; } } diff --git a/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesService.java b/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesService.java index 5eae82e10b..ec19a806a0 100644 --- a/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesService.java +++ b/services/core/businessconfig/src/main/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesService.java @@ -37,12 +37,15 @@ import org.lfenergy.operatorfabric.businessconfig.model.*; import org.lfenergy.operatorfabric.businessconfig.model.Process; +import org.lfenergy.operatorfabric.springtools.error.model.ApiError; +import org.lfenergy.operatorfabric.springtools.error.model.ApiErrorException; import org.lfenergy.operatorfabric.utilities.PathUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @@ -62,6 +65,8 @@ public class ProcessesService implements ResourceLoaderAware { private static final String PATH_PREFIX = "file:"; private static final String CONFIG_FILE_NAME = "config.json"; + private static final String DUPLICATE_PROCESS_IN_PROCESS_GROUPS_FILE = "There is a duplicate process in the file you have sent"; + @Value("${operatorfabric.businessconfig.storage.path}") private String storagePath; private ObjectMapper objectMapper; @@ -309,6 +314,20 @@ public synchronized Process updateProcess(InputStream is) throws IOException { } } + public boolean checkNoDuplicateProcessInUploadedFile(ProcessGroupsData newProcessGroups) { + HashMap mapOfProcesses = new HashMap<>(); + + for (ProcessGroup group : newProcessGroups.getGroups()) { + for (String process : group.getProcesses()) { + if (mapOfProcesses.containsKey(process)) + return false; + else + mapOfProcesses.put(process, 1); + } + } + return true; + } + /** * Updates or creates processgroups file from a file uploaded from POST /businessconfig/processgroups * @@ -325,6 +344,13 @@ public synchronized void updateProcessGroupsFile(InputStream is) throws IOExcept ProcessGroupsData newProcessGroups = objectMapper.readValue(is, ProcessGroupsData.class); is.reset(); + if (! checkNoDuplicateProcessInUploadedFile(newProcessGroups)) + throw new ApiErrorException( + ApiError.builder() + .status(HttpStatus.BAD_REQUEST) + .message(DUPLICATE_PROCESS_IN_PROCESS_GROUPS_FILE) + .build()); + //copy file PathUtils.copyInputStreamToFile(is, rootPath.toString() + "/processGroups.json"); diff --git a/services/core/businessconfig/src/main/modeling/swagger.yaml b/services/core/businessconfig/src/main/modeling/swagger.yaml index 982f97f07c..c192a1fef4 100755 --- a/services/core/businessconfig/src/main/modeling/swagger.yaml +++ b/services/core/businessconfig/src/main/modeling/swagger.yaml @@ -1,7 +1,7 @@ swagger: '2.0' info: description: OperatorFabric BusinessconfigParty Management API - version: 2.0.0.RELEASE + version: 2.1.0.RELEASE title: Businessconfig Management termsOfService: '' contact: @@ -371,9 +371,6 @@ definitions: userCard: description : User card template and visibility options $ref: '#/definitions/UserCard' - detailTitle: - description: Detail i18n title - $ref: '#/definitions/I18n' templateName: description: >- Name of the template to use @@ -384,6 +381,9 @@ definitions: type: array items: type: string + type: + description: Type of state ("INPROGRESS", "FINISHED" or "CANCELED") + $ref: '#/definitions/TypeOfStateEnum' uiVisibility: type: object properties: @@ -404,16 +404,8 @@ definitions: name: some_business_process.label version: v1.0 initial_state: - detailTitle: - key: template.title - parameters: - param: value templateName: template1 other_state: - detailTitle: - key: template2.title - parameters: - param: value templateName: template2 styles: - my-template.css @@ -484,6 +476,18 @@ definitions: - Never - OnlyWhenResponseDisabledForUser + TypeOfStateEnum: + type: string + description: |- + Type of state > + * INPROGRESS - In Progress + * FINISHED - Finished + * CANCELED - Canceled + enum: + - INPROGRESS + - FINISHED + - CANCELED + ProcessGroup: description: Object containing a list of processes. properties: diff --git a/services/core/businessconfig/src/test/data/bundles/second/2.0/config.json b/services/core/businessconfig/src/test/data/bundles/second/2.0/config.json index 369baa2b08..b64deadb25 100755 --- a/services/core/businessconfig/src/test/data/bundles/second/2.0/config.json +++ b/services/core/businessconfig/src/test/data/bundles/second/2.0/config.json @@ -18,9 +18,6 @@ }, "externalRecipients": ["externalRecipient1", "externalRecipient2"] }, - "detailTitle": { - "key": "template.title" - }, "templateName": "template", "actions": { "action1": { diff --git a/services/core/businessconfig/src/test/data/bundles/second/2.1/config.json b/services/core/businessconfig/src/test/data/bundles/second/2.1/config.json index 68ebe47626..c9ac8343f5 100755 --- a/services/core/businessconfig/src/test/data/bundles/second/2.1/config.json +++ b/services/core/businessconfig/src/test/data/bundles/second/2.1/config.json @@ -20,9 +20,6 @@ }, "externalRecipients": ["externalRecipient1", "externalRecipient2"] }, - "detailTitle": { - "key": "template.title" - }, "templateName": "template", "actions": { "action1": { diff --git a/services/core/businessconfig/src/test/data/processgroups_with_duplicate_in_different_groups.json b/services/core/businessconfig/src/test/data/processgroups_with_duplicate_in_different_groups.json new file mode 100644 index 0000000000..60da6b7517 --- /dev/null +++ b/services/core/businessconfig/src/test/data/processgroups_with_duplicate_in_different_groups.json @@ -0,0 +1,29 @@ +{ + "groups": [ + { + "id": "processgroup1", + "processes": [ + "id_process1", + "id_process2" + ] + }, + { + "id": "processgroup2", + "processes": [ + "id_process3", + "id_process4", + "id_process1" + ] + } + ], + "locale": { + "en": { + "processgroup1": "Process Group 1", + "processgroup2": "Process Group 2" + }, + "fr": { + "processgroup1": "Groupe de process 1", + "processgroup2": "Groupe de process 2" + } + } +} diff --git a/services/core/businessconfig/src/test/data/processgroups_with_duplicate_in_same_group.json b/services/core/businessconfig/src/test/data/processgroups_with_duplicate_in_same_group.json new file mode 100644 index 0000000000..9cb201ad41 --- /dev/null +++ b/services/core/businessconfig/src/test/data/processgroups_with_duplicate_in_same_group.json @@ -0,0 +1,29 @@ +{ + "groups": [ + { + "id": "processgroup1", + "processes": [ + "id_process1", + "id_process2" + ] + }, + { + "id": "processgroup2", + "processes": [ + "id_process3", + "id_process4", + "id_process3" + ] + } + ], + "locale": { + "en": { + "processgroup1": "Process Group 1", + "processgroup2": "Process Group 2" + }, + "fr": { + "processgroup1": "Groupe de process 1", + "processgroup2": "Groupe de process 2" + } + } +} diff --git a/services/core/businessconfig/src/test/docker/volume/businessconfig-storage/first/config.json b/services/core/businessconfig/src/test/docker/volume/businessconfig-storage/first/config.json index ac5227066d..6267994003 100755 --- a/services/core/businessconfig/src/test/docker/volume/businessconfig-storage/first/config.json +++ b/services/core/businessconfig/src/test/docker/volume/businessconfig-storage/first/config.json @@ -7,9 +7,6 @@ ], "states": { "testState": { - "detailTitle": { - "key": "template.title" - }, "templateName": "template", "actions": { "testAction": { diff --git a/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/controllers/GivenAdminUserThirdControllerShould.java b/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/controllers/GivenAdminUserThirdControllerShould.java index 04934eeada..2823fb9a75 100644 --- a/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/controllers/GivenAdminUserThirdControllerShould.java +++ b/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/controllers/GivenAdminUserThirdControllerShould.java @@ -282,6 +282,32 @@ void createProcessGroups() throws Exception { .andExpect(jsonPath("$.locale.fr.processgroup1", is("Groupe de process 1"))) .andExpect(jsonPath("$.locale.fr.processgroup2", is("Groupe de process 2"))); } + + @Test + void createProcessGroupsWithDuplicateProcessInSameGroup() throws Exception { + Path pathToProcessGroupsFile = Paths.get("./build/test-data/processgroups_with_duplicate_in_same_group.json"); + + MockMultipartFile processGroupsFile = new MockMultipartFile("file", + "processgroups_with_duplicate_in_same_group.json", MediaType.TEXT_PLAIN_VALUE, Files + .readAllBytes(pathToProcessGroupsFile)); + + mockMvc.perform(multipart("/businessconfig/processgroups").file(processGroupsFile)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", is("There is a duplicate process in the file you have sent"))); + } + + @Test + void createProcessGroupsWithDuplicateProcessInDifferentGroups() throws Exception { + Path pathToProcessGroupsFile = Paths.get("./build/test-data/processgroups_with_duplicate_in_different_groups.json"); + + MockMultipartFile processGroupsFile = new MockMultipartFile("file", + "processgroups_with_duplicate_in_different_groups.json", MediaType.TEXT_PLAIN_VALUE, Files + .readAllBytes(pathToProcessGroupsFile)); + + mockMvc.perform(multipart("/businessconfig/processgroups").file(processGroupsFile)) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", is("There is a duplicate process in the file you have sent"))); + } @Nested @WithMockOpFabUser(login="adminUser", roles = {"ADMIN"}) diff --git a/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesServiceShould.java b/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesServiceShould.java index 10e7d24477..045719954a 100644 --- a/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesServiceShould.java +++ b/services/core/businessconfig/src/test/java/org/lfenergy/operatorfabric/businessconfig/services/ProcessesServiceShould.java @@ -25,7 +25,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; +import net.minidev.json.JSONObject; import org.apache.commons.io.FileUtils; import org.assertj.core.api.Condition; import org.junit.jupiter.api.AfterAll; @@ -38,8 +40,13 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.lfenergy.operatorfabric.businessconfig.application.IntegrationTestApplication; import org.lfenergy.operatorfabric.businessconfig.model.Process; +import org.lfenergy.operatorfabric.businessconfig.model.ProcessGroup; +import org.lfenergy.operatorfabric.businessconfig.model.ProcessGroupData; +import org.lfenergy.operatorfabric.businessconfig.model.ProcessGroupsData; +import org.lfenergy.operatorfabric.springtools.error.model.ApiError; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -203,6 +210,23 @@ void fetchResourceError() { ); } + @Test + public void testCheckNoDuplicateProcessInUploadedFile() { + + ProcessGroupData gp1 = ProcessGroupData.builder().id("gp1").processes(Arrays.asList("process1", "process2")).build(); + ProcessGroupData gp2 = ProcessGroupData.builder().id("gp2").processes(Arrays.asList("process3", "process4")).build(); + ProcessGroupData gp3 = ProcessGroupData.builder().id("gp3").processes(Arrays.asList("process5", "process4")).build(); + ProcessGroupData gp4 = ProcessGroupData.builder().id("gp4").processes(Arrays.asList("process7", "process8", "process7")).build(); + + ProcessGroupsData groups_without_duplicate = ProcessGroupsData.builder().groups(Arrays.asList(gp1, gp2)).build(); + ProcessGroupsData groups_with_duplicate = ProcessGroupsData.builder().groups(Arrays.asList(gp2, gp3)).build(); + ProcessGroupsData groups_with_duplicate_in_the_same_group = ProcessGroupsData.builder().groups(Arrays.asList(gp1, gp4)).build(); + + assertThat(service.checkNoDuplicateProcessInUploadedFile(groups_without_duplicate)).isTrue(); + assertThat(service.checkNoDuplicateProcessInUploadedFile(groups_with_duplicate)).isFalse(); + assertThat(service.checkNoDuplicateProcessInUploadedFile(groups_with_duplicate_in_the_same_group)).isFalse(); + } + @Nested class CreateContent { @RepeatedTest(2) diff --git a/services/core/cards-consultation/src/main/docker/Dockerfile b/services/core/cards-consultation/src/main/docker/Dockerfile index a34e52320a..9e7494d740 100755 --- a/services/core/cards-consultation/src/main/docker/Dockerfile +++ b/services/core/cards-consultation/src/main/docker/Dockerfile @@ -12,10 +12,13 @@ RUN apk add bash curl --no-cache ENV http_proxy="" ENV https_proxy="" ENV HTTP_PROXY_AUTH="" +ENV SPRING_CONFIG_NAME common,application,cards-consultation +ENV SPRING_PROFILES_ACTIVE docker +ENV SPRING_CONFIG_LOCATION ./config/,./external-config/ RUN env COPY add-certificates.sh /add-certificates.sh COPY java-config-docker-entrypoint.sh /docker-entrypoint.sh COPY common-docker.yml /config/common-docker.yml COPY ${JAR_FILE} app.jar -COPY cards-consultation-docker.yml /config/application-docker.yml +COPY cards-consultation-docker.yml /config/ ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/model/LightCardConsultationData.java b/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/model/LightCardConsultationData.java index 58a625c707..decce99bbb 100644 --- a/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/model/LightCardConsultationData.java +++ b/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/model/LightCardConsultationData.java @@ -122,7 +122,7 @@ public static LightCardConsultationData copy(Card other) { .entitiesAllowedToRespond(other.getEntitiesAllowedToRespond()) .publisherType(other.getPublisherType()) .secondsBeforeTimeSpanForReminder(other.getSecondsBeforeTimeSpanForReminder()); - ; + if(other.getTags()!=null && ! other.getTags().isEmpty()) builder.tags(other.getTags()); if(other.getTimeSpans()!=null && !other.getTimeSpans().isEmpty()) diff --git a/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/CardCustomRepository.java b/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/CardCustomRepository.java index 48f69d4d01..47c6f73377 100644 --- a/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/CardCustomRepository.java +++ b/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/CardCustomRepository.java @@ -10,14 +10,13 @@ package org.lfenergy.operatorfabric.cards.consultation.repositories; -import java.time.Instant; -import java.util.List; - import org.lfenergy.operatorfabric.cards.consultation.model.CardConsultationData; import org.lfenergy.operatorfabric.cards.consultation.model.CardOperation; import org.lfenergy.operatorfabric.users.model.CurrentUserWithPerimeters; import reactor.core.publisher.Flux; +import java.time.Instant; + /* *

Needed to avoid trouble at runtime when springframework try to create mongo request for findByIdWithUser method

diff --git a/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/UserUtilitiesCommonToCardRepository.java b/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/UserUtilitiesCommonToCardRepository.java index 146b815711..7ce122e545 100644 --- a/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/UserUtilitiesCommonToCardRepository.java +++ b/services/core/cards-consultation/src/main/java/org/lfenergy/operatorfabric/cards/consultation/repositories/UserUtilitiesCommonToCardRepository.java @@ -15,13 +15,12 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; - -import lombok.extern.slf4j.Slf4j; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.ArrayList; import java.util.List; + import static org.springframework.data.mongodb.core.query.Criteria.where; public interface UserUtilitiesCommonToCardRepository { @@ -63,8 +62,6 @@ default List computeCriteriaToFindCardByIdWithUser(String id, CurrentU } default Criteria computeCriteriaForUser(CurrentUserWithPerimeters currentUserWithPerimeters) { - List criteriaList = new ArrayList<>(); - List criteria = new ArrayList<>(); String login = currentUserWithPerimeters.getUserData().getLogin(); List groups = currentUserWithPerimeters.getUserData().getGroups(); List entities = currentUserWithPerimeters.getUserData().getEntities(); diff --git a/services/core/cards-publication/src/main/docker/Dockerfile b/services/core/cards-publication/src/main/docker/Dockerfile index c169911006..f62492b8ab 100755 --- a/services/core/cards-publication/src/main/docker/Dockerfile +++ b/services/core/cards-publication/src/main/docker/Dockerfile @@ -12,10 +12,13 @@ RUN apk add bash curl --no-cache ENV http_proxy="" ENV https_proxy="" ENV HTTP_PROXY_AUTH="" +ENV SPRING_CONFIG_NAME common,application,cards-publication +ENV SPRING_PROFILES_ACTIVE docker +ENV SPRING_CONFIG_LOCATION ./config/,./external-config/ RUN env COPY add-certificates.sh /add-certificates.sh COPY java-config-docker-entrypoint.sh /docker-entrypoint.sh COPY common-docker.yml /config/common-docker.yml COPY ${JAR_FILE} app.jar -COPY cards-publication-docker.yml /config/application-docker.yml +COPY cards-publication-docker.yml /config/ ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/controllers/CardController.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/controllers/CardController.java index 68d59948f3..6c571b593f 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/controllers/CardController.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/controllers/CardController.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2020, RTE (http://www.rte-france.com) +/* Copyright (c) 2018-2021, RTE (http://www.rte-france.com) * See AUTHORS.txt * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -52,7 +52,10 @@ public class CardController { @PostMapping @ResponseStatus(HttpStatus.CREATED) public @Valid Mono createCards(@Valid @RequestBody Flux cards) { - return cardProcessingService.processCards(cards); + return cardProcessingService.processCards(cards.map(card -> { + card.setPublisherType(PublisherTypeEnum.EXTERNAL); + return card; + })); } diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/kafka/consumer/KafkaAvroWithoutRegistryDeserializer.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/kafka/consumer/KafkaAvroWithoutRegistryDeserializer.java index fc1bbe88b1..eeefbd19d2 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/kafka/consumer/KafkaAvroWithoutRegistryDeserializer.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/kafka/consumer/KafkaAvroWithoutRegistryDeserializer.java @@ -1,4 +1,5 @@ /* Copyright (c) 2020, Alliander (http://www.alliander.com) + * Copyright (c) 2021, RTE (http://www.rte-france.com) * See AUTHORS.txt * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -42,13 +43,10 @@ public CardCommand deserialize(String s, byte[] payload) { try { ByteBuffer buffer = this.getByteBuffer(payload); buffer.getInt(); // read next 4 bytes - String subject = null; int length = buffer.limit() - 1 - 4; int start = buffer.position() + buffer.arrayOffset(); - CardCommand result = datumReader.read((CardCommand) null, this.decoderFactory.binaryDecoder(buffer.array(), start, length, (BinaryDecoder) null)); - - return result; + return datumReader.read((CardCommand) null, this.decoderFactory.binaryDecoder(buffer.array(), start, length, (BinaryDecoder) null)); } catch (RuntimeException | IOException ex) { throw new SerializationException("Error deserializing Avro message", ex); } diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/ArchivedCardPublicationData.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/ArchivedCardPublicationData.java index 3eae0bd6bb..3beb427944 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/ArchivedCardPublicationData.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/ArchivedCardPublicationData.java @@ -21,7 +21,6 @@ import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; -import javax.validation.constraints.NotNull; import java.time.Instant; import java.util.ArrayList; import java.util.List; diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/CardPublicationData.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/CardPublicationData.java index 6c368a9211..2399c13e8e 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/CardPublicationData.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/CardPublicationData.java @@ -13,11 +13,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.Singular; +import lombok.*; import org.lfenergy.operatorfabric.cards.model.SeverityEnum; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Id; @@ -160,9 +156,18 @@ public LightCardPublicationData toLightCard() { .summary(((I18nPublicationData) this.getSummary()).copy()) .publisherType(this.getPublisherType()) .secondsBeforeTimeSpanForReminder(this.secondsBeforeTimeSpanForReminder); - ; + if(this.getTimeSpans()!=null) result.timeSpansSet(new HashSet<>(this.getTimeSpans())); return result.build(); } + + + public Boolean getKeepChildCards() { + return keepChildCards; + } + + public void setKeepChildCards(Boolean keepChildCards) { + this.keepChildCards = keepChildCards != null ? keepChildCards : false; + } } diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/I18nPublicationData.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/I18nPublicationData.java index 205d6849e2..485db14f2e 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/I18nPublicationData.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/I18nPublicationData.java @@ -13,7 +13,6 @@ import lombok.*; -import javax.validation.constraints.NotNull; import java.util.Map; /** diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/LightCardPublicationData.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/LightCardPublicationData.java index 5cfceb500d..b85be908d6 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/LightCardPublicationData.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/LightCardPublicationData.java @@ -16,7 +16,6 @@ import org.lfenergy.operatorfabric.cards.model.SeverityEnum; import org.springframework.data.annotation.Transient; -import javax.validation.constraints.NotNull; import java.time.Instant; import java.util.ArrayList; import java.util.HashSet; diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/RecipientPublicationData.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/RecipientPublicationData.java index 9f3f49763e..b9c3f5f50b 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/RecipientPublicationData.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/model/RecipientPublicationData.java @@ -14,7 +14,6 @@ import lombok.*; import org.lfenergy.operatorfabric.cards.model.RecipientEnum; -import javax.validation.constraints.NotNull; import java.util.List; /** diff --git a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessingService.java b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessingService.java index 321055c822..8fcfa0f9a7 100644 --- a/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessingService.java +++ b/services/core/cards-publication/src/main/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessingService.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2020, RTE (http://www.rte-france.com) +/* Copyright (c) 2018-2021, RTE (http://www.rte-france.com) * See AUTHORS.txt * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -71,6 +71,7 @@ private Mono processCards(Flux push long windowStart = Instant.now().toEpochMilli(); + //delete child cards process should be prior to cards updates Flux cards = deleteChildCardsProcess(pushedCards); cards = registerRecipientProcess(cards); diff --git a/services/core/cards-publication/src/main/modeling/swagger.yaml b/services/core/cards-publication/src/main/modeling/swagger.yaml index a708a9c17e..5bce42a61b 100755 --- a/services/core/cards-publication/src/main/modeling/swagger.yaml +++ b/services/core/cards-publication/src/main/modeling/swagger.yaml @@ -1,7 +1,7 @@ swagger: '2.0' info: description: OperatorFabric Card Consumer Service - version: 2.0.0.RELEASE + version: 2.1.0.RELEASE title: Card Management API termsOfService: '' contact: diff --git a/services/core/cards-publication/src/test/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessServiceShould.java b/services/core/cards-publication/src/test/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessServiceShould.java index d186cd8c51..db572ae3a4 100644 --- a/services/core/cards-publication/src/test/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessServiceShould.java +++ b/services/core/cards-publication/src/test/java/org/lfenergy/operatorfabric/cards/publication/services/CardProcessServiceShould.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2020, RTE (http://www.rte-france.com) +/* Copyright (c) 2018-2021, RTE (http://www.rte-france.com) * See AUTHORS.txt * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -1034,4 +1034,25 @@ void isUserAllowedToDeleteThisCard() { assertThat(cardProcessingService.isUserAllowedToDeleteThisCard(cardFromAnEntity4, currentUserWithPerimeters)).isTrue(); assertThat(cardProcessingService.isUserAllowedToDeleteThisCard(cardFromAnEntity5, currentUserWithPerimeters)).isTrue(); } + + @Test + void processKeepChildCardsNull() { + EasyRandom easyRandom = instantiateRandomCardGenerator(); + int numberOfCards = 1; + List cards = instantiateSeveralRandomCards(easyRandom, numberOfCards); + cards.get(0).setParentCardId(null); + cards.get(0).setInitialParentCardUid(null); + cards.get(0).setKeepChildCards(null); + cardProcessingService.processCards(Flux.just(cards.toArray(new CardPublicationData[numberOfCards]))) + .subscribe(); + + Long block = cardRepository.count().block(); + Assertions.assertThat(block).withFailMessage( + "The number of registered cards should be '%d' but is " + "'%d' actually", + numberOfCards, block).isEqualTo(numberOfCards); + + CardPublicationData firstCard = cardRepository.findById(cards.get(0).getId()).block(); + Assertions.assertThat(firstCard.getKeepChildCards()).isNotNull(); + Assertions.assertThat(firstCard.getKeepChildCards()).isFalse(); + } } diff --git a/services/core/users/src/main/docker/Dockerfile b/services/core/users/src/main/docker/Dockerfile index c5ece31060..f8ea4299f8 100755 --- a/services/core/users/src/main/docker/Dockerfile +++ b/services/core/users/src/main/docker/Dockerfile @@ -12,6 +12,9 @@ RUN apk add bash curl --no-cache ENV http_proxy="" ENV https_proxy="" ENV HTTP_PROXY_AUTH="" +ENV SPRING_CONFIG_NAME common,application,users +ENV SPRING_PROFILES_ACTIVE docker +ENV SPRING_CONFIG_LOCATION ./config/,./external-config/ RUN env COPY add-certificates.sh /add-certificates.sh COPY java-config-docker-entrypoint.sh /docker-entrypoint.sh diff --git a/services/core/users/src/main/java/org/lfenergy/operatorfabric/users/utils/EntityCycleDetector.java b/services/core/users/src/main/java/org/lfenergy/operatorfabric/users/utils/EntityCycleDetector.java index 4ed150a47e..be41698c81 100644 --- a/services/core/users/src/main/java/org/lfenergy/operatorfabric/users/utils/EntityCycleDetector.java +++ b/services/core/users/src/main/java/org/lfenergy/operatorfabric/users/utils/EntityCycleDetector.java @@ -19,9 +19,9 @@ public class EntityCycleDetector { static final String CYCLE_DETECTION = "A cycle has been detected: "; - final private List visitedId; - final private Map> graph; - final private String currentEntityId; + private final List visitedId; + private final Map> graph; + private final String currentEntityId; public EntityCycleDetector(Entity currentEntity, List allEntities) { diff --git a/services/core/users/src/main/modeling/swagger.yaml b/services/core/users/src/main/modeling/swagger.yaml index 6e1aab753c..7ee4aac60e 100755 --- a/services/core/users/src/main/modeling/swagger.yaml +++ b/services/core/users/src/main/modeling/swagger.yaml @@ -1,7 +1,7 @@ swagger: '2.0' info: description: OperatorFabric User Management API - version: 2.0.0.RELEASE + version: 2.1.0.RELEASE title: User Management termsOfService: '' contact: @@ -785,7 +785,7 @@ paths: tags: - entities summary: Fetch a list of all existing entities. - description: 'Fetch a list of all existing entities, with pagination and filter options. Caution : work is still in progress, please do not use it.' + description: 'Fetch a list of all existing entities, with pagination and filter options.' operationId: fetchEntities produces: - application/json @@ -810,7 +810,7 @@ paths: tags: - entities summary: Create a new entity of users - description: 'Create a new entity of users. Caution : work is still in progress, please do not use it.' + description: 'Create a new entity of users.' operationId: createEntity consumes: - application/json @@ -842,7 +842,7 @@ paths: tags: - entities summary: Update existing entity - description: 'Update existing entity. Caution : work is still in progress, please do not use it.' + description: 'Update existing entity.' operationId: updateEntity consumes: - application/json @@ -878,7 +878,7 @@ paths: tags: - entities summary: Fetch an existing entity of users - description: 'Fetch an existing entity of users. Caution : work is still in progress, please do not use it.' + description: 'Fetch an existing entity of users.' operationId: fetchEntity produces: - application/json @@ -932,7 +932,7 @@ paths: summary: Update list of entity users description: >- Update list of entity users, users not included in given list are removed - from entity. Caution : work is still in progress, please do not use it. + from entity. operationId: updateEntityUsers produces: - application/json @@ -969,7 +969,7 @@ paths: - entities - users summary: Add users to entity - description: 'ONLY add users to entity (no deletion). Caution : work is still in progress, please do not use it.' + description: 'ONLY add users to entity (no deletion).' operationId: addEntityUsers produces: - application/json @@ -1004,7 +1004,7 @@ paths: - entities - users summary: Remove all users from entity - description: 'remove all users from entity. Caution : work is still in progress, please do not use it.' + description: 'remove all users from entity.' operationId: deleteEntityUsers produces: - application/json @@ -1031,7 +1031,7 @@ paths: - entities - users summary: Remove user from entity - description: 'ONLY remove user from entity (no addition). Caution : work is still in progress, please do not use it.' + description: 'ONLY remove user from entity (no addition).' operationId: deleteEntityUser produces: - application/json @@ -1062,7 +1062,7 @@ paths: tags: - perimeters summary: Fetch a list of all existing perimeters - description: 'Fetch a list of all existing perimeters. Caution : work is still in progress, please do not use it.' + description: 'Fetch a list of all existing perimeters.' operationId: fetchPerimeters produces: - application/json @@ -1097,7 +1097,7 @@ paths: tags: - perimeters summary: Create a new perimeter - description: 'Create a new perimeter. Caution : work is still in progress, please do not use it.' + description: 'Create a new perimeter.' operationId: createPerimeter consumes: - application/json @@ -1125,7 +1125,7 @@ paths: tags: - perimeters summary: Update existing perimeter - description: 'Update existing perimeter. Caution : work is still in progress, please do not use it.' + description: 'Update existing perimeter.' operationId: updatePerimeter consumes: - application/json @@ -1161,7 +1161,7 @@ paths: tags: - perimeters summary: Fetch an existing perimeter - description: 'Fetch an existing perimeter. Caution : work is still in progress, please do not use it.' + description: 'Fetch an existing perimeter.' operationId: fetchPerimeter produces: - application/json @@ -1214,7 +1214,7 @@ paths: - groups summary: Update list of groups that have this perimeter description: >- - Update list of groups that have this perimeter, groups not included in given list lose this perimeter. Caution : work is still in progress, please do not use it. + Update list of groups that have this perimeter, groups not included in given list lose this perimeter. operationId: updatePerimeterGroups produces: - application/json @@ -1250,7 +1250,7 @@ paths: - perimeters - groups summary: Add groups to perimeter - description: 'ONLY add groups to perimeter (no deletion). Caution : work is still in progress, please do not use it.' + description: 'ONLY add groups to perimeter (no deletion).' operationId: addPerimeterGroups produces: - application/json @@ -1285,7 +1285,7 @@ paths: - perimeters - groups summary: Remove all groups from perimeter - description: 'remove all groups from perimeter. Caution : work is still in progress, please do not use it.' + description: 'remove all groups from perimeter.' operationId: deletePerimeterGroups produces: - application/json @@ -1312,7 +1312,7 @@ paths: - perimeters - groups summary: Remove group from perimeter - description: 'ONLY remove group from perimeter (no addition). Caution : work is still in progress, please do not use it.' + description: 'ONLY remove group from perimeter (no addition).' operationId: deletePerimeterGroup produces: - application/json @@ -1344,7 +1344,7 @@ paths: - groups - perimeters summary: Fetch an existing group's perimeters - description: "Fetch existing group's perimeters from their id. Caution : work is still in progress, please do not use it." + description: "Fetch existing group's perimeters from their id." operationId: fetchGroupPerimeters produces: - application/json @@ -1389,7 +1389,7 @@ paths: - perimeters summary: Update list of perimeters for group description: >- - Update list of perimeters for group, perimeters not included in given list are no longer linked to the group. Caution : work is still in progress, please do not use it. + Update list of perimeters for group, perimeters not included in given list are no longer linked to the group. operationId: updateGroupPerimeters produces: - application/json @@ -1425,7 +1425,7 @@ paths: - groups - perimeters summary: Add perimeters to group - description: 'ONLY add perimeters to group (no deletion). Caution : work is still in progress, please do not use it.' + description: 'ONLY add perimeters to group (no deletion).' operationId: addGroupPerimeters produces: - application/json @@ -1461,7 +1461,7 @@ paths: - users - perimeters summary: Fetch an existing user's perimeters - description: "Fetch existing user's perimeters from their login. Caution : work is still in progress, please do not use it." + description: "Fetch existing user's perimeters from their login." operationId: fetchUserPerimeters produces: - application/json @@ -1507,7 +1507,7 @@ paths: tags: - users summary: Get information about the user connected and his perimeters - description: 'Get information about the user connected and his perimeters. Caution : work is still in progress, please do not use it.' + description: 'Get information about the user connected and his perimeters.' operationId: fetchCurrentUserWithPerimeters produces: - application/json diff --git a/src/docs/asciidoc/CICD/release_process.adoc b/src/docs/asciidoc/CICD/release_process.adoc index ccea79f8c4..057d58fb64 100644 --- a/src/docs/asciidoc/CICD/release_process.adoc +++ b/src/docs/asciidoc/CICD/release_process.adoc @@ -132,7 +132,7 @@ git merge X.X.X.release <3> ---- <1> Check out the `master` branch <2> Make sure your local copy is up to date -<3> Merge the `X.X.X.release` branch into `master` +<3> Merge the `X.X.X.release` branch into `master`, accepting changes from X.X.X.release in case of conflicts. IMPORTANT: If you also want the new docker images to be tagged `latest` (as should be the case for most release versions), you should add the keyword `ci_latest` to the merge commit message. @@ -176,7 +176,7 @@ branch they should rely on the latest RELEASE version available on DockerHub. On previous steps has completed successfully, and you can see X.X.X.RELEASE images for all services on DockerHub, you should: . Remove your locally built X.X.X.RELEASE images if any -. Run the config/demo docker-compose file to make sure it pulls the images from DockerHub and behaves as intended. +. Run the config/docker docker-compose file to make sure it pulls the images from DockerHub and behaves as intended. People who want to experiment with OperatorFabric are pointed to this docker-compose so it's important to make sure that it's working correctly. @@ -214,7 +214,7 @@ avoid confusion with the actual release commit tagged on `master`. ---- git branch -d X.X.X.release <1> -​git push origin --delete X.X.X.release <2> ---- <1> Delete the branch locally -<2> Remove it from GitHub + +NOTE: The branch will automatically be deleted from GitHub after it is merged (new repository policy). diff --git a/src/docs/asciidoc/community/workflow.adoc b/src/docs/asciidoc/community/workflow.adoc index 8e87411ae4..8ff2fba7fc 100644 --- a/src/docs/asciidoc/community/workflow.adoc +++ b/src/docs/asciidoc/community/workflow.adoc @@ -358,7 +358,8 @@ logic and not the framework itself) * Documentation has been updated (especially if configuration is needed) * Configuration examples have been updated (both for dev and docker) * Build and run OpFab locally to see the new feature or bug fix at work. In the case of a new feature, it's also a way -of making sure that the configuration documentation is correct and easily understandable. +of making sure that the configuration documentation is correct and easily understandable. +* Check for error messages in the browser console. * Depending on the scope of the PR , build docker images and test in docker mode * Check that the copyright header has been updated on the changed files if need be, and in the case of a first-time contributor, make sure they're added to the AUTHORS.txt file. @@ -379,6 +380,7 @@ Compile and run OperatorFabric docker images is the most effective way to check . Run the following scripts: `./loadBundle.sh && ./setPerimeterForTest.sh && ./postTestCards.sh`; . Open the front-end in a browser and look for any regression. +To automate build and API testing, you can use `${OF_HOME}/src/test/api/karate/buildAndLaunchAll.sh`. === Merging a Pull Request diff --git a/src/docs/asciidoc/deployment/configuration/configuration.adoc b/src/docs/asciidoc/deployment/configuration/configuration.adoc index 1d54b1491d..6fb2346ba8 100644 --- a/src/docs/asciidoc/deployment/configuration/configuration.adoc +++ b/src/docs/asciidoc/deployment/configuration/configuration.adoc @@ -34,6 +34,22 @@ while the *docker* sub-directory is a specific configuration meant for use in a == Business service configuration +=== Specify an external configuration + +When starting docker in the full docker environment an external environment file could be provided like: + +---- +cd ./config/docker +./docker-compose.sh ~/config/local.env +---- +In the provided environment file the Spring active profiles can be set. + +---- +SPRING_PROFILES_ACTIVE=docker,local +---- +This way the configuration file 'cards-publication-local.yml' can be provided in the same configuration directory and can be read by SpringBoot + + === Shared business service configuration The configuration shared by all business services is in a yaml file, you can find an example with the file diff --git a/src/docs/asciidoc/deployment/configuration/web-ui_configuration.adoc b/src/docs/asciidoc/deployment/configuration/web-ui_configuration.adoc index cb5edd25e0..d1ee6bb674 100644 --- a/src/docs/asciidoc/deployment/configuration/web-ui_configuration.adoc +++ b/src/docs/asciidoc/deployment/configuration/web-ui_configuration.adoc @@ -42,6 +42,7 @@ The properties lie in the `web-ui.json`.The following table describes their mean |=== |name|default|mandatory?|Description + |security.provider-realm||yes|The realm name in keycloak server settings page. This is used for the log out process to know which realm should be affected. |security.provider-url||yes|The keycloak server instance |security.logout-url||yes @@ -78,7 +79,6 @@ a|card time display mode in the feed. Values : |feed.card.secondsBeforeLttdForClockDisplay|180|no| Number of seconds before lttd when a clock is activated in cards on the feed |feed.timeline.domains|["TR", "J", "7D", "W", "M", "Y"]|no| List of domains to show on the timeline, possible domains are : "TR", "J", "7D", "W", "M", "Y". -|feed.notify|false|no|If set to true, new cards are notified in the OS through web-push notifications |feedConfiguration.hidden|false|no|Control if you want to show or hide the notification configuration screen |playSoundForAlarm|false|no|If set to true, a sound is played when Alarm cards are added or updated in the feed |playSoundForAction|false|no|If set to true, a sound is played when Action cards are added or updated in the feed @@ -123,6 +123,8 @@ It should look like: |logo.width|150|no|The width of the logo (in px) (only taken into account if logo.base64 is set). |logo.limitSize|true|no|If it is true, the height limit is 32(px) and the width limit is 200(px), it means that if the height is over than 32, it will be set to 32, if the width is over than 200, it is set to 200. If it is false, no limit restriction for the height and the width. |title|OperatorFabric|no|Title of the application, displayed on the browser +|environmentName||no| Name of the environment to display on the top-right corner (examples: PROD , TEST .. ), if the value not set the environnement name is not shown . +|environmentColor|blue|no| Color of the background of the environnement name. The format of color is css, for example : `red` , `#4052FF` |navbar.hidden|["logging","monitoring"]|no a| Lists the application menu to hide in the navbar. + The `keys` used are the `route.path` declared in the `${OF_HOME}ui/main/src/app/app-routing.module.ts` file. + diff --git a/src/docs/asciidoc/docs/release_notes.adoc b/src/docs/asciidoc/docs/release_notes.adoc index 18ad0e2375..16cb59297b 100644 --- a/src/docs/asciidoc/docs/release_notes.adoc +++ b/src/docs/asciidoc/docs/release_notes.adoc @@ -5,62 +5,63 @@ // file, You can obtain one at https://creativecommons.org/licenses/by/4.0/. // SPDX-License-Identifier: CC-BY-4.0 -= Version 2.0.0.RELEASE - -== Overview - -We decided to make this a major version because in addition to providing new features, it also substancially changes (and hopefully improves!) the user experience (*new global style for the UI* and layout changes for some screens). - -The following features introduced as beta in previous versions are now *production-ready*: - -- User Cards -- Agenda -- Logging -- Monitoring - -This version also introduces a *notification filter management* interface for users (see below for details). += Version 2.1.0.RELEASE == Features -- *Filter notification screen for user* (OC-1218, OC-1219, OC-1275, OC-1360): users can now filter the card they received in the feed with a configuration screen accessible throught the right menu -- *Events representation in time* (OC-1241, OC-1242, OC-1299): handle repeating events & remove bubble for business period end. -- [OC-1229] Send card to user using group of entities -- [OC-1272] Add the possibility to show ack button only if action is disabled for the user. In consequence, the configuration of the acknowledgement feature has changed (link:https://opfab.github.io/documentation/current/docs/single_page_doc.html#_migration_guide_from_release_1_8_0_to_release_2_0_0[see migration documentation]). -- [OC-1277] Add the possibility to set business menu visibility depending on group membership (link:https://opfab.github.io/documentation/current/reference_doc/#menu_entries[see documentation]) -- [OC-1289] Do not show child cards on the UI archive panel -- [OC-1200] Add update reponse button when there is already a reponse for the entity -- *User cards (Free Message)* (OC-1279, OC-1295, OC-1195): feature enhancement and changes to the card-sending form - -== Tasks - -=== Technical - -- [OC-1060] Upgrade to Java 11 -- [OC-1285] Update backend dependencies to last versions -- [OC-824] DockerTagSnapshot task shouldn't tag latest as well - -=== Documentation - -- [OC-1206] Add config parameters for date and time rendering in the documentation -- [OC-1234] Update documentation regarding entities and groups description -- [OC-1286] Updated Kafka documentation -- [OC-840], [OC-1298] Modify Getting Started documentation -- [OC-1256] Add documentation for groups of entities -- [OC-1101] Add user card documentation -- [OC-1139] Add in documentation : describe notion of processes groups - -=== Misc - -- [OC-1250] Make externalRecipients-url param in cards-publication.yml not mandatory -- [OC-1276] Remove double state definition in process endpoint -- [OC-1183] Set login to lowercase -- [OC-1309] Template communication improvement +- OC-1395 : When user exits the feed screen or exits operator fabric his filters/sorts options are memorized, when he +goes back the filters/sorts options are set to the memorized values. +- OC-1399 : Notification Screen - Display the states, process and process groups in alphabetical order +- OC-1438 : Add the possibility to show environment name in the top right corner +- OC-1201 : Inform the template when lttd has expired +- OC-1396 : Communicate to the template the screen size calling setScreenSize() method +- OC-1400 : Add "service" field in the free message feature +- OC-1270 : Timeline circles : open popover on mouseover +- OC-964 : Deal with user in more than one entity ++ +Now if the entity to respond with cannot be resolved because a user is a member of several entities that are allowed to +respond to a card, the response action is disabled. +- OC-1431 - Display names rather than IDs for entities/groups in the users table (Administration) == Bugs -- [OC-1355] Bug in creation/edit user with multiselect component -- [OC-1363] Start UI even if no processes defined (add a warning in the log) -- [OC-654] Correct deprecated code in cards-consultation - +- OC-1428 : Fix bug on Feed Filter when setting only date and not time +- OC-1436 : Error message does not appear correctly in usercard +- OC-1452 : Translation error : criticity -> criticality +- OC-890 : When using PASSWORD flow, once the token is expired the user isn't notified +- OC-1472 : Card detail show last seen card for few instants before showing the selected card (rework of OC-1419) +- OC-1347 : Fix bug with keepChildCards default value +- OC-1459 : Admin - Propagate entity/group update to users +- OC-1469 : Fix Bug - publisherType not set to external when receiving a card via card endPoint +- OC-1478 : Fix Bug in calendar day mode when event spans multiple days +- OC-1489 : Fix bug on delayed display of countdown counter +- OC-1425 : Export data : title of the columns are not translated +- OC-1496 : Admin UI : In day mode : when trying to delete user/group/entity, popup is displayed in night mode +== Tasks +- OC-1283 : Allow external config location for docker-compose ++ +This can be useful to avoid committing test or demo-specific configuration. +See https://opfab.github.io/documentation/archives/2.1.0.RELEASE/docs/single_page_doc.html#_specify_an_external_configuration[documentation]. +- OC-1361 : Remove old notification feature via the browser +- OC-1407 : Remove detailTitle in bundle config -> the title of the card always comes from the title field of the card ++ +IMPORTANT: Please remove detailTitle properties from your bundles. ++ +- Rework of the admin screen (OC-1191, OC-1434, OC-1457) +- Upgrade Angular from v8.2 to v10.2 and related tasks (OC-1061, OC-1392, OC-1437, OC-1468) +- OC-1409 : When pushing the process group file check for duplicate processes +- OC-1430 : Adapt api testing script to first stop and remove existing containers +- OC-1447 : Introduce notion of type of state ++ +NOTE: This shouldn't have any impact for deployments using docker. If you need to build the UI however, +you need to run "npm install" first to get the new dependencies. We found it best to delete the node_modules folder +before running npm_install to avoid errors. +In addition, see the https://opfab.github.io/documentation/archives/2.1.0.RELEASE/docs/single_page_doc.html#_build[documentation] +to troubleshoot any errors. ++ +- Documentation updates (OC-1427, OC-1429) +- OC-1083 : Refactoring of NGNX endpoints for groups and entities : "/users/entities" instead of "/entities" +and "/users/groups" instead of "/groups" +- OC-1439 : New archives screen filters diff --git a/src/docs/asciidoc/getting_started/index.adoc b/src/docs/asciidoc/getting_started/index.adoc index 66d5ff1e1a..f588ae9dac 100644 --- a/src/docs/asciidoc/getting_started/index.adoc +++ b/src/docs/asciidoc/getting_started/index.adoc @@ -192,7 +192,6 @@ The global configuration is defined in config.json : "version":"2", "states":{ "messageState" : { - "detailTitle" : { "key" : "defaultProcess.title"}, "templateName" : "template", "styles" : [ "style" ] } @@ -251,7 +250,7 @@ You should received the following JSON in response, describing your bundle. [source,JSON] ---- -{"id":"defaultProcess","name":null,"version":"2","uiVisibility":null,"states":{"messageState":{"responseData":null,"acknowledgementAllowed":true,"color":null,"name":null,"userCard":null,"detailTitle":{"key":"defaultProcess.title","parameters":null},"templateName":"template","styles":["style"],"acknowledgmentAllowed":true,"response":null}}} +{"id":"defaultProcess","name":null,"version":"2","uiVisibility":null,"states":{"messageState":{"responseData":null,"acknowledgementAllowed":true,"color":null,"name":null,"userCard":null,"templateName":"template","styles":["style"],"acknowledgmentAllowed":true,"response":null}}} ---- ==== Send a card @@ -309,19 +308,16 @@ of the bundle: "version":"1", "states":{ "criticalSituation-begin" : { - "detailTitle" : { "key" : "criticalSituation-begin.title"}, "templateName" : "criticalSituationTemplate", "styles" : [ "style" ], "acknowledgmentAllowed": "Always" }, "criticalSituation-update" : { - "detailTitle" : { "key" : "criticalSituation-update.title"}, "templateName" : "criticalSituationTemplate", "styles" : [ "style" ], "acknowledgmentAllowed": "Always" }, "criticalSituation-end" : { - "detailTitle" : { "key" : "criticalSituation-end.title"}, "templateName" : "endCriticalSituationTemplate", "styles" : [ "style" ], "acknowledgmentAllowed": "Always" diff --git a/src/docs/asciidoc/reference_doc/process_definition.adoc b/src/docs/asciidoc/reference_doc/process_definition.adoc index 388275d13e..c71972cd7b 100644 --- a/src/docs/asciidoc/reference_doc/process_definition.adoc +++ b/src/docs/asciidoc/reference_doc/process_definition.adoc @@ -317,15 +317,9 @@ These command line should return a `200 http status` response with the details o "version": "1", "states" : { "start" : { - "detailTitle" : { - "key" : "start.first.title" - }, - "templateName" : "template1" + "templateName" : "template1" }, "end" : { - "detailTitle" : { - "key" : "end.first.title" - }, "templateName" : "template2", "styles" : [ "bundleTest.css" ] } @@ -340,11 +334,15 @@ section which resumes how to resolve common problems. == Processes groups -OperatorFabric offers the possibility of defining processes groups. These groups have an impact only on the UI, for example on the notification configuration screen, by offering a more organized view of all the processes. +OperatorFabric offers the possibility of defining process groups. These groups have an impact only on the UI, for +example on the notification configuration screen, by offering a more organized view of all the processes. + +IMPORTANT: A process can only belong to one process group. To define processes groups, you have to upload a file via a `POST` http request as described in the -ifdef::single-page-doc[<<../api/businessconfig/#/businessconfig/uploadProcessgroups, Businessconfig Service API documentation>>] -ifndef::single-page-doc[<<{gradle-rootdir}/documentation/current/api/businessconfig/#/businessconfig/uploadProcessgroups, Businessconfig Service API documentation>>] + +ifdef::single-page-doc[link:../api/businessconfig/index.html#/businessconfig/uploadProcessgroups[Businessconfig Service API documentation]] +ifndef::single-page-doc[link:{gradle-rootdir}/documentation/current/api/businessconfig/index.html#/default/uploadProcessgroups[Businessconfig Service API documentation]] . *Example* @@ -399,4 +397,4 @@ Example of content for uploaded file : ---- -These command line should return a `201 http status`. \ No newline at end of file +These command line should return a `201 http status`. diff --git a/src/docs/asciidoc/reference_doc/response_cards.adoc b/src/docs/asciidoc/reference_doc/response_cards.adoc index df1129b0c7..4317870dfa 100644 --- a/src/docs/asciidoc/reference_doc/response_cards.adoc +++ b/src/docs/asciidoc/reference_doc/response_cards.adoc @@ -65,9 +65,6 @@ A card can have a response only if it's in a process/state that is configured fo "key": "question.button.text" } }, - "detailTitle": { - "key": "question.title" - }, "templateName": "question", "styles": [ "style" @@ -174,3 +171,7 @@ From there, as soon as they will open this card the button will be marked as "MO The user can then click on "MODIFY ANSWER" and the button will come back to its initial state ("VALIDATE ANSWER") and the information that the user wants to modify its initial answer will be sent to the third template (by calling the _templateGateway.unlockAnswer()_ function). Once again, after validating its answer, the information will be sent to the third template that the card has been locked (by calling the templateGateway.lockAnswer() function). + +== Last Time to Decide (`lttd`) + +If the card has a last time to decide (lttd) configured, when the time is expired this information will be sent to the third template (by calling the template.setLttdExpired(true) function). \ No newline at end of file diff --git a/src/docs/asciidoc/reference_doc/template_description.adoc b/src/docs/asciidoc/reference_doc/template_description.adoc index e929701bbb..7169867f2a 100644 --- a/src/docs/asciidoc/reference_doc/template_description.adoc +++ b/src/docs/asciidoc/reference_doc/template_description.adoc @@ -466,3 +466,12 @@ Your can find example using these classes in the OperatorFabric core repository The library https://www.chartjs.org/[charts.js] is integrated in OperatorFabric, it means it's possible to show charts in cards, you can find a bundle example in the operator fabric git (https://github.com/opfab/operatorfabric-core/tree/develop/src/test/utils/karate/businessconfig/resources/bundle_defautlProcess[src/test/utils/karate/businessconfig/resources/bundle_defaultProcess]). + +== OperatorFabric specific functions + +=== Set screen size + +To adapt the template content on screen size it is possible to receive from OperatorFabric information on the size of the window where the template will be rendered. To receive screen size information you need to implement a javascript function in your template called templateGateway.setScreenSize(size) which receives as input a string parameter with one of the following values : + +- 'md' : medium size window +- 'lg' : large size window diff --git a/src/docs/asciidoc/reference_doc/user_cards.adoc b/src/docs/asciidoc/reference_doc/user_cards.adoc index 6729679826..a4522687ed 100644 --- a/src/docs/asciidoc/reference_doc/user_cards.adoc +++ b/src/docs/asciidoc/reference_doc/user_cards.adoc @@ -31,9 +31,6 @@ For example : "startDateVisible" : true, "endDateVisible" : true }, - "detailTitle": { - "key": "message.title" - }, "templateName": "message", "styles": [], "acknowledgmentAllowed": "Always" diff --git a/src/docs/asciidoc/resources/index.adoc b/src/docs/asciidoc/resources/index.adoc index 9b76de2b5a..041ec9f92f 100644 --- a/src/docs/asciidoc/resources/index.adoc +++ b/src/docs/asciidoc/resources/index.adoc @@ -15,3 +15,5 @@ include::mock_pipeline.adoc[leveloffset=+1] include::migration_guide.adoc[leveloffset=+1] include::migration_guide_to_1.8.adoc[leveloffset=+1] + +include::migration_guide_to_2.0.adoc[leveloffset=+1] diff --git a/src/main/docker/java-config-docker-entrypoint.sh b/src/main/docker/java-config-docker-entrypoint.sh index 8864447c07..4a3175a83e 100755 --- a/src/main/docker/java-config-docker-entrypoint.sh +++ b/src/main/docker/java-config-docker-entrypoint.sh @@ -13,5 +13,5 @@ cp $JAVA_HOME/jre/lib/security/cacerts /tmp chmod u+w /tmp/cacerts ./add-certificates.sh /certificates_to_add /tmp/cacerts -java -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n -Djavax.net.ssl.trustStore=/tmp/cacerts -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.profiles.active=docker --spring.config.name=common,application $JAVA_OPTIONS +java -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n -Djavax.net.ssl.trustStore=/tmp/cacerts -Djava.security.egd=file:/dev/./urandom -jar /app.jar $JAVA_OPTIONS diff --git a/src/test/api/karate/buildAndLaunchAll.sh b/src/test/api/karate/buildAndLaunchAll.sh index 4cb90df6cd..18160d0682 100755 --- a/src/test/api/karate/buildAndLaunchAll.sh +++ b/src/test/api/karate/buildAndLaunchAll.sh @@ -16,6 +16,12 @@ bin/run_all.sh stop sleep 5 echo "Hard stop for cleaning if needed" bin/run_all.sh hardstop +echo "Stop existing running opfab docker" +cd config/dev +docker-compose down +cd ../docker +docker-compose down +cd ../.. echo "Start docker compose for building" docker-compose -f ${dockerComposeFile} up -d echo "Build all" diff --git a/src/test/api/karate/businessconfig/getABusinessconfig.feature b/src/test/api/karate/businessconfig/getABusinessconfig.feature index 49d1af3b30..e86e2d9f97 100644 --- a/src/test/api/karate/businessconfig/getABusinessconfig.feature +++ b/src/test/api/karate/businessconfig/getABusinessconfig.feature @@ -20,11 +20,14 @@ Feature: Bundle And match response.states.questionState.userCard.severityVisible == false And match response.states.questionState.userCard.startDateVisible == true And match response.states.questionState.userCard.endDateVisible == true + And match response.states.questionState.type == 'INPROGRESS' + And match response.states.messageState.type == 'CANCELED' And match response.states.incidentInProgressState.userCard.template == 'usercard_incidentInProgress' And match response.states.incidentInProgressState.userCard.severityVisible == true And match response.states.incidentInProgressState.userCard.startDateVisible == false And match response.states.incidentInProgressState.userCard.endDateVisible == false And match response.states.incidentInProgressState.acknowledgmentAllowed == 'Always' + And match response.states.incidentInProgressState.type == 'FINISHED' diff --git a/src/test/api/karate/businessconfig/resources/bundle_api_test/config.json b/src/test/api/karate/businessconfig/resources/bundle_api_test/config.json index 4a19faeb61..90d7d4c2ca 100644 --- a/src/test/api/karate/businessconfig/resources/bundle_api_test/config.json +++ b/src/test/api/karate/businessconfig/resources/bundle_api_test/config.json @@ -8,7 +8,6 @@ }, "states": { "messageState" : { - "detailTitle" : { "key" : "detail.title"}, "templateName" : "template", "styles" : [ "style" ] }, @@ -24,9 +23,6 @@ "response": { "state": "questionState" }, - "detailTitle": { - "key": "question.title" - }, "templateName": "question", "styles": [], "acknowledgmentAllowed": "Never" @@ -43,9 +39,6 @@ "response": { "state": "incidentInProgressState" }, - "detailTitle": { - "key": "incidentInProgress.name" - }, "templateName": "incidentInProgress", "styles": [], "acknowledgmentAllowed": "Always" diff --git a/src/test/api/karate/businessconfig/resources/bundle_api_test_v2/config.json b/src/test/api/karate/businessconfig/resources/bundle_api_test_v2/config.json index 78813edbe6..2bd0b3e655 100644 --- a/src/test/api/karate/businessconfig/resources/bundle_api_test_v2/config.json +++ b/src/test/api/karate/businessconfig/resources/bundle_api_test_v2/config.json @@ -8,9 +8,9 @@ }, "states": { "messageState" : { - "detailTitle" : { "key" : "detail.title"}, "templateName" : "template", - "styles" : [ "style" ] + "styles" : [ "style" ], + "type" : "CANCELED" }, "questionState": { "name": "question.title", @@ -24,12 +24,10 @@ "response": { "state": "questionState" }, - "detailTitle": { - "key": "question.title" - }, "templateName": "question", "styles": [], - "acknowledgmentAllowed": "Never" + "acknowledgmentAllowed": "Never", + "type" : "INPROGRESS" }, "incidentInProgressState": { "name": "incidentInProgress.name", @@ -43,12 +41,10 @@ "response": { "state": "incidentInProgressState" }, - "detailTitle": { - "key": "incidentInProgress.name" - }, "templateName": "incidentInProgress", "styles": [], - "acknowledgmentAllowed": "Always" + "acknowledgmentAllowed": "Always", + "type" : "FINISHED" } } } diff --git a/src/test/api/karate/businessconfig/resources/bundle_test_action/config.json b/src/test/api/karate/businessconfig/resources/bundle_test_action/config.json index 207c2a96b4..181262c7d7 100755 --- a/src/test/api/karate/businessconfig/resources/bundle_test_action/config.json +++ b/src/test/api/karate/businessconfig/resources/bundle_test_action/config.json @@ -14,9 +14,6 @@ "key": "action.text" } }, - "detailTitle": { - "key": "cardDetails.title" - }, "templateName": "long-card", "styles": [ ] @@ -31,9 +28,6 @@ }, "externalRecipients": ["externalRecipient1", "externalRecipient2"] }, - "detailTitle": { - "key": "cardDetails.title" - }, "templateName": "template1", "styles": [ "main" @@ -47,9 +41,6 @@ "key": "action.text" } }, - "detailTitle": { - "key": "cardDetails.title" - }, "templateName": "template1", "styles": [ "main" @@ -61,9 +52,6 @@ "state": "responseState", "btnColor": "RED" }, - "detailTitle": { - "key": "cardDetails.title" - }, "templateName": "template1", "styles": [ "main" @@ -74,9 +62,6 @@ "lock": true, "state": "responseState" }, - "detailTitle": { - "key": "cardDetails.title" - }, "templateName": "template1", "styles": [ "main" diff --git a/src/test/api/karate/businessconfig/resources/processgroups2_with_duplicate_in_different_groups.json b/src/test/api/karate/businessconfig/resources/processgroups2_with_duplicate_in_different_groups.json new file mode 100644 index 0000000000..cb1a6c7343 --- /dev/null +++ b/src/test/api/karate/businessconfig/resources/processgroups2_with_duplicate_in_different_groups.json @@ -0,0 +1,29 @@ +{ + "groups": [ + { + "id": "processgroupKarate3", + "processes": [ + "id_process5", + "id_process6" + ] + }, + { + "id": "processgroupKarate4", + "processes": [ + "id_process7", + "id_process8", + "id_process6" + ] + } + ], + "locale": { + "en": { + "processgroupKarate3": "Process Group Karate 3", + "processgroupKarate4": "Process Group Karate 4" + }, + "fr": { + "processgroupKarate3": "Groupe de process Karate 3", + "processgroupKarate4": "Groupe de process Karate 4" + } + } +} diff --git a/src/test/api/karate/businessconfig/resources/processgroups2_with_duplicate_in_same_group.json b/src/test/api/karate/businessconfig/resources/processgroups2_with_duplicate_in_same_group.json new file mode 100644 index 0000000000..47829f8e41 --- /dev/null +++ b/src/test/api/karate/businessconfig/resources/processgroups2_with_duplicate_in_same_group.json @@ -0,0 +1,29 @@ +{ + "groups": [ + { + "id": "processgroupKarate3", + "processes": [ + "id_process5", + "id_process6" + ] + }, + { + "id": "processgroupKarate4", + "processes": [ + "id_process7", + "id_process8", + "id_process7" + ] + } + ], + "locale": { + "en": { + "processgroupKarate3": "Process Group Karate 3", + "processgroupKarate4": "Process Group Karate 4" + }, + "fr": { + "processgroupKarate3": "Groupe de process Karate 3", + "processgroupKarate4": "Groupe de process Karate 4" + } + } +} diff --git a/src/test/api/karate/businessconfig/uploadProcessGroupsFile.feature b/src/test/api/karate/businessconfig/uploadProcessGroupsFile.feature index 370efa18f0..6a6d1f3f8c 100644 --- a/src/test/api/karate/businessconfig/uploadProcessGroupsFile.feature +++ b/src/test/api/karate/businessconfig/uploadProcessGroupsFile.feature @@ -25,6 +25,22 @@ Feature: uploadProcessGroups And status 403 + Scenario: Post process groups file with duplicate process + Given url opfabUrl + '/businessconfig/processgroups' + And header Authorization = 'Bearer ' + authToken + And multipart file file = { read: 'resources/processgroups2_with_duplicate_in_different_groups.json' } + When method post + And status 400 + + + Scenario: Post process groups file with duplicate process in the same group + Given url opfabUrl + '/businessconfig/processgroups' + And header Authorization = 'Bearer ' + authToken + And multipart file file = { read: 'resources/processgroups2_with_duplicate_in_same_group.json' } + When method post + And status 400 + + Scenario: Post process groups file Given url opfabUrl + '/businessconfig/processgroups' And header Authorization = 'Bearer ' + authToken diff --git a/src/test/api/karate/cards/cards.feature b/src/test/api/karate/cards/cards.feature index 1d4930d86c..53e71155c8 100644 --- a/src/test/api/karate/cards/cards.feature +++ b/src/test/api/karate/cards/cards.feature @@ -509,4 +509,42 @@ Scenario: Push a card for a user with no group and no entity And header Authorization = 'Bearer ' + authTokenUserWithNoGroupNoEntity When method get Then status 200 - And match response.data.message == 'a message for user with no group and no entity' \ No newline at end of file + And match response.data.message == 'a message for user with no group and no entity' + + +Scenario: Push card with null keepChilCards and publisherType + + * def parentCard2 = +""" +{ + "publisher" : "api_test", + "processVersion" : "1", + "process" :"api_test", + "processInstanceId" : "processKeepChildCardsNull", + "state": "messageState", + "groupRecipients": ["Dispatcher"], + "severity" : "INFORMATION", + "startDate" : 1553186770681, + "keepChildCards": null, + "publisherType": null, + "summary" : {"key" : "defaultProcess.summary"}, + "title" : {"key" : "defaultProcess.title2"}, + "data" : {"message":"test externalRecipients"} +} +""" + +# Push parent card + Given url opfabPublishCardUrl + 'cards' + And request parentCard2 + When method post + Then status 201 + And match response.count == 1 + And match response.message == "All pushedCards were successfully handled" + +#get parent card id + Given url opfabUrl + 'cards/cards/api_test.processKeepChildCardsNull' + And header Authorization = 'Bearer ' + authToken + When method get + Then status 200 + And match response.card.keepChildCards == false + And match response.card.publisherType == "EXTERNAL" diff --git a/src/test/api/karate/cards/deleteUserCard.feature b/src/test/api/karate/cards/deleteUserCard.feature index d5f3e1074f..6e7273de26 100644 --- a/src/test/api/karate/cards/deleteUserCard.feature +++ b/src/test/api/karate/cards/deleteUserCard.feature @@ -6,6 +6,8 @@ Feature: deleteUserCards tests * def authToken = signIn.authToken * def signInAsTSO = call read('../common/getToken.feature') { username: 'operator1'} * def authTokenAsTSO = signInAsTSO.authToken + * def signInAsTSO2 = call read('../common/getToken.feature') { username: 'operator2'} + * def authTokenAsTSO2 = signInAsTSO2.authToken * def groupKarate = """ @@ -14,6 +16,14 @@ Feature: deleteUserCards tests "name" : "groupKarate name", "description" : "groupKarate description" } +""" + * def groupKarate2 = +""" +{ + "id" : "groupKarateDeleteUserCards2", + "name" : "groupKarate name", + "description" : "groupKarate description" +} """ @@ -33,17 +43,45 @@ Feature: deleteUserCards tests } ] } +""" + + * def perimeterWriteForState2 = +""" +{ + "id" : "perimeterKarateDeleteUserCards2", + "process" : "processDeleteUserCard", + "stateRights" : [ + { + "state" : "state1", + "right" : "Write" + }, + { + "state" : "state2", + "right" : "Write" + } + ] +} """ * def operator1Array = """ [ "operator1" ] +""" + * def operator2Array = +""" +[ "operator2" +] """ * def groupArray = """ [ "groupKarateDeleteUserCards" ] +""" + * def group2Array = +""" +[ "groupKarateDeleteUserCards2" +] """ Scenario: Create groupKarate @@ -55,6 +93,15 @@ Feature: deleteUserCards tests And match response.name == groupKarate.name And match response.id == groupKarate.id + Scenario: Create groupKarate2 + Given url opfabUrl + 'users/groups' + And header Authorization = 'Bearer ' + authToken + And request groupKarate2 + When method post + Then match response.description == groupKarate2.description + And match response.name == groupKarate2.name + And match response.id == groupKarate2.id + Scenario: Add operator1 to groupKarate Given url opfabUrl + 'users/groups/' + groupKarate.id + '/users' @@ -63,6 +110,13 @@ Feature: deleteUserCards tests When method patch And status 200 + Scenario: Add operator2 to groupKarate2 + Given url opfabUrl + 'users/groups/' + groupKarate2.id + '/users' + And header Authorization = 'Bearer ' + authToken + And request operator2Array + When method patch + And status 200 + Scenario: Create perimeter Given url opfabUrl + 'users/perimeters' @@ -70,6 +124,12 @@ Feature: deleteUserCards tests And request perimeter When method post + Scenario: Create perimeterWriteForState2 + Given url opfabUrl + 'users/perimeters' + And header Authorization = 'Bearer ' + authToken + And request perimeterWriteForState2 + When method post + Scenario: Put groupKarate for perimeter Given url opfabUrl + 'users/perimeters/'+ perimeter.id + '/groups' @@ -78,13 +138,19 @@ Feature: deleteUserCards tests When method put Then status 200 + Scenario: Put groupKarate2 for perimeterWriteForState2 + Given url opfabUrl + 'users/perimeters/'+ perimeterWriteForState2.id + '/groups' + And header Authorization = 'Bearer ' + authToken + And request group2Array + When method put + Then status 200 + Scenario: Push user card * def cardForDeleteOk = """ { "publisher" : "ENTITY1", - "publisherType" : "ENTITY", "processVersion" : "1", "process" :"processDeleteUserCard", "processInstanceId" : "processDeleteUserCardOk", @@ -102,7 +168,6 @@ Feature: deleteUserCards tests """ { "publisher" : "publisherKarate", - "publisherType" : "EXTERNAL", "processVersion" : "1", "process" :"processDeleteUserCard", "processInstanceId" : "processDeleteUserCardForbidden1", @@ -120,7 +185,6 @@ Feature: deleteUserCards tests """ { "publisher" : "ENTITY2", - "publisherType" : "ENTITY", "processVersion" : "1", "process" :"processDeleteUserCard", "processInstanceId" : "processDeleteUserCardForbidden2", @@ -138,7 +202,6 @@ Feature: deleteUserCards tests """ { "publisher" : "ENTITY1", - "publisherType" : "ENTITY", "processVersion" : "1", "process" :"processDeleteUserCard", "processInstanceId" : "processDeleteUserCardForbidden3", @@ -153,7 +216,8 @@ Feature: deleteUserCards tests """ # Push cardForDeleteOk - Given url opfabPublishCardUrl + 'cards' + Given url opfabPublishCardUrl + 'cards/userCard' + And header Authorization = 'Bearer ' + authTokenAsTSO And request cardForDeleteOk When method post Then status 201 @@ -168,7 +232,8 @@ Feature: deleteUserCards tests And match response.count == 1 # Push cardForDeleteForbidden2 - Given url opfabPublishCardUrl + 'cards' + Given url opfabPublishCardUrl + 'cards/userCard' + And header Authorization = 'Bearer ' + authTokenAsTSO2 And request cardForDeleteForbidden2 When method post Then status 201 @@ -176,7 +241,8 @@ Feature: deleteUserCards tests # Push cardForDeleteForbidden3 - Given url opfabPublishCardUrl + 'cards' + Given url opfabPublishCardUrl + 'cards/userCard' + And header Authorization = 'Bearer ' + authTokenAsTSO2 And request cardForDeleteForbidden3 When method post Then status 201 diff --git a/src/test/utils/karate/businessconfig/postBundleUserCardExamples.feature b/src/test/utils/karate/businessconfig/postBundleUserCardExamples.feature index aaf7e9bbb4..9ffaa28cb5 100644 --- a/src/test/utils/karate/businessconfig/postBundleUserCardExamples.feature +++ b/src/test/utils/karate/businessconfig/postBundleUserCardExamples.feature @@ -22,11 +22,7 @@ Feature: Bundle When method GET Then status 200 And match response.id == 'userCardExamples' - And match response.states.questionState.userCard.template == 'usercard_question' - And match response.states.questionState.userCard.severityVisible == false - And match response.states.questionState.userCard.startDateVisible == true - And match response.states.questionState.userCard.endDateVisible == true - And match response.states.questionState.showDetailCardHeader == false + And match response.states.conferenceState.userCard.template == 'usercard_conference' And match response.states.incidentInProgressState.userCard.template == 'usercard_incidentInProgress' And match response.states.incidentInProgressState.userCard.severityVisible == true And match response.states.incidentInProgressState.userCard.startDateVisible == false diff --git a/src/test/utils/karate/businessconfig/postBundleUserCardExamples2.feature b/src/test/utils/karate/businessconfig/postBundleUserCardExamples2.feature new file mode 100644 index 0000000000..832f3a6600 --- /dev/null +++ b/src/test/utils/karate/businessconfig/postBundleUserCardExamples2.feature @@ -0,0 +1,30 @@ +Feature: Bundle + + Background: + # Get admin token + * def signIn = call read('../common/getToken.feature') { username: 'admin'} + * def authToken = signIn.authToken + + + Scenario: Post Bundle + + + # Push bundle + Given url opfabUrl + 'businessconfig/processes' + And header Authorization = 'Bearer ' + authToken + And multipart field file = read('resources/bundle_userCardExamples2.tar.gz') + When method post + Then status 201 + + # Check bundle + Given url opfabUrl + 'businessconfig/processes/userCardExamples2' + And header Authorization = 'Bearer ' + authToken + When method GET + Then status 200 + And match response.id == 'userCardExamples2' + And match response.states.questionState.userCard.template == 'usercard_question' + And match response.states.questionState.userCard.severityVisible == false + And match response.states.questionState.userCard.startDateVisible == true + And match response.states.questionState.userCard.endDateVisible == true + And match response.states.questionState.showDetailCardHeader == false + And match response.states.messageState.userCard.template == 'usercard_message' diff --git a/src/test/utils/karate/businessconfig/postBundleUserCardExamples3.feature b/src/test/utils/karate/businessconfig/postBundleUserCardExamples3.feature new file mode 100644 index 0000000000..1701dc8e64 --- /dev/null +++ b/src/test/utils/karate/businessconfig/postBundleUserCardExamples3.feature @@ -0,0 +1,25 @@ +Feature: Bundle + + Background: + # Get admin token + * def signIn = call read('../common/getToken.feature') { username: 'admin'} + * def authToken = signIn.authToken + + + Scenario: Post Bundle + + + # Push bundle + Given url opfabUrl + 'businessconfig/processes' + And header Authorization = 'Bearer ' + authToken + And multipart field file = read('resources/bundle_userCardExamples3.tar.gz') + When method post + Then status 201 + + # Check bundle + Given url opfabUrl + 'businessconfig/processes/userCardExamples3' + And header Authorization = 'Bearer ' + authToken + When method GET + Then status 200 + And match response.id == 'userCardExamples3' + And match response.states.taskState.userCard.template == 'usercard_task' diff --git a/src/test/utils/karate/businessconfig/postProcessGroups.feature b/src/test/utils/karate/businessconfig/postProcessGroups.feature new file mode 100644 index 0000000000..efe74c0f25 --- /dev/null +++ b/src/test/utils/karate/businessconfig/postProcessGroups.feature @@ -0,0 +1,22 @@ +Feature: Process groups + + Background: + # Get admin token + * def signIn = call read('../common/getToken.feature') { username: 'admin'} + * def authToken = signIn.authToken + + + Scenario: Post process groups file + Given url opfabUrl + '/businessconfig/processgroups' + And header Authorization = 'Bearer ' + authToken + And multipart file file = { read: 'resources/processgroups.json' } + When method post + And status 201 + + + Scenario: Check that process groups have been updated + Given url opfabUrl + '/businessconfig/processgroups' + And header Authorization = 'Bearer ' + authToken + When method GET + Then status 200 + diff --git a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/config.json b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/config.json index 46b4734c27..16c33677dc 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/config.json +++ b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/config.json @@ -15,9 +15,6 @@ "userCard" : { "template" : "usercard_message" }, - "detailTitle": { - "key": "message.title" - }, "templateName": "template", "styles": [ "style" @@ -28,9 +25,6 @@ "name": "chartDetail.title", "description": "chartState.description", "color": "#DA00DA", - "detailTitle": { - "key": "chartDetail.title" - }, "templateName": "chart", "styles": [ "style" @@ -41,9 +35,6 @@ "name": "chartLine.title", "description": "chartLineState.description", "color": "#6666FF", - "detailTitle": { - "key": "chartLine.title" - }, "templateName": "chart-line", "styles": [ "style" @@ -57,9 +48,6 @@ "userCard" : { "template" : "usercard_process" }, - "detailTitle": { - "key": "process.label" - }, "templateName": "process", "styles": [ "style" @@ -70,9 +58,6 @@ "name": "contingencies.title", "description": "contingenciesState.description", "color": "#0070C0", - "detailTitle": { - "key": "contingencies.title" - }, "templateName": "contingencies", "styles": [ "contingencies" @@ -91,9 +76,6 @@ "key": "question.button.text" } }, - "detailTitle": { - "key": "question.title" - }, "templateName": "question", "styles": [ "style" @@ -104,9 +86,6 @@ "name": "response.title", "description": "responseState.description", "color": "#0070C0", - "detailTitle": { - "key": "response.title" - }, "templateName": "response", "styles": [ "style" diff --git a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/process.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/process.handlebars index 8e906ab7ff..795bc33f79 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/process.handlebars +++ b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/process.handlebars @@ -3,7 +3,7 @@

-
process start
process start
+
process start
process start
Calcul 2
Calcul 2
Calcul 1
Calcul 1
Calcul 3
Calcul 3
Viewer does not support full SVG 1.1
@@ -16,5 +16,20 @@ var stateColor = "#aaffaa"; if (document.getElementById("error").getAttribute("value")=="true") stateColor="red"; console.log("color = " + stateColor ); document.getElementById(rect).setAttribute("fill",stateColor); + +templateGateway.setScreenSize = function(size) { + const chart = document.getElementById('chart'); + if (chart) { + if (size === 'lg') { + chart.setAttribute("width", "181px"); + chart.setAttribute("height", "466px"); + } else { + chart.setAttribute("width", "111px"); + chart.setAttribute("height", "311px"); + } + } + + } + \ No newline at end of file diff --git a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/question.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/question.handlebars index 34c0f9f36d..de1a80d87c 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/question.handlebars +++ b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/en/question.handlebars @@ -9,6 +9,7 @@
+

@@ -77,6 +78,18 @@ } + templateGateway.setLttdExpired = function(expired) { + const responseEnabled = document.getElementById('responseDisabled'); + if (responseEnabled != null) { + if (expired) { + responseEnabled.innerHTML="Response time has expired"; + templateGateway.lockAnswer(); + } else { + responseEnabled.innerHTML=""; + templateGateway.unlockAnswer(); + } + } + } diff --git a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/process.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/process.handlebars index 3d1588d372..af085df586 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/process.handlebars +++ b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/process.handlebars @@ -3,7 +3,7 @@

-
process start
process start
+
process start
process start
Calcul 2
Calcul 2
Calcul 1
Calcul 1
Calcul 3
Calcul 3
Viewer does not support full SVG 1.1
@@ -16,5 +16,20 @@ var stateColor = "#aaffaa"; if (document.getElementById("error").getAttribute("value")=="true") stateColor="red"; console.log("color = " + stateColor ); document.getElementById(rect).setAttribute("fill",stateColor); + +templateGateway.setScreenSize = function(size) { + const chart = document.getElementById('chart'); + if (chart) { + if (size === 'lg') { + chart.setAttribute("width", "181px"); + chart.setAttribute("height", "466px"); + } else { + chart.setAttribute("width", "111px"); + chart.setAttribute("height", "311px"); + } + } + + } + \ No newline at end of file diff --git a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/question.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/question.handlebars index f1a0dd7f6c..210a43c8de 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/question.handlebars +++ b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess/template/fr/question.handlebars @@ -11,6 +11,7 @@
+

@@ -82,6 +83,19 @@ } + templateGateway.setLttdExpired = function(expired) { + const responseEnabled = document.getElementById('responseDisabled'); + if (responseEnabled != null) { + if (expired) { + responseEnabled.innerHTML="Response time has expired"; + templateGateway.lockAnswer(); + } else { + responseEnabled.innerHTML=""; + templateGateway.unlockAnswer(); + } + } + } + diff --git a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess_V0.1/config.json b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess_V0.1/config.json index 10f4182681..d3e375b980 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess_V0.1/config.json +++ b/src/test/utils/karate/businessconfig/resources/bundle_defaultProcess_V0.1/config.json @@ -6,9 +6,6 @@ "messageState": { "name": "defaultProcess.title", "color": "#CC9900", - "detailTitle": { - "key": "defaultProcess.title" - }, "templateName": "template", "styles": [ "style" diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/config.json b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/config.json index 1e2d592c5e..20ae8aa492 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/config.json +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/config.json @@ -8,66 +8,16 @@ "calendar": true }, "states": { - "messageState": { - "name": "message.title", - "color": "#CC9900", - "userCard" : { - "template" : "usercard_message" - }, - "detailTitle": { - "key": "message.title" - }, - "templateName": "message", - "styles": [], - "acknowledgmentAllowed": "Always" - }, "conferenceState": { "name": "conference.title", "color": "#CC9900", "userCard" : { "template" : "usercard_conference" }, - "detailTitle": { - "key": "conference.title" - }, "templateName": "conference", "styles": [], "acknowledgmentAllowed": "Always" }, - "questionState": { - "name": "question.title", - "showDetailCardHeader": false, - "color": "#0070C0", - "userCard" : { - "template" : "usercard_question", - "severityVisible" : false, - "startDateVisible" : true, - "endDateVisible" : true - }, - "response": { - "state": "questionState" - }, - "detailTitle": { - "key": "question.title" - }, - "templateName": "question", - "styles": [], - "acknowledgmentAllowed": "Never" - }, - "taskState": { - "name": "task.title", - "color": "#0070C0", - "userCard" : { - "template" : "usercard_task" - }, - "detailTitle": { - "key": "task.title" - }, - "templateName": "task", - "styles": [ - ], - "acknowledgmentAllowed": "Always" - }, "incidentInProgressState": { "name": "incidentInProgress.name", "userCard" : { @@ -80,9 +30,6 @@ "response": { "state": "incidentInProgressState" }, - "detailTitle": { - "key": "incidentInProgress.name" - }, "templateName": "incidentInProgress", "styles": [], "acknowledgmentAllowed": "OnlyWhenResponseDisabledForUser" diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/en.json b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/en.json index c2a0ebe90f..688d6e8eaf 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/en.json +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/en.json @@ -1,21 +1,9 @@ { "userCardExamples": {"label": "Examples for new cards "}, - "message":{ - "title":"Message", - "summary":"Message received" - }, "conference":{ "title":"Conference Call ☏", "summary":"You are invited to a conference" }, - "question":{ - "title":"Question ", - "summary":"There is a question for you" - }, - "task":{ - "title":"Task ", - "summary":"There is something to do" - }, "incidentInProgress":{ "name":"IT Incident", "title":"IT Incident ", diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/fr.json b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/fr.json index 984d49bbf6..963b87904a 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/fr.json +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/i18n/fr.json @@ -1,21 +1,9 @@ { "userCardExamples": {"label": "Exemples de nouvelles cartes "}, - "message":{ - "title":"Message", - "summary":"Message reçu" - }, "conference":{ "title":"Conférence téléphonique ☏", "summary":"Vous êtes invité à une conférence téléphonique" }, - "question":{ - "title":"Question", - "summary":"Il y a une question pour vous" - }, - "task":{ - "title":"Tâche ", - "summary":"Il y a quelque chose à faire " - }, "incidentInProgress":{ "name":"Incident SI", "title":"Incident SI ", diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/config.json b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/config.json new file mode 100644 index 0000000000..2d521ddf1f --- /dev/null +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/config.json @@ -0,0 +1,39 @@ +{ + "id": "userCardExamples2", + "name": "userCardExamples2.label", + "version": "1", + "uiVisibility": { + "monitoring": true, + "logging": true, + "calendar": true + }, + "states": { + "messageState": { + "name": "message.title", + "color": "#CC9900", + "userCard" : { + "template" : "usercard_message" + }, + "templateName": "message", + "styles": [], + "acknowledgmentAllowed": "Always" + }, + "questionState": { + "name": "question.title", + "showDetailCardHeader": false, + "color": "#0070C0", + "userCard" : { + "template" : "usercard_question", + "severityVisible" : false, + "startDateVisible" : true, + "endDateVisible" : true + }, + "response": { + "state": "questionState" + }, + "templateName": "question", + "styles": [], + "acknowledgmentAllowed": "Never" + } + } +} \ No newline at end of file diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/i18n/en.json b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/i18n/en.json new file mode 100644 index 0000000000..b14ca21c05 --- /dev/null +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/i18n/en.json @@ -0,0 +1,11 @@ +{ + "userCardExamples2": {"label": "Examples for new cards 2"}, + "message":{ + "title":"Message", + "summary":"Message received" + }, + "question":{ + "title":"Question ", + "summary":"There is a question for you" + } +} diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/i18n/fr.json b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/i18n/fr.json new file mode 100644 index 0000000000..b4d111debe --- /dev/null +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/i18n/fr.json @@ -0,0 +1,11 @@ +{ + "userCardExamples2": {"label": "Exemples de nouvelles cartes 2"}, + "message":{ + "title":"Message", + "summary":"Message reçu" + }, + "question":{ + "title":"Question", + "summary":"Il y a une question pour vous" + } +} diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/message.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/message.handlebars similarity index 100% rename from src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/message.handlebars rename to src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/message.handlebars diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/question.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/question.handlebars similarity index 100% rename from src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/question.handlebars rename to src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/question.handlebars diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/usercard_message.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/usercard_message.handlebars similarity index 94% rename from src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/usercard_message.handlebars rename to src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/usercard_message.handlebars index 6cda4bbfc8..7fe6cd0968 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/usercard_message.handlebars +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/usercard_message.handlebars @@ -11,7 +11,7 @@
+ style="width:100%">{{card.data.message}}
diff --git a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/usercard_question.handlebars b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/usercard_question.handlebars similarity index 90% rename from src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/usercard_question.handlebars rename to src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/usercard_question.handlebars index e00ec695cb..66dc42c82d 100644 --- a/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples/template/en/usercard_question.handlebars +++ b/src/test/utils/karate/businessconfig/resources/bundle_userCardExamples2/template/en/usercard_question.handlebars @@ -15,6 +15,11 @@