From 07d48b078124d98cef8a7523270e45943e2ae76a Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 28 Jun 2022 18:27:48 +0300 Subject: [PATCH 1/6] docker-compose checkFolders: create and set owner --- docker/compose-utils.sh | 74 +++++++++++++++++++++++++++++ docker/docker-check-log-folders.sh | 21 ++++++++ docker/docker-create-log-folders.sh | 39 ++------------- docker/docker-install-tb.sh | 2 + docker/docker-start-services.sh | 2 + docker/docker-upgrade-tb.sh | 2 + 6 files changed, 104 insertions(+), 36 deletions(-) create mode 100755 docker/docker-check-log-folders.sh diff --git a/docker/compose-utils.sh b/docker/compose-utils.sh index 28601afa3c..bbd8357a87 100755 --- a/docker/compose-utils.sh +++ b/docker/compose-utils.sh @@ -121,3 +121,77 @@ function additionalStartupServices() { echo $ADDITIONAL_STARTUP_SERVICES } + +function permissionList() { + PERMISSION_LIST=" + 799 799 tb-node/log + 799 799 tb-transports/coap/log + 799 799 tb-transports/lwm2m/log + 799 799 tb-transports/http/log + 799 799 tb-transports/mqtt/log + 799 799 tb-transports/snmp/log + 799 799 tb-transports/coap/log + 799 799 tb-vc-executor/log + 999 999 tb-node/postgres + " + + source .env + + if [ "$DATABASE" = "hybrid" ]; then + PERMISSION_LIST="$PERMISSION_LIST + 999 999 tb-node/cassandra + " + fi + + CACHE="${CACHE:-redis}" + case $CACHE in + redis) + PERMISSION_LIST="$PERMISSION_LIST + 1001 1001 tb-node/redis-data + " + ;; + redis-cluster) + PERMISSION_LIST="$PERMISSION_LIST + 1001 1001 tb-node/redis-cluster-data-0 + 1001 1001 tb-node/redis-cluster-data-1 + 1001 1001 tb-node/redis-cluster-data-2 + 1001 1001 tb-node/redis-cluster-data-3 + 1001 1001 tb-node/redis-cluster-data-4 + 1001 1001 tb-node/redis-cluster-data-5 + " + ;; + *) + echo "Unknown CACHE value specified in the .env file: '${CACHE}'. Should be either 'redis' or 'redis-cluster'." >&2 + exit 1 + esac + + echo "$PERMISSION_LIST" +} + +function checkFolders() { + EXIT_CODE=0 + PERMISSION_LIST=$(permissionList) || exit $? + set -e + while read -r USR GRP DIR + do + if [ -z "$DIR" ]; then # skip empty lines + continue + fi + MESSAGE="Checking user ${USR} group ${GRP} dir ${DIR} " + if [[ -d "$DIR" ]] && + [[ $(ls -ldn "$DIR" | awk '{print $3}') -eq "$USR" ]] && + [[ $(ls -ldn "$DIR" | awk '{print $4}') -eq "$GRP" ]] + then + MESSAGE="$MESSAGE OK" + else + if [ "$1" = "--create" ]; then + echo "Create and chown: user ${USR} group ${GRP} dir ${DIR}" + mkdir -p "$DIR" && sudo chown -R "$USR":"$GRP" "$DIR" + else + echo "$MESSAGE FAILED" + EXIT_CODE=1 + fi + fi + done < <(echo "$PERMISSION_LIST") + return $EXIT_CODE +} diff --git a/docker/docker-check-log-folders.sh b/docker/docker-check-log-folders.sh new file mode 100755 index 0000000000..66e7ea394c --- /dev/null +++ b/docker/docker-check-log-folders.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Copyright © 2016-2022 The Thingsboard Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set -e +source compose-utils.sh +checkFolders || exit $? +echo "OK" diff --git a/docker/docker-create-log-folders.sh b/docker/docker-create-log-folders.sh index 6224b7040b..54a74f4812 100755 --- a/docker/docker-create-log-folders.sh +++ b/docker/docker-create-log-folders.sh @@ -15,39 +15,6 @@ # limitations under the License. # -mkdir -p tb-node/log && sudo chown -R 799:799 tb-node/log - -mkdir -p tb-transports/coap/log && sudo chown -R 799:799 tb-transports/coap/log - -mkdir -p tb-transports/lwm2m/log && sudo chown -R 799:799 tb-transports/lwm2m/log - -mkdir -p tb-transports/http/log && sudo chown -R 799:799 tb-transports/http/log - -mkdir -p tb-transports/mqtt/log && sudo chown -R 799:799 tb-transports/mqtt/log - -mkdir -p tb-transports/snmp/log && sudo chown -R 799:799 tb-transports/snmp/log - -mkdir -p tb-vc-executor/log && sudo chown -R 799:799 tb-vc-executor/log - -mkdir -p tb-node/postgres && sudo chown -R 999:999 tb-node/postgres - -mkdir -p tb-node/cassandra && sudo chown -R 999:999 tb-node/cassandra - -source .env -CACHE="${CACHE:-redis}" -case $CACHE in - redis) - mkdir -p tb-node/redis-data && sudo chown -R 1001:1001 tb-node/redis-data - ;; - redis-cluster) - mkdir -p tb-node/redis-cluster-data-0 && sudo chown -R 1001:1001 tb-node/redis-cluster-data-0 - mkdir -p tb-node/redis-cluster-data-1 && sudo chown -R 1001:1001 tb-node/redis-cluster-data-1 - mkdir -p tb-node/redis-cluster-data-2 && sudo chown -R 1001:1001 tb-node/redis-cluster-data-2 - mkdir -p tb-node/redis-cluster-data-3 && sudo chown -R 1001:1001 tb-node/redis-cluster-data-3 - mkdir -p tb-node/redis-cluster-data-4 && sudo chown -R 1001:1001 tb-node/redis-cluster-data-4 - mkdir -p tb-node/redis-cluster-data-5 && sudo chown -R 1001:1001 tb-node/redis-cluster-data-5 - ;; - *) - echo "Unknown CACHE value specified in the .env file: '${CACHE}'. Should be either 'redis' or 'redis-cluster'." >&2 - exit 1 -esac \ No newline at end of file +set -e +source compose-utils.sh +checkFolders --create diff --git a/docker/docker-install-tb.sh b/docker/docker-install-tb.sh index 9129c72796..f86b82acc8 100755 --- a/docker/docker-install-tb.sh +++ b/docker/docker-install-tb.sh @@ -41,6 +41,8 @@ set -e source compose-utils.sh +checkFolders --create || exit $? + ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? diff --git a/docker/docker-start-services.sh b/docker/docker-start-services.sh index 9e5d08add9..4762f1a040 100755 --- a/docker/docker-start-services.sh +++ b/docker/docker-start-services.sh @@ -19,6 +19,8 @@ set -e source compose-utils.sh +checkFolders --create || exit $? + ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? diff --git a/docker/docker-upgrade-tb.sh b/docker/docker-upgrade-tb.sh index 260e14cf8b..d0c82f6794 100755 --- a/docker/docker-upgrade-tb.sh +++ b/docker/docker-upgrade-tb.sh @@ -40,6 +40,8 @@ set -e source compose-utils.sh +checkFolders --create || exit $? + ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? From 2841d6b6f25d40ac1efab0b388f9fb0bb370ba23 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 28 Jun 2022 18:48:37 +0300 Subject: [PATCH 2/6] compose-utils: whitespace removed --- docker/compose-utils.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/compose-utils.sh b/docker/compose-utils.sh index bbd8357a87..f45339eb92 100755 --- a/docker/compose-utils.sh +++ b/docker/compose-utils.sh @@ -177,7 +177,7 @@ function checkFolders() { if [ -z "$DIR" ]; then # skip empty lines continue fi - MESSAGE="Checking user ${USR} group ${GRP} dir ${DIR} " + MESSAGE="Checking user ${USR} group ${GRP} dir ${DIR}" if [[ -d "$DIR" ]] && [[ $(ls -ldn "$DIR" | awk '{print $3}') -eq "$USR" ]] && [[ $(ls -ldn "$DIR" | awk '{print $4}') -eq "$GRP" ]] From 2f9537449179f1836f30c50efda9c6c9bdae3823 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 28 Jun 2022 19:02:43 +0300 Subject: [PATCH 3/6] docker-compose checkFolders: refactored for easier merge with docker-compose project --- docker/docker-install-tb.sh | 4 ++-- docker/docker-start-services.sh | 4 ++-- docker/docker-upgrade-tb.sh | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/docker-install-tb.sh b/docker/docker-install-tb.sh index f86b82acc8..628b16e6ee 100755 --- a/docker/docker-install-tb.sh +++ b/docker/docker-install-tb.sh @@ -41,8 +41,6 @@ set -e source compose-utils.sh -checkFolders --create || exit $? - ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? @@ -51,6 +49,8 @@ ADDITIONAL_CACHE_ARGS=$(additionalComposeCacheArgs) || exit $? ADDITIONAL_STARTUP_SERVICES=$(additionalStartupServices) || exit $? +checkFolders --create || exit $? + if [ ! -z "${ADDITIONAL_STARTUP_SERVICES// }" ]; then docker-compose \ -f docker-compose.yml $ADDITIONAL_CACHE_ARGS $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS \ diff --git a/docker/docker-start-services.sh b/docker/docker-start-services.sh index 4762f1a040..1a06946308 100755 --- a/docker/docker-start-services.sh +++ b/docker/docker-start-services.sh @@ -19,8 +19,6 @@ set -e source compose-utils.sh -checkFolders --create || exit $? - ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? @@ -29,6 +27,8 @@ ADDITIONAL_CACHE_ARGS=$(additionalComposeCacheArgs) || exit $? ADDITIONAL_COMPOSE_MONITORING_ARGS=$(additionalComposeMonitoringArgs) || exit $? +checkFolders --create || exit $? + docker-compose \ -f docker-compose.yml $ADDITIONAL_CACHE_ARGS $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS $ADDITIONAL_COMPOSE_MONITORING_ARGS \ up -d diff --git a/docker/docker-upgrade-tb.sh b/docker/docker-upgrade-tb.sh index d0c82f6794..87dff9da15 100755 --- a/docker/docker-upgrade-tb.sh +++ b/docker/docker-upgrade-tb.sh @@ -40,8 +40,6 @@ set -e source compose-utils.sh -checkFolders --create || exit $? - ADDITIONAL_COMPOSE_QUEUE_ARGS=$(additionalComposeQueueArgs) || exit $? ADDITIONAL_COMPOSE_ARGS=$(additionalComposeArgs) || exit $? @@ -50,6 +48,8 @@ ADDITIONAL_CACHE_ARGS=$(additionalComposeCacheArgs) || exit $? ADDITIONAL_STARTUP_SERVICES=$(additionalStartupServices) || exit $? +checkFolders --create || exit $? + docker-compose \ -f docker-compose.yml $ADDITIONAL_CACHE_ARGS $ADDITIONAL_COMPOSE_ARGS $ADDITIONAL_COMPOSE_QUEUE_ARGS \ pull \ From 395d4f49004c57f471fdaa727b26cbf518e1d961 Mon Sep 17 00:00:00 2001 From: fe-dev Date: Wed, 29 Jun 2022 09:20:40 +0300 Subject: [PATCH 4/6] UI: Bug fix validation queue form --- .../app/modules/home/components/queue/queue-form.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts index b84dfc9985..c1aecea4b2 100644 --- a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts +++ b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts @@ -209,6 +209,7 @@ export class QueueFormComponent implements ControlValueAccessor, OnInit, OnDestr } else { batchSizeField.patchValue(null, {emitEvent: false}); batchSizeField.clearValidators(); + batchSizeField.updateValueAndValidity(); this.hideBatchSize = false; } } From 27e3070b7a8cbb04ad8b0e7a3133410d914bcfb0 Mon Sep 17 00:00:00 2001 From: fe-dev Date: Wed, 29 Jun 2022 15:02:30 +0300 Subject: [PATCH 5/6] UI: Refactoring --- .../app/modules/home/components/queue/queue-form.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts index c1aecea4b2..add3c26007 100644 --- a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts +++ b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.ts @@ -205,11 +205,12 @@ export class QueueFormComponent implements ControlValueAccessor, OnInit, OnDestr if (type === QueueSubmitStrategyTypes.BATCH) { batchSizeField.patchValue(1000, {emitEvent: false}); batchSizeField.setValidators([Validators.min(1), Validators.required]); + batchSizeField.updateValueAndValidity({emitEvent: false}); this.hideBatchSize = true; } else { batchSizeField.patchValue(null, {emitEvent: false}); batchSizeField.clearValidators(); - batchSizeField.updateValueAndValidity(); + batchSizeField.updateValueAndValidity({emitEvent: false}); this.hideBatchSize = false; } } From 4b5e94e3cc6e9813bed3385e9d4bb2c766ff13a4 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 29 Jun 2022 17:35:13 +0300 Subject: [PATCH 6/6] Add Version control REST API methods to Rest Client. Remove redudant branch request parameter from some version control REST API methods. --- .../server/controller/AssetController.java | 4 +- .../server/controller/DeviceController.java | 4 +- .../server/controller/EdgeController.java | 4 +- .../EntitiesVersionControlController.java | 22 +- .../service/asset/AssetBulkImportService.java | 2 +- .../device/DeviceBulkImportService.java | 2 +- .../service/edge/EdgeBulkImportService.java | 2 +- .../csv/AbstractBulkImportService.java | 3 + .../DefaultEntitiesVersionControlService.java | 10 +- .../DefaultGitVersionControlQueueService.java | 119 ++++---- .../vc/EntitiesVersionControlService.java | 6 +- .../vc/GitVersionControlQueueService.java | 4 +- .../importing/csv/BulkImportColumnType.java | 2 +- .../ie/importing/csv/BulkImportRequest.java | 2 +- .../ie/importing/csv/BulkImportResult.java | 2 +- .../common/data/sync/vc/BranchInfo.java | 3 + .../vc/request/load/VersionLoadRequest.java | 1 - .../server/service/sync/vc/GitRepository.java | 6 +- .../thingsboard/rest/client/RestClient.java | 266 +++++++++++++++++- .../http/entities-version-control.service.ts | 6 +- .../vc/complex-version-load.component.ts | 4 - .../vc/entity-version-diff.component.ts | 6 +- .../vc/entity-version-restore.component.ts | 4 - .../vc/entity-versions-table.component.ts | 3 - ui-ngx/src/app/shared/models/vc.models.ts | 1 - 25 files changed, 369 insertions(+), 119 deletions(-) rename {application/src/main/java/org/thingsboard/server/service => common/data/src/main/java/org/thingsboard/server/common/data}/sync/ie/importing/csv/BulkImportColumnType.java (97%) rename {application/src/main/java/org/thingsboard/server/service => common/data/src/main/java/org/thingsboard/server/common/data}/sync/ie/importing/csv/BulkImportRequest.java (94%) rename {application/src/main/java/org/thingsboard/server/service => common/data/src/main/java/org/thingsboard/server/common/data}/sync/ie/importing/csv/BulkImportResult.java (94%) diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 13ef646eaa..f1ff6aa3c6 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -51,8 +51,8 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.asset.AssetBulkImportService; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportRequest; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportResult; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; import org.thingsboard.server.service.entitiy.asset.TbAssetService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 183b5ea048..895e711073 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -66,8 +66,8 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.device.DeviceBulkImportService; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportRequest; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportResult; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; import org.thingsboard.server.service.entitiy.device.TbDeviceService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index b3c1792b6a..5b2c6a6a9d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -53,8 +53,8 @@ import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.EdgeBulkImportService; import org.thingsboard.server.service.entitiy.edge.TbEdgeService; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportRequest; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportResult; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; diff --git a/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java b/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java index 2e37bcbe59..65b5f10407 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java @@ -310,15 +310,13 @@ public class EntitiesVersionControlController extends BaseController { "Each entity item in the result has `externalId` property. " + "Entities order will be the same as in the repository." + TENANT_AUTHORITY_PARAGRAPH) - @GetMapping(value = "/entity/{entityType}/{versionId}", params = {"branch"}) + @GetMapping(value = "/entity/{entityType}/{versionId}") public DeferredResult> listEntitiesAtVersion(@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable EntityType entityType, @ApiParam(value = VERSION_ID_PARAM_DESCRIPTION, required = true) - @PathVariable String versionId, - @ApiParam(value = BRANCH_PARAM_DESCRIPTION, required = true) - @RequestParam String branch) throws Exception { + @PathVariable String versionId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); - return wrapFuture(versionControlService.listEntitiesAtVersion(getTenantId(), branch, versionId, entityType)); + return wrapFuture(versionControlService.listEntitiesAtVersion(getTenantId(), versionId, entityType)); } @ApiOperation(value = "List all entities at version (listAllEntitiesAtVersion)", notes = "" + @@ -326,13 +324,11 @@ public class EntitiesVersionControlController extends BaseController { "Response type is the same as for listAllEntitiesAtVersion API method. \n" + "Returned entities order will be the same as in the repository." + TENANT_AUTHORITY_PARAGRAPH) - @GetMapping(value = "/entity/{versionId}", params = {"branch"}) + @GetMapping(value = "/entity/{versionId}") public DeferredResult> listAllEntitiesAtVersion(@ApiParam(value = VERSION_ID_PARAM_DESCRIPTION, required = true) - @PathVariable String versionId, - @ApiParam(value = BRANCH_PARAM_DESCRIPTION, required = true) - @RequestParam String branch) throws Exception { + @PathVariable String versionId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); - return wrapFuture(versionControlService.listAllEntitiesAtVersion(getTenantId(), branch, versionId)); + return wrapFuture(versionControlService.listAllEntitiesAtVersion(getTenantId(), versionId)); } @ApiOperation(value = "Get entity data info (getEntityDataInfo)", notes = "" + @@ -357,18 +353,16 @@ public class EntitiesVersionControlController extends BaseController { "Returns an object with current entity data and the one at a specific version. " + "Entity data structure is the same as stored in a repository. " + TENANT_AUTHORITY_PARAGRAPH) - @GetMapping(value = "/diff/{entityType}/{internalEntityUuid}", params = {"branch", "versionId"}) + @GetMapping(value = "/diff/{entityType}/{internalEntityUuid}", params = {"versionId"}) public DeferredResult compareEntityDataToVersion(@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable EntityType entityType, @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable UUID internalEntityUuid, - @ApiParam(value = BRANCH_PARAM_DESCRIPTION) - @RequestParam String branch, @ApiParam(value = VERSION_ID_PARAM_DESCRIPTION, required = true) @RequestParam String versionId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, internalEntityUuid); - return wrapFuture(versionControlService.compareEntityDataToVersion(getCurrentUser(), branch, entityId, versionId)); + return wrapFuture(versionControlService.compareEntityDataToVersion(getCurrentUser(), entityId, versionId)); } @ApiOperation(value = "Load entities version (loadEntitiesVersion)", notes = "" + diff --git a/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java index 5eaeec0b73..ff89c3dd06 100644 --- a/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.sync.ie.importing.csv.AbstractBulkImportService; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportColumnType; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportColumnType; import org.thingsboard.server.service.entitiy.asset.TbAssetService; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java index c04dd5ce15..8b2126905f 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java @@ -50,7 +50,7 @@ import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.sync.ie.importing.csv.AbstractBulkImportService; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportColumnType; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportColumnType; import org.thingsboard.server.service.entitiy.device.TbDeviceService; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java index 404e5af5fd..8372e2ba0e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java @@ -29,7 +29,7 @@ import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.sync.ie.importing.csv.AbstractBulkImportService; -import org.thingsboard.server.service.sync.ie.importing.csv.BulkImportColumnType; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportColumnType; import org.thingsboard.server.service.entitiy.edge.TbEdgeService; import org.thingsboard.server.service.security.model.SecurityUser; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java index b92e100401..becf92771f 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java @@ -39,6 +39,9 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; import org.thingsboard.server.common.data.kv.DataType; import org.thingsboard.server.common.data.kv.TsKvEntry; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportColumnType; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.transport.adaptor.JsonConverter; import org.thingsboard.server.controller.BaseController; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java index 88a15f7cdc..00e98cd3a1 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java @@ -241,13 +241,13 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont } @Override - public ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String branch, String versionId, EntityType entityType) throws Exception { - return gitServiceQueue.listEntitiesAtVersion(tenantId, branch, versionId, entityType); + public ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String versionId, EntityType entityType) throws Exception { + return gitServiceQueue.listEntitiesAtVersion(tenantId, versionId, entityType); } @Override - public ListenableFuture> listAllEntitiesAtVersion(TenantId tenantId, String branch, String versionId) throws Exception { - return gitServiceQueue.listEntitiesAtVersion(tenantId, branch, versionId); + public ListenableFuture> listAllEntitiesAtVersion(TenantId tenantId, String versionId) throws Exception { + return gitServiceQueue.listEntitiesAtVersion(tenantId, versionId); } @SuppressWarnings({"UnstableApiUsage", "rawtypes"}) @@ -451,7 +451,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont } @Override - public ListenableFuture compareEntityDataToVersion(User user, String branch, EntityId entityId, String versionId) throws Exception { + public ListenableFuture compareEntityDataToVersion(User user, EntityId entityId, String versionId) throws Exception { HasId entity = exportableEntitiesService.findEntityByTenantIdAndId(user.getTenantId(), entityId); if (!(entity instanceof ExportableEntity)) throw new IllegalArgumentException("Unsupported entity type"); diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitVersionControlQueueService.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitVersionControlQueueService.java index 6eaa2df74f..c9b620ad1c 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitVersionControlQueueService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitVersionControlQueueService.java @@ -245,7 +245,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu } @Override - public ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String branch, String versionId, EntityType entityType) { + public ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String versionId, EntityType entityType) { return listEntitiesAtVersion(tenantId, ListEntitiesRequestMsg.newBuilder() .setVersionId(versionId) .setEntityType(entityType.name()) @@ -253,7 +253,7 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu } @Override - public ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String branch, String versionId) { + public ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String versionId) { return listEntitiesAtVersion(tenantId, ListEntitiesRequestMsg.newBuilder() .setVersionId(versionId) .build()); @@ -385,66 +385,71 @@ public class DefaultGitVersionControlQueueService implements GitVersionControlQu if (!StringUtils.isEmpty(vcResponseMsg.getError())) { future.setException(new RuntimeException(vcResponseMsg.getError())); } else { - if (vcResponseMsg.hasGenericResponse()) { - future.set(null); - } else if (vcResponseMsg.hasCommitResponse()) { - var commitResponse = vcResponseMsg.getCommitResponse(); - var commitResult = new VersionCreationResult(); - if (commitResponse.getTs() > 0) { - commitResult.setVersion(new EntityVersion(commitResponse.getTs(), commitResponse.getCommitId(), commitResponse.getName(), commitResponse.getAuthor())); - } - commitResult.setAdded(commitResponse.getAdded()); - commitResult.setRemoved(commitResponse.getRemoved()); - commitResult.setModified(commitResponse.getModified()); - commitResult.setDone(true); - ((CommitGitRequest) request).getFuture().set(commitResult); - } else if (vcResponseMsg.hasListBranchesResponse()) { - var listBranchesResponse = vcResponseMsg.getListBranchesResponse(); - ((ListBranchesGitRequest) request).getFuture().set(listBranchesResponse.getBranchesList().stream().map(this::getBranchInfo).collect(Collectors.toList())); - } else if (vcResponseMsg.hasListEntitiesResponse()) { - var listEntitiesResponse = vcResponseMsg.getListEntitiesResponse(); - ((ListEntitiesGitRequest) request).getFuture().set( - listEntitiesResponse.getEntitiesList().stream().map(this::getVersionedEntityInfo).collect(Collectors.toList())); - } else if (vcResponseMsg.hasListVersionsResponse()) { - var listVersionsResponse = vcResponseMsg.getListVersionsResponse(); - ((ListVersionsGitRequest) request).getFuture().set(toPageData(listVersionsResponse)); - } else if (vcResponseMsg.hasEntityContentResponse()) { - TransportProtos.EntityContentResponseMsg responseMsg = vcResponseMsg.getEntityContentResponse(); - log.trace("[{}] received chunk {} for 'getEntity'", responseMsg.getChunkedMsgId(), responseMsg.getChunkIndex()); - var joined = joinChunks(requestId, responseMsg, 1); - if (joined.isPresent()) { - log.trace("[{}] collected all chunks for 'getEntity'", responseMsg.getChunkedMsgId()); - ((EntityContentGitRequest) request).getFuture().set(joined.get().get(0)); - } else { - completed = false; - } - } else if (vcResponseMsg.hasEntitiesContentResponse()) { - TransportProtos.EntitiesContentResponseMsg responseMsg = vcResponseMsg.getEntitiesContentResponse(); - TransportProtos.EntityContentResponseMsg item = responseMsg.getItem(); - if (responseMsg.getItemsCount() > 0) { - var joined = joinChunks(requestId, item, responseMsg.getItemsCount()); + try { + if (vcResponseMsg.hasGenericResponse()) { + future.set(null); + } else if (vcResponseMsg.hasCommitResponse()) { + var commitResponse = vcResponseMsg.getCommitResponse(); + var commitResult = new VersionCreationResult(); + if (commitResponse.getTs() > 0) { + commitResult.setVersion(new EntityVersion(commitResponse.getTs(), commitResponse.getCommitId(), commitResponse.getName(), commitResponse.getAuthor())); + } + commitResult.setAdded(commitResponse.getAdded()); + commitResult.setRemoved(commitResponse.getRemoved()); + commitResult.setModified(commitResponse.getModified()); + commitResult.setDone(true); + ((CommitGitRequest) request).getFuture().set(commitResult); + } else if (vcResponseMsg.hasListBranchesResponse()) { + var listBranchesResponse = vcResponseMsg.getListBranchesResponse(); + ((ListBranchesGitRequest) request).getFuture().set(listBranchesResponse.getBranchesList().stream().map(this::getBranchInfo).collect(Collectors.toList())); + } else if (vcResponseMsg.hasListEntitiesResponse()) { + var listEntitiesResponse = vcResponseMsg.getListEntitiesResponse(); + ((ListEntitiesGitRequest) request).getFuture().set( + listEntitiesResponse.getEntitiesList().stream().map(this::getVersionedEntityInfo).collect(Collectors.toList())); + } else if (vcResponseMsg.hasListVersionsResponse()) { + var listVersionsResponse = vcResponseMsg.getListVersionsResponse(); + ((ListVersionsGitRequest) request).getFuture().set(toPageData(listVersionsResponse)); + } else if (vcResponseMsg.hasEntityContentResponse()) { + TransportProtos.EntityContentResponseMsg responseMsg = vcResponseMsg.getEntityContentResponse(); + log.trace("[{}] received chunk {} for 'getEntity'", responseMsg.getChunkedMsgId(), responseMsg.getChunkIndex()); + var joined = joinChunks(requestId, responseMsg, 1); if (joined.isPresent()) { - ((EntitiesContentGitRequest) request).getFuture().set(joined.get()); + log.trace("[{}] collected all chunks for 'getEntity'", responseMsg.getChunkedMsgId()); + ((EntityContentGitRequest) request).getFuture().set(joined.get().get(0)); } else { completed = false; } - } else { - ((EntitiesContentGitRequest) request).getFuture().set(Collections.emptyList()); + } else if (vcResponseMsg.hasEntitiesContentResponse()) { + TransportProtos.EntitiesContentResponseMsg responseMsg = vcResponseMsg.getEntitiesContentResponse(); + TransportProtos.EntityContentResponseMsg item = responseMsg.getItem(); + if (responseMsg.getItemsCount() > 0) { + var joined = joinChunks(requestId, item, responseMsg.getItemsCount()); + if (joined.isPresent()) { + ((EntitiesContentGitRequest) request).getFuture().set(joined.get()); + } else { + completed = false; + } + } else { + ((EntitiesContentGitRequest) request).getFuture().set(Collections.emptyList()); + } + } else if (vcResponseMsg.hasVersionsDiffResponse()) { + TransportProtos.VersionsDiffResponseMsg diffResponse = vcResponseMsg.getVersionsDiffResponse(); + List entityVersionsDiffList = diffResponse.getDiffList().stream() + .map(diff -> EntityVersionsDiff.builder() + .externalId(EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(diff.getEntityType()), + new UUID(diff.getEntityIdMSB(), diff.getEntityIdLSB()))) + .entityDataAtVersion1(StringUtils.isNotEmpty(diff.getEntityDataAtVersion1()) ? + toData(diff.getEntityDataAtVersion1()) : null) + .entityDataAtVersion2(StringUtils.isNotEmpty(diff.getEntityDataAtVersion2()) ? + toData(diff.getEntityDataAtVersion2()) : null) + .rawDiff(diff.getRawDiff()) + .build()) + .collect(Collectors.toList()); + ((VersionsDiffGitRequest) request).getFuture().set(entityVersionsDiffList); } - } else if (vcResponseMsg.hasVersionsDiffResponse()) { - TransportProtos.VersionsDiffResponseMsg diffResponse = vcResponseMsg.getVersionsDiffResponse(); - List entityVersionsDiffList = diffResponse.getDiffList().stream() - .map(diff -> EntityVersionsDiff.builder() - .externalId(EntityIdFactory.getByTypeAndUuid(EntityType.valueOf(diff.getEntityType()), - new UUID(diff.getEntityIdMSB(), diff.getEntityIdLSB()))) - .entityDataAtVersion1(StringUtils.isNotEmpty(diff.getEntityDataAtVersion1()) ? - toData(diff.getEntityDataAtVersion1()) : null) - .entityDataAtVersion2(StringUtils.isNotEmpty(diff.getEntityDataAtVersion2()) ? - toData(diff.getEntityDataAtVersion2()) : null) - .rawDiff(diff.getRawDiff()) - .build()) - .collect(Collectors.toList()); - ((VersionsDiffGitRequest) request).getFuture().set(entityVersionsDiffList); + } catch (Exception e) { + future.setException(e); + throw e; } } if (completed) { diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/EntitiesVersionControlService.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/EntitiesVersionControlService.java index 8bc2049e33..8a2410e932 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/EntitiesVersionControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/EntitiesVersionControlService.java @@ -49,15 +49,15 @@ public interface EntitiesVersionControlService { ListenableFuture> listVersions(TenantId tenantId, String branch, PageLink pageLink) throws Exception; - ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String branch, String versionId, EntityType entityType) throws Exception; + ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String versionId, EntityType entityType) throws Exception; - ListenableFuture> listAllEntitiesAtVersion(TenantId tenantId, String branch, String versionId) throws Exception; + ListenableFuture> listAllEntitiesAtVersion(TenantId tenantId, String versionId) throws Exception; UUID loadEntitiesVersion(User user, VersionLoadRequest request) throws Exception; VersionLoadResult getVersionLoadStatus(User user, UUID requestId) throws ThingsboardException; - ListenableFuture compareEntityDataToVersion(User user, String branch, EntityId entityId, String versionId) throws Exception; + ListenableFuture compareEntityDataToVersion(User user, EntityId entityId, String versionId) throws Exception; ListenableFuture> listBranches(TenantId tenantId) throws Exception; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/GitVersionControlQueueService.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/GitVersionControlQueueService.java index cc83479896..feba7db76d 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/GitVersionControlQueueService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/GitVersionControlQueueService.java @@ -52,9 +52,9 @@ public interface GitVersionControlQueueService { ListenableFuture> listVersions(TenantId tenantId, String branch, EntityId entityId, PageLink pageLink); - ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String branch, String versionId, EntityType entityType); + ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String versionId, EntityType entityType); - ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String branch, String versionId); + ListenableFuture> listEntitiesAtVersion(TenantId tenantId, String versionId); ListenableFuture> listBranches(TenantId tenantId); diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportColumnType.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportColumnType.java similarity index 97% rename from application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportColumnType.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportColumnType.java index 24b566e631..a0cd40251f 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportColumnType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportColumnType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.sync.ie.importing.csv; +package org.thingsboard.server.common.data.sync.ie.importing.csv; import lombok.Getter; import org.thingsboard.server.common.data.DataConstants; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportRequest.java similarity index 94% rename from application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportRequest.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportRequest.java index e8eac6a9ed..8d7b6f9d82 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportRequest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.sync.ie.importing.csv; +package org.thingsboard.server.common.data.sync.ie.importing.csv; import lombok.Data; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportResult.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportResult.java similarity index 94% rename from application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportResult.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportResult.java index 0626c8e690..cced74afaa 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/BulkImportResult.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/ie/importing/csv/BulkImportResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.service.sync.ie.importing.csv; +package org.thingsboard.server.common.data.sync.ie.importing.csv; import lombok.Data; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/BranchInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/BranchInfo.java index fcf1f4470e..c4dc3d8e07 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/BranchInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/BranchInfo.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.sync.vc; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.Objects; @@ -22,6 +23,8 @@ import java.util.Objects; @Data public class BranchInfo { private final String name; + + @JsonProperty("default") private final boolean isDefault; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/request/load/VersionLoadRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/request/load/VersionLoadRequest.java index d9d1329c8b..cb60d91b24 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/request/load/VersionLoadRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/request/load/VersionLoadRequest.java @@ -29,7 +29,6 @@ import static com.fasterxml.jackson.annotation.JsonSubTypes.Type; @Data public abstract class VersionLoadRequest { - private String branch; private String versionId; public abstract VersionLoadRequestType getType(); diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java index 392c686a14..7d1710a87b 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java @@ -354,7 +354,11 @@ public class GitRepository { } private ObjectId resolve(String rev) throws IOException { - return git.getRepository().resolve(rev); + ObjectId result = git.getRepository().resolve(rev); + if (result == null) { + throw new IllegalArgumentException("Failed to parse git revision string: \"" + rev + "\""); + } + return result; } private , T> T execute(C command) throws GitAPIException { diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index fe78879125..e3c43be6f7 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -51,6 +51,7 @@ import org.thingsboard.server.common.data.DeviceProfileInfo; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.EntityInfo; import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.EntityViewInfo; import org.thingsboard.server.common.data.Event; @@ -77,6 +78,7 @@ import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.device.DeviceSearchQuery; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; +import org.thingsboard.server.common.data.edge.EdgeInfo; import org.thingsboard.server.common.data.edge.EdgeSearchQuery; import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; import org.thingsboard.server.common.data.id.AlarmId; @@ -134,6 +136,19 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.common.data.sms.config.TestSmsRequest; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; +import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; +import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings; +import org.thingsboard.server.common.data.sync.vc.BranchInfo; +import org.thingsboard.server.common.data.sync.vc.EntityDataDiff; +import org.thingsboard.server.common.data.sync.vc.EntityDataInfo; +import org.thingsboard.server.common.data.sync.vc.EntityVersion; +import org.thingsboard.server.common.data.sync.vc.RepositorySettings; +import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; +import org.thingsboard.server.common.data.sync.vc.VersionLoadResult; +import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; +import org.thingsboard.server.common.data.sync.vc.request.create.VersionCreateRequest; +import org.thingsboard.server.common.data.sync.vc.request.load.VersionLoadRequest; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeInfo; @@ -147,11 +162,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.stream.Collectors; -import static org.springframework.util.StringUtils.isEmpty; +import static org.thingsboard.server.common.data.StringUtils.isEmpty; /** * @author Andrew Shvayka @@ -267,6 +283,60 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { return restTemplate.postForEntity(baseURL + "/api/admin/securitySettings", securitySettings, SecuritySettings.class).getBody(); } + public Optional getRepositorySettings() { + try { + ResponseEntity repositorySettings = restTemplate.getForEntity(baseURL + "/api/admin/repositorySettings", RepositorySettings.class); + return Optional.ofNullable(repositorySettings.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Boolean repositorySettingsExists() { + return restTemplate.getForEntity(baseURL + "/api/admin/repositorySettings/exists", Boolean.class).getBody(); + } + + public RepositorySettings saveRepositorySettings(RepositorySettings repositorySettings) { + return restTemplate.postForEntity(baseURL + "/api/admin/repositorySettings", repositorySettings, RepositorySettings.class).getBody(); + } + + public void deleteRepositorySettings() { + restTemplate.delete(baseURL + "/api/admin/repositorySettings"); + } + + public void checkRepositoryAccess(RepositorySettings repositorySettings) { + restTemplate.postForLocation(baseURL + "/api/admin/repositorySettings/checkAccess", repositorySettings); + } + + public Optional getAutoCommitSettings() { + try { + ResponseEntity autoCommitSettings = restTemplate.getForEntity(baseURL + "/api/admin/autoCommitSettings", AutoCommitSettings.class); + return Optional.ofNullable(autoCommitSettings.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Boolean autoCommitSettingsExists() { + return restTemplate.getForEntity(baseURL + "/api/admin/autoCommitSettings/exists", Boolean.class).getBody(); + } + + public AutoCommitSettings saveAutoCommitSettings(AutoCommitSettings autoCommitSettings) { + return restTemplate.postForEntity(baseURL + "/api/admin/autoCommitSettings", autoCommitSettings, AutoCommitSettings.class).getBody(); + } + + public void deleteAutoCommitSettings() { + restTemplate.delete(baseURL + "/api/admin/autoCommitSettings"); + } + public Optional checkUpdates() { try { ResponseEntity updateMsg = restTemplate.getForEntity(baseURL + "/api/admin/updates", UpdateMessage.class); @@ -550,6 +620,15 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { }).getBody(); } + public BulkImportResult processAssetsBulkImport(BulkImportRequest request) { + return restTemplate.exchange( + baseURL + "/api/asset/bulk_import", + HttpMethod.POST, + new HttpEntity<>(request), + new ParameterizedTypeReference>() { + }).getBody(); + } + @Deprecated public Optional findAsset(String name) { Map params = new HashMap(); @@ -1251,7 +1330,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { HttpEntity.EMPTY, Device.class, tenantId, deviceId).getBody(); } - public Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(OtaPackageType otaPackageType, DeviceProfileId deviceProfileId) { + public Long countByDeviceProfileAndEmptyOtaPackage(OtaPackageType otaPackageType, DeviceProfileId deviceProfileId) { Map params = new HashMap<>(); params.put("otaPackageType", otaPackageType.name()); params.put("deviceProfileId", deviceProfileId.getId().toString()); @@ -1266,6 +1345,15 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { ).getBody(); } + public BulkImportResult processDevicesBulkImport(BulkImportRequest request) { + return restTemplate.exchange( + baseURL + "/api/device/bulk_import", + HttpMethod.POST, + new HttpEntity<>(request), + new ParameterizedTypeReference>() { + }).getBody(); + } + @Deprecated public Device createDevice(String name, String type) { Device device = new Device(); @@ -2499,6 +2587,10 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } + public Boolean isEdgesSupportEnabled() { + return restTemplate.getForEntity(baseURL + "/api/edges/enabled", Boolean.class).getBody(); + } + public Edge saveEdge(Edge edge) { return restTemplate.postForEntity(baseURL + "/api/edge", edge, Edge.class).getBody(); } @@ -2520,6 +2612,19 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } + public Optional getEdgeInfoById(EdgeId edgeId) { + try { + ResponseEntity edge = restTemplate.getForEntity(baseURL + "/api/edge/info/{edgeId}", EdgeInfo.class, edgeId.getId()); + return Optional.ofNullable(edge.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + public Optional assignEdgeToCustomer(CustomerId customerId, EdgeId edgeId) { try { ResponseEntity edge = restTemplate.postForEntity(baseURL + "/api/customer/{customerId}/edge/{edgeId}", null, Edge.class, customerId.getId(), edgeId.getId()); @@ -2546,7 +2651,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } } - public Optional setRootRuleChain(EdgeId edgeId, RuleChainId ruleChainId) { + public Optional setEdgeRootRuleChain(EdgeId edgeId, RuleChainId ruleChainId) { try { ResponseEntity ruleChain = restTemplate.postForEntity(baseURL + "/api/edge/{edgeId}/{ruleChainId}/root", null, Edge.class, edgeId.getId(), ruleChainId.getId()); return Optional.ofNullable(ruleChain.getBody()); @@ -2827,6 +2932,17 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { }, params).getBody(); } + public PageData getTenantEdgeInfos(String type, PageLink pageLink) { + Map params = new HashMap<>(); + params.put("type", type); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/tenant/edgeInfos?type={type}&" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + public Optional getTenantEdge(String edgeName) { try { ResponseEntity edge = restTemplate.getForEntity(baseURL + "/api/tenant/edges?edgeName={edgeName}", Edge.class, edgeName); @@ -2852,6 +2968,18 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { }, params).getBody(); } + public PageData getCustomerEdgeInfos(CustomerId customerId, PageLink pageLink, String edgeType) { + Map params = new HashMap<>(); + params.put("customerId", customerId.getId().toString()); + params.put("type", edgeType); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/customer/{customerId}/edgeInfos?type={type}&" + getUrlParams(pageLink), + HttpMethod.GET, HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, params).getBody(); + } + public List getEdgesByIds(List edgeIds) { return restTemplate.exchange(baseURL + "/api/edges?edgeIds={edgeIds}", HttpMethod.GET, @@ -2896,6 +3024,138 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { restTemplate.postForEntity(baseURL + "/api/edge/sync/{edgeId}", null, EdgeId.class, params); } + public String findMissingToRelatedRuleChains(EdgeId edgeId) { + return restTemplate.getForEntity(baseURL + "/api/edge/missingToRelatedRuleChains/{edgeId}", String.class, edgeId.getId()).getBody(); + } + + public BulkImportResult processEdgesBulkImport(BulkImportRequest request) { + return restTemplate.exchange( + baseURL + "/api/edge/bulk_import", + HttpMethod.POST, + new HttpEntity<>(request), + new ParameterizedTypeReference>() { + }).getBody(); + } + + public UUID saveEntitiesVersion(VersionCreateRequest request) { + return restTemplate.postForEntity(baseURL + "/api/entities/vc/version", request, UUID.class).getBody(); + } + + public Optional getVersionCreateRequestStatus(UUID requestId) { + try { + ResponseEntity versionCreateResult = restTemplate.getForEntity(baseURL + "/api/entities/vc/version/{requestId}/status", VersionCreationResult.class, requestId); + return Optional.ofNullable(versionCreateResult.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + public PageData listEntityVersions(EntityId externalEntityId, String branch, PageLink pageLink) { + Map params = new HashMap<>(); + params.put("entityType", externalEntityId.getEntityType().name()); + params.put("externalEntityUuid", externalEntityId.getId().toString()); + params.put("branch", branch); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/entities/vc/version/{entityType}/{externalEntityUuid}?branch={branch}&" + getUrlParams(pageLink), + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, + params).getBody(); + } + + public PageData listEntityTypeVersions(EntityType entityType, String branch, PageLink pageLink) { + Map params = new HashMap<>(); + params.put("entityType", entityType.name()); + params.put("branch", branch); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/entities/vc/version/{entityType}?branch={branch}&" + getUrlParams(pageLink), + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, + params).getBody(); + } + + public PageData listVersions(String branch, PageLink pageLink) { + Map params = new HashMap<>(); + params.put("branch", branch); + addPageLinkToParam(params, pageLink); + return restTemplate.exchange( + baseURL + "/api/entities/vc/version?branch={branch}&" + getUrlParams(pageLink), + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, + params).getBody(); + } + + public List listEntitiesAtVersion(EntityType entityType, String versionId) { + Map params = new HashMap<>(); + params.put("entityType", entityType.name()); + params.put("versionId", versionId); + return restTemplate.exchange( + baseURL + "/api/entities/vc/entity/{entityType}/{versionId}", + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, + params).getBody(); + } + + public List listAllEntitiesAtVersion(String versionId) { + Map params = new HashMap<>(); + params.put("versionId", versionId); + return restTemplate.exchange( + baseURL + "/api/entities/vc/entity/{versionId}", + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }, + params).getBody(); + } + + public EntityDataInfo getEntityDataInfo(EntityId externalEntityId, String versionId) { + return restTemplate.getForEntity(baseURL + "/api/entities/vc/info/{versionId}/{entityType}/{externalEntityUuid}", + EntityDataInfo.class, versionId, externalEntityId.getEntityType(), externalEntityId.getId()).getBody(); + } + + public EntityDataDiff compareEntityDataToVersion(EntityId internalEntityId, String versionId) { + return restTemplate.getForEntity(baseURL + "/api/entities/vc/diff/{entityType}/{internalEntityUuid}?versionId={versionId}", + EntityDataDiff.class, internalEntityId.getEntityType(), internalEntityId.getId(), versionId).getBody(); + } + + public UUID loadEntitiesVersion(VersionLoadRequest request) { + return restTemplate.postForEntity(baseURL + "/api/entities/vc/entity", request, UUID.class).getBody(); + } + + public Optional getVersionLoadRequestStatus(UUID requestId) { + try { + ResponseEntity versionLoadResult = restTemplate.getForEntity(baseURL + "/api/entities/vc/entity/{requestId}/status", VersionLoadResult.class, requestId); + return Optional.ofNullable(versionLoadResult.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public List listBranches() { + return restTemplate.exchange( + baseURL + "/api/entities/vc/branches", + HttpMethod.GET, + HttpEntity.EMPTY, + new ParameterizedTypeReference>() { + }).getBody(); + } + public ResponseEntity downloadResource(TbResourceId resourceId) { Map params = new HashMap<>(); params.put("resourceId", resourceId.getId().toString()); diff --git a/ui-ngx/src/app/core/http/entities-version-control.service.ts b/ui-ngx/src/app/core/http/entities-version-control.service.ts index 447f252fad..b71c95b3ec 100644 --- a/ui-ngx/src/app/core/http/entities-version-control.service.ts +++ b/ui-ngx/src/app/core/http/entities-version-control.service.ts @@ -158,12 +158,10 @@ export class EntitiesVersionControlService { defaultHttpOptionsFromConfig({...config, ...{ignoreLoading: true}})); } - public compareEntityDataToVersion(branch: string, - entityId: EntityId, + public compareEntityDataToVersion(entityId: EntityId, versionId: string, config?: RequestConfig): Observable { - const encodedBranch = encodeURIComponent(branch); - return this.http.get(`/api/entities/vc/diff/${entityId.entityType}/${entityId.id}?branch=${encodedBranch}&versionId=${versionId}`, + return this.http.get(`/api/entities/vc/diff/${entityId.entityType}/${entityId.id}?versionId=${versionId}`, defaultHttpOptionsFromConfig(config)); } diff --git a/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts b/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts index 718dc5c2e7..dda0f6b39d 100644 --- a/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/complex-version-load.component.ts @@ -41,9 +41,6 @@ import { parseHttpErrorMessage } from '@core/utils'; }) export class ComplexVersionLoadComponent extends PageComponent implements OnInit, OnDestroy { - @Input() - branch: string; - @Input() versionName: string; @@ -117,7 +114,6 @@ export class ComplexVersionLoadComponent extends PageComponent implements OnInit restore(): void { const request: EntityTypeVersionLoadRequest = { - branch: this.branch, versionId: this.versionId, entityTypes: this.loadVersionFormGroup.get('entityTypes').value, type: VersionLoadRequestType.ENTITY_TYPE diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts index eb9fe8118b..8cc4a3b008 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-version-diff.component.ts @@ -59,9 +59,6 @@ export class EntityVersionDiffComponent extends PageComponent implements OnInit, @ViewChild('diffViewer', {static: true}) diffViewerElmRef: ElementRef; - @Input() - branch: string; - @Input() versionName: string; @@ -108,7 +105,7 @@ export class EntityVersionDiffComponent extends PageComponent implements OnInit, ngOnInit(): void { this.entitiesVersionControlService - .compareEntityDataToVersion(this.branch, this.entityId, this.versionId).subscribe((diffData) => { + .compareEntityDataToVersion(this.entityId, this.versionId).subscribe((diffData) => { const leftContent = entityExportDataToJsonString(diffData.currentVersion); const rightContent = entityExportDataToJsonString(diffData.otherVersion); const leftLines = leftContent.split('\n').length; @@ -310,7 +307,6 @@ export class EntityVersionDiffComponent extends PageComponent implements OnInit, const restoreVersionPopover = this.popoverService.displayPopover(trigger, this.renderer, this.viewContainerRef, EntityVersionRestoreComponent, 'leftTop', true, null, { - branch: this.branch, versionName: this.versionName, versionId: this.versionId, externalEntityId: this.externalEntityId, diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts index 43d2452ea3..44f86129d8 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts @@ -41,9 +41,6 @@ import { parseHttpErrorMessage } from '@core/utils'; }) export class EntityVersionRestoreComponent extends PageComponent implements OnInit, OnDestroy { - @Input() - branch: string; - @Input() versionName: string; @@ -108,7 +105,6 @@ export class EntityVersionRestoreComponent extends PageComponent implements OnIn restore(): void { const request: SingleEntityVersionLoadRequest = { - branch: this.branch, versionId: this.versionId, externalEntityId: this.externalEntityId, config: { diff --git a/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts b/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts index 9612a1c1b3..0c4a7ca477 100644 --- a/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/vc/entity-versions-table.component.ts @@ -260,7 +260,6 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni const diffVersionPopover = this.popoverService.displayPopover(trigger, this.renderer, this.viewContainerRef, EntityVersionDiffComponent, 'leftTop', true, null, { - branch: this.branch, versionName: entityVersion.name, versionId: entityVersion.id, entityId: this.entityId, @@ -284,7 +283,6 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni const restoreVersionPopover = this.popoverService.displayPopover(trigger, this.renderer, this.viewContainerRef, EntityVersionRestoreComponent, 'leftTop', true, null, { - branch: this.branch, versionName: entityVersion.name, versionId: entityVersion.id, externalEntityId: this.externalEntityIdValue, @@ -310,7 +308,6 @@ export class EntityVersionsTableComponent extends PageComponent implements OnIni const restoreEntitiesVersionPopover = this.popoverService.displayPopover(trigger, this.renderer, this.viewContainerRef, ComplexVersionLoadComponent, 'leftTop', true, null, { - branch: this.branch, versionName: entityVersion.name, versionId: entityVersion.id, onClose: (result: VersionLoadResult | null) => { diff --git a/ui-ngx/src/app/shared/models/vc.models.ts b/ui-ngx/src/app/shared/models/vc.models.ts index c8184a195a..432332fcee 100644 --- a/ui-ngx/src/app/shared/models/vc.models.ts +++ b/ui-ngx/src/app/shared/models/vc.models.ts @@ -113,7 +113,6 @@ export enum VersionLoadRequestType { } export interface VersionLoadRequest { - branch: string; versionId: string; type: VersionLoadRequestType; }