From 8a157397d48a2d0a96c6bd44debcee39a0874671 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 8 Dec 2022 17:04:30 +0200 Subject: [PATCH 01/43] added rest controller for alarm comments --- .../main/data/upgrade/3.5/schema_update.sql | 28 +++++ .../server/actors/ActorSystemContext.java | 5 + .../actors/ruleChain/DefaultTbContext.java | 6 + .../controller/AlarmCommentController.java | 108 ++++++++++++++++ .../server/controller/BaseController.java | 22 +++- .../controller/ControllerConstants.java | 2 + .../entitiy/AbstractTbEntityService.java | 3 + .../DefaultTbNotificationEntityService.java | 13 ++ .../entitiy/TbNotificationEntityService.java | 4 + .../alarm/DefaultTbAlarmCommentService.java | 50 ++++++++ .../entitiy/alarm/TbAlarmCommentService.java | 26 ++++ .../permission/CustomerUserPermissions.java | 14 +++ .../service/security/permission/Resource.java | 1 + .../permission/TenantAdminPermissions.java | 1 + .../src/main/resources/thingsboard.yml | 2 + .../alarm/AlarmCommentOperationResult.java | 37 ++++++ .../server/dao/alarm/AlarmCommentService.java | 35 ++++++ .../server/dao/alarm/AlarmService.java | 2 +- .../server/common/data/EntityType.java | 2 +- .../common/data/alarm/AlarmComment.java | 91 ++++++++++++++ .../common/data/alarm/AlarmCommentInfo.java | 67 ++++++++++ .../server/common/data/id/AlarmCommentId.java | 45 +++++++ .../common/data/id/EntityIdFactory.java | 2 + .../server/dao/alarm/AlarmCommentDao.java | 39 ++++++ .../dao/alarm/BaseAlarmCommentService.java | 105 ++++++++++++++++ .../server/dao/model/ModelConstants.java | 9 ++ .../dao/model/sql/AlarmCommentEntity.java | 119 ++++++++++++++++++ .../validator/AlarmCommentDataValidator.java | 44 +++++++ .../dao/sql/alarm/AlarmCommentRepository.java | 29 +++++ .../dao/sql/alarm/JpaAlarmCommentDao.java | 101 +++++++++++++++ .../rule/engine/api/TbContext.java | 3 + .../util/EntitiesFieldsAsyncLoader.java | 4 + 32 files changed, 1016 insertions(+), 3 deletions(-) create mode 100644 application/src/main/data/upgrade/3.5/schema_update.sql create mode 100644 application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java create mode 100644 application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java create mode 100644 application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java create mode 100644 common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java create mode 100644 common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java diff --git a/application/src/main/data/upgrade/3.5/schema_update.sql b/application/src/main/data/upgrade/3.5/schema_update.sql new file mode 100644 index 0000000000..506ac7e38c --- /dev/null +++ b/application/src/main/data/upgrade/3.5/schema_update.sql @@ -0,0 +1,28 @@ +-- +-- 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. +-- + +CREATE TABLE IF NOT EXISTS alarm_comment ( + id uuid NOT NULL, + tenant_id uuid NOT NULL, + customer_id uuid NOT NULL, + created_time bigint NOT NULL, + alarm_id uuid NOT NULL, + user_id uuid, + type varchar(255) NOT NULL, + comment varchar(1000000), + CONSTRAINT fk_alarm_comment_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE +) PARTITION BY RANGE (created_time); +CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id ASC); \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index e1a41fe401..82f9ec25b6 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -50,6 +50,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.tools.TbRateLimits; import org.thingsboard.server.common.stats.TbApiUsageReportClient; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.audit.AuditLogService; @@ -268,6 +269,10 @@ public class ActorSystemContext { @Getter private AlarmSubscriptionService alarmService; + @Autowired + @Getter + private AlarmCommentService alarmCommentService; + @Autowired @Getter private JsInvokeService jsInvokeService; diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index ef2de35912..826883aee2 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -71,6 +71,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgProcessingStackItem; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.cassandra.CassandraCluster; @@ -579,6 +580,11 @@ class DefaultTbContext implements TbContext { return mainCtx.getAlarmService(); } + @Override + public AlarmCommentService getAlarmCommentService() { + return mainCtx.getAlarmCommentService(); + } + @Override public RuleChainService getRuleChainService() { return mainCtx.getRuleChainService(); diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java new file mode 100644 index 0000000000..c4c1bc8de2 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -0,0 +1,108 @@ +/** + * 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. + */ +package org.thingsboard.server.controller; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService; +import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; + +import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; +import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; +import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; + +@RestController +@TbCoreComponent +@RequiredArgsConstructor +@RequestMapping("/api") +public class AlarmCommentController extends BaseController { + public static final String ALARM_ID = "alarmId"; + public static final String ALARM_COMMENT_ID = "commentId"; + + private final TbAlarmCommentService tbAlarmCommentService; + + @ApiOperation(value = "Create or update Alarm Comment ", + notes = "Creates or Updates the Alarm Comment. " + + "When creating comment, platform generates Alarm Comment Id as " + UUID_WIKI_LINK + + "The newly created Alarm Comment id will be present in the response. Specify existing Alarm Comment id to update the alarm. " + + "Referencing non-existing Alarm Comment Id will cause 'Not Found' error. " + + "\nRemove 'id' and optionally 'userId' from the request body example (below) to create new Alarm comment entity. " + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH + , produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.POST) + @ResponseBody + public AlarmComment saveAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) + @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = "A JSON value representing the comment.") @RequestBody AlarmComment alarmComment) throws ThingsboardException { + checkParameter(ALARM_ID, strAlarmId); + alarmComment.setTenantId(getTenantId()); + alarmComment.setAlarmId(new AlarmId(toUUID(strAlarmId))); + checkEntity(alarmComment.getId(), alarmComment, Resource.ALARM_COMMENT); + return tbAlarmCommentService.saveAlarmComment(alarmComment, getCurrentUser()); + } + + @ApiOperation(value = "Delete Alarm comment(deleteAlarmComment)", + notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/alarm/{alarmId}/comment/{commentId}", method = RequestMethod.DELETE) + @ResponseBody + public Boolean deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { + checkParameter(ALARM_ID, strAlarmId); + AlarmCommentId alarmCommentId = new AlarmCommentId(toUUID(strAlarmId)); + AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId, Operation.DELETE); + return tbAlarmCommentService.deleteAlarmComment(alarmComment, getCurrentUser()); + } + + @ApiOperation(value = "Get Alarm comments (getAlarmComments)", + notes = "Returns a page of alarm comments. " + + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.GET) + @ResponseBody + public PageData getAlarmComments( + @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) + @PathVariable(ALARM_ID) String strAlarmCommentId, + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @RequestParam int pageSize, + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @RequestParam int page + ) throws Exception { + AlarmId alarmId = new AlarmId(toUUID(strAlarmCommentId)); + PageLink pageLink = createPageLink(pageSize, page, null, null, null); + return checkNotNull(alarmCommentService.findAlarmComments(alarmId, pageLink).get()); + } +} diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index ffc3fcf3cd..965842af46 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -54,6 +54,7 @@ import org.thingsboard.server.common.data.TenantInfo; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetInfo; @@ -64,6 +65,7 @@ import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.edge.EdgeInfo; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetProfileId; @@ -98,6 +100,7 @@ import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetsBundle; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.asset.AssetProfileService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; @@ -131,7 +134,6 @@ import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.component.ComponentDiscoveryService; -import org.thingsboard.server.service.edge.EdgeNotificationService; import org.thingsboard.server.service.edge.rpc.EdgeRpcService; import org.thingsboard.server.service.entitiy.TbNotificationEntityService; import org.thingsboard.server.service.ota.OtaPackageStateService; @@ -200,6 +202,9 @@ public abstract class BaseController { @Autowired protected AlarmSubscriptionService alarmService; + @Autowired + protected AlarmCommentService alarmCommentService; + @Autowired protected DeviceCredentialsService deviceCredentialsService; @@ -531,6 +536,9 @@ public abstract class BaseController { case ALARM: checkAlarmId(new AlarmId(entityId.getId()), operation); return; + case ALARM_COMMENT: + checkAlarmCommentId(new AlarmCommentId(entityId.getId()), operation); + return; case DEVICE: checkDeviceId(new DeviceId(entityId.getId()), operation); return; @@ -713,6 +721,18 @@ public abstract class BaseController { } } + AlarmComment checkAlarmCommentId(AlarmCommentId alarmCommentId, Operation operation) throws ThingsboardException { + try { + validateId(alarmCommentId, "Incorrect alarmCommentId " + alarmCommentId); + AlarmComment alarmComment = alarmCommentService.findAlarmCommentByIdAsync(getCurrentUser().getTenantId(), alarmCommentId).get(); + checkNotNull(alarmComment, "Alarm comment with id [" + alarmCommentId + "] is not found"); + accessControlService.checkPermission(getCurrentUser(), Resource.ALARM_COMMENT, operation, alarmCommentId, alarmComment); + return alarmComment; + } catch (Exception e) { + throw handleException(e, false); + } + } + WidgetsBundle checkWidgetsBundleId(WidgetsBundleId widgetsBundleId, Operation operation) throws ThingsboardException { try { validateId(widgetsBundleId, "Incorrect widgetsBundleId " + widgetsBundleId); diff --git a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java index e00ccaa4bc..5e7622ece5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java +++ b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java @@ -44,6 +44,8 @@ public class ControllerConstants { protected static final String USER_ID_PARAM_DESCRIPTION = "A string value representing the user id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; protected static final String ASSET_ID_PARAM_DESCRIPTION = "A string value representing the asset id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; protected static final String ALARM_ID_PARAM_DESCRIPTION = "A string value representing the alarm id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; + + protected static final String ALARM_COMMENT_ID_PARAM_DESCRIPTION = "A string value representing the alarm comment id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; protected static final String ENTITY_ID_PARAM_DESCRIPTION = "A string value representing the entity id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; protected static final String OTA_PACKAGE_ID_PARAM_DESCRIPTION = "A string value representing the ota package id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; protected static final String ENTITY_TYPE_PARAM_DESCRIPTION = "A string value representing the entity type. For example, 'DEVICE'"; diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java index 9f34c061fe..10af591647 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java @@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.edge.EdgeService; @@ -65,6 +66,8 @@ public abstract class AbstractTbEntityService { @Autowired protected AlarmSubscriptionService alarmSubscriptionService; @Autowired + protected AlarmCommentService alarmCommentService; + @Autowired protected CustomerService customerService; @Autowired protected TbClusterService tbClusterService; diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java index 8f8531a5b4..0bcd605928 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEventActionType; @@ -229,6 +230,18 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS sendEntityNotificationMsg(alarm.getTenantId(), alarm.getId(), edgeTypeByActionType(actionType)); } + @Override + public void notifyCreateOrUpdateAlarmComment(AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo) { + logEntityAction(alarmComment.getTenantId(), alarmComment.getAlarmId(), alarmComment, alarmComment.getCustomerId(), actionType, user, additionalInfo); + // TODO: should we send notification to edge? + } + + @Override + public void notifyDeleteAlarmComment(AlarmComment alarmComment, User user, Object... additionalInfo) { + logEntityAction(alarmComment.getTenantId(), alarmComment.getAlarmId(), alarmComment, alarmComment.getCustomerId(), ActionType.DELETED, user, additionalInfo); + // TODO: should we send notification to edge? + } + @Override public void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, I entityId, E entity, User user, diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java index dc6e148cab..6719394d5b 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java @@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEventActionType; @@ -102,6 +103,9 @@ public interface TbNotificationEntityService { void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, User user, Object... additionalInfo); + void notifyCreateOrUpdateAlarmComment(AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo); + + void notifyDeleteAlarmComment(AlarmComment alarmComment, User user, Object... additionalInfo); void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, I entityId, E entity, User user, ActionType actionType, boolean sendNotifyMsgToEdge, diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java new file mode 100644 index 0000000000..e0bfaf10e4 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java @@ -0,0 +1,50 @@ +/** + * 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. + */ +package org.thingsboard.server.service.entitiy.alarm; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.service.entitiy.AbstractTbEntityService; + +@Service +@AllArgsConstructor +public class DefaultTbAlarmCommentService extends AbstractTbEntityService implements TbAlarmCommentService{ + @Override + public AlarmComment saveAlarmComment(AlarmComment alarmComment, User user) throws ThingsboardException { + ActionType actionType = alarmComment.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + UserId userId = user.getId(); + alarmComment.setUserId(userId); + try { + AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarmComment).getAlarmComment()); + notificationEntityService.notifyCreateOrUpdateAlarmComment(savedAlarmComment, actionType, user); + return savedAlarmComment; + } catch (Exception e) { + notificationEntityService.logEntityAction(alarmComment.getTenantId(), emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e); + throw e; + } + } + @Override + public Boolean deleteAlarmComment(AlarmComment alarmComment, User user) { + notificationEntityService.notifyDeleteAlarmComment(alarmComment, user); + return alarmCommentService.deleteAlarmComment(alarmComment.getId()).isSuccessful(); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java new file mode 100644 index 0000000000..375b655af8 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java @@ -0,0 +1,26 @@ +/** + * 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. + */ +package org.thingsboard.server.service.entitiy.alarm; + +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.exception.ThingsboardException; + +public interface TbAlarmCommentService { + AlarmComment saveAlarmComment(AlarmComment alarmComment, User user) throws ThingsboardException; + + Boolean deleteAlarmComment(AlarmComment alarmComment, User user); +} diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java index cdd84b0478..489d9deb81 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java @@ -32,6 +32,7 @@ public class CustomerUserPermissions extends AbstractPermissions { public CustomerUserPermissions() { super(); put(Resource.ALARM, customerAlarmPermissionChecker); + put(Resource.ALARM_COMMENT, customerAlarmCommentPermissionChecker); put(Resource.ASSET, customerEntityPermissionChecker); put(Resource.DEVICE, customerEntityPermissionChecker); put(Resource.CUSTOMER, customerPermissionChecker); @@ -59,6 +60,19 @@ public class CustomerUserPermissions extends AbstractPermissions { } }; + private static final PermissionChecker customerAlarmCommentPermissionChecker = new PermissionChecker() { + @Override + public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { + if (!user.getTenantId().equals(entity.getTenantId())) { + return false; + } + if (!(entity instanceof HasCustomerId)) { + return false; + } + return user.getCustomerId().equals(((HasCustomerId) entity).getCustomerId()); + } + }; + private static final PermissionChecker customerEntityPermissionChecker = new PermissionChecker.GenericPermissionChecker(Operation.READ, Operation.READ_CREDENTIALS, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY, Operation.RPC_CALL, Operation.CLAIM_DEVICES, diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java index a9484a2bd3..0979c0969d 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java @@ -22,6 +22,7 @@ import java.util.Optional; public enum Resource { ADMIN_SETTINGS(), ALARM(EntityType.ALARM), + ALARM_COMMENT(EntityType.ALARM_COMMENT), DEVICE(EntityType.DEVICE), ASSET(EntityType.ASSET), CUSTOMER(EntityType.CUSTOMER), diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java index ef7991e5de..7027fda414 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java @@ -30,6 +30,7 @@ public class TenantAdminPermissions extends AbstractPermissions { super(); put(Resource.ADMIN_SETTINGS, PermissionChecker.allowAllPermissionChecker); put(Resource.ALARM, tenantEntityPermissionChecker); + put(Resource.ALARM_COMMENT, tenantEntityPermissionChecker); put(Resource.ASSET, tenantEntityPermissionChecker); put(Resource.DEVICE, tenantEntityPermissionChecker); put(Resource.CUSTOMER, tenantEntityPermissionChecker); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 6a00775a38..67f9928c18 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -277,6 +277,8 @@ sql: partition_size: "${SQL_EDGE_EVENTS_PARTITION_SIZE_HOURS:168}" # Number of hours to partition the events. The current value corresponds to one week. audit_logs: partition_size: "${SQL_AUDIT_LOGS_PARTITION_SIZE_HOURS:168}" # Default value - 1 week + alarm_comments: + partition_size: "${SQL_ALARM_COMMENTS_PARTITION_SIZE_HOURS:168}" # Default value - 1 week # Specify whether to sort entities before batch update. Should be enabled for cluster mode to avoid deadlocks batch_sort: "${SQL_BATCH_SORT:true}" # Specify whether to remove null characters from strValue of attributes and timeseries before insert diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java new file mode 100644 index 0000000000..3687a03eca --- /dev/null +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java @@ -0,0 +1,37 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.alarm; + +import lombok.Data; +import org.thingsboard.server.common.data.alarm.AlarmComment; + +@Data +public class AlarmCommentOperationResult { + private final AlarmComment alarmComment; + private final boolean successful; + private final boolean created; + + + public AlarmCommentOperationResult(AlarmComment alarmComment, boolean successful) { + this(alarmComment, successful, false); + } + + public AlarmCommentOperationResult(AlarmComment alarmComment, boolean successful, boolean created) { + this.alarmComment = alarmComment; + this.successful = successful; + this.created = created; + } +} diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java new file mode 100644 index 0000000000..83e6216800 --- /dev/null +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -0,0 +1,35 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.alarm; + +import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; + +public interface AlarmCommentService { + AlarmCommentOperationResult createOrUpdateAlarmComment(AlarmComment alarmComment); + + AlarmCommentOperationResult deleteAlarmComment(AlarmCommentId alarmCommentId); + + ListenableFuture> findAlarmComments(AlarmId alarmId, PageLink pageLink); + + ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId); + +} diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java index b8041aa3fc..b5bbdc761c 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java @@ -18,12 +18,12 @@ package org.thingsboard.server.dao.alarm; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index 0798647903..44b175c20d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -19,5 +19,5 @@ package org.thingsboard.server.common.data; * @author Andrew Shvayka */ public enum EntityType { - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE; + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, ALARM_COMMENT, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java new file mode 100644 index 0000000000..ce2d11d12f --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -0,0 +1,91 @@ +/** + * 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. + */ +package org.thingsboard.server.common.data.alarm; + +import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import org.thingsboard.server.common.data.BaseData; +import org.thingsboard.server.common.data.HasCustomerId; +import org.thingsboard.server.common.data.HasName; +import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; + +@ApiModel +@Data +@Builder +@AllArgsConstructor +public class AlarmComment extends BaseData implements HasName, HasTenantId, HasCustomerId { + @ApiModelProperty(position = 3, value = "JSON object with Tenant Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private TenantId tenantId; + + @ApiModelProperty(position = 4, value = "JSON object with Customer Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private CustomerId customerId; + @ApiModelProperty(position = 2, value = "JSON object with Alarm id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private EntityId alarmId; + @ApiModelProperty(position = 3, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private UserId userId; + @ApiModelProperty(position = 4, value = "Defines origination of comment", example = "System/Other", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private String type; + @ApiModelProperty(position = 5, value = "JSON object with text of comment.", dataType = "com.fasterxml.jackson.databind.JsonNode") + private transient JsonNode comment; + + @ApiModelProperty(position = 1, value = "JSON object with the alarm comment Id. " + + "Specify this field to update the alarm comment. " + + "Referencing non-existing alarm Id will cause error. " + + "Omit this field to create new alarm." ) + @Override + public AlarmCommentId getId() { + return super.getId(); + } + + @ApiModelProperty(position = 2, value = "Timestamp of the alarm comment creation, in milliseconds", example = "1634058704567", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Override + public long getCreatedTime() { + return super.getCreatedTime(); + } + + public AlarmComment() { + super(); + } + + public AlarmComment(AlarmCommentId id) { + super(id); + } + + @Override + public String getName() { + return comment.toString(); + } + + public AlarmComment(AlarmComment alarmComment) { + super(alarmComment.getId()); + this.createdTime = alarmComment.getCreatedTime(); + this.tenantId = alarmComment.getTenantId(); + this.customerId = alarmComment.getCustomerId(); + this.type = alarmComment.getType(); + this.comment = alarmComment.getComment(); + this.userId = alarmComment.getUserId(); + + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java new file mode 100644 index 0000000000..7cbff38d80 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java @@ -0,0 +1,67 @@ +/** + * 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. + */ +package org.thingsboard.server.common.data.alarm; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel +public class AlarmCommentInfo extends AlarmComment{ + private static final long serialVersionUID = 2807343093519543377L; + + @ApiModelProperty(position = 19, value = "Alarm originator name", example = "Thermostat") + private String userName; + + public AlarmCommentInfo() { + super(); + } + + public AlarmCommentInfo(AlarmComment alarmComment) { + super(alarmComment); + } + + public AlarmCommentInfo(AlarmComment alarmComment, String userName) { + super(alarmComment); + this.userName = userName; + } + + public String getUserName() { + return userName; + } + + public void setOriginatorName(String originatorName) { + this.userName = originatorName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + AlarmCommentInfo alarmCommentInfo = (AlarmCommentInfo) o; + + return userName != null ? userName.equals(alarmCommentInfo.userName) : alarmCommentInfo.userName == null; + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (userName != null ? userName.hashCode() : 0); + return result; + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java new file mode 100644 index 0000000000..b13b5837a0 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java @@ -0,0 +1,45 @@ +/** + * 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. + */ +package org.thingsboard.server.common.data.id; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.thingsboard.server.common.data.EntityType; + +import java.util.UUID; + +@ApiModel +public class AlarmCommentId extends UUIDBased implements EntityId{ + + private static final long serialVersionUID = 2L; + + @JsonCreator + public AlarmCommentId(@JsonProperty("id") UUID id) { + super(id); + } + + public static AlarmCommentId fromString(String commentId) { + return new AlarmCommentId(UUID.fromString(commentId)); + } + + @ApiModelProperty(position = 2, required = true, value = "string", example = "ALARM_COMMENT", allowableValues = "ALARM_COMMENT") + @Override + public EntityType getEntityType() { + return EntityType.ALARM_COMMENT; + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java index c6a19e0040..ae647825cd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java @@ -53,6 +53,8 @@ public class EntityIdFactory { return new AssetId(uuid); case ALARM: return new AlarmId(uuid); + case ALARM_COMMENT: + return new AlarmCommentId(uuid); case RULE_CHAIN: return new RuleChainId(uuid); case RULE_NODE: diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java new file mode 100644 index 0000000000..e58ca14664 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java @@ -0,0 +1,39 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.alarm; + +import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.dao.Dao; + +import java.util.UUID; + +public interface AlarmCommentDao extends Dao { + AlarmComment createAlarmComment(AlarmComment alarmComment); + void deleteAlarmComment(AlarmCommentId alarmCommentId); + + AlarmComment findAlarmCommentById(TenantId tenantId, UUID key); + + PageData findAlarmComments(AlarmId id, PageLink pageLink); + + ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, UUID key); + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java new file mode 100644 index 0000000000..d293531dd4 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -0,0 +1,105 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.alarm; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.dao.entity.AbstractEntityService; +import org.thingsboard.server.dao.entity.EntityService; +import org.thingsboard.server.dao.service.DataValidator; + +import static org.thingsboard.server.dao.service.Validator.validateId; + +@Service +@Slf4j +public class BaseAlarmCommentService extends AbstractEntityService implements AlarmCommentService{ + + @Autowired + private AlarmCommentDao alarmCommentDao; + @Autowired + private EntityService entityService; + @Autowired + private DataValidator alarmCommentDataValidator; + @Override + public AlarmCommentOperationResult createOrUpdateAlarmComment(AlarmComment alarmComment) { + alarmCommentDataValidator.validate(alarmComment, AlarmComment::getTenantId); + alarmComment.setCustomerId(entityService.fetchEntityCustomerId(alarmComment.getTenantId(), alarmComment.getAlarmId())); + if (alarmComment.getId() == null) { + return createAlarmComment(alarmComment); + } else { + return updateAlarmComment(alarmComment); + } + } + + @Override + @Transactional + public AlarmCommentOperationResult deleteAlarmComment(AlarmCommentId alarmCommentId) { + log.debug("Deleting Alarm Comment with id: {}", alarmCommentId); + AlarmCommentOperationResult result = new AlarmCommentOperationResult(new AlarmComment(), true); + alarmCommentDao.deleteAlarmComment(alarmCommentId); + return result; + } + + @Override + public ListenableFuture> findAlarmComments(AlarmId alarmId, PageLink pageLink) { + PageData alarmComments = alarmCommentDao.findAlarmComments(alarmId, pageLink); + return Futures.immediateFuture(alarmComments); + } + + @Override + public ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId) { + log.trace("Executing findAlarmCommentByIdAsync [{}]", alarmCommentId); + validateId(alarmCommentId, "Incorrect alarmId " + alarmCommentId); + return alarmCommentDao.findAlarmCommentByIdAsync(tenantId, alarmCommentId.getId()); + } + + private AlarmCommentOperationResult createAlarmComment(AlarmComment alarmComment) { + log.debug("New Alarm comment : {}", alarmComment); + if (alarmComment.getType() == null) { + alarmComment.setType("OTHER"); + } + AlarmComment saved = alarmCommentDao.createAlarmComment(alarmComment); + return new AlarmCommentOperationResult(saved, true, true); + } + + private AlarmCommentOperationResult updateAlarmComment(AlarmComment newAlarmComment) { + log.debug("Update Alarm comment : {}", newAlarmComment); + + validateId(newAlarmComment.getId(), "Alarm comment id should be specified!"); + AlarmComment existing = alarmCommentDao.findAlarmCommentById(newAlarmComment.getTenantId(), newAlarmComment.getId().getId()); + if (existing != null) { + AlarmComment result = alarmCommentDao.save(newAlarmComment.getTenantId(), merge(existing, newAlarmComment)); + return new AlarmCommentOperationResult(result, true, true); + } + return null; + } + + private AlarmComment merge(AlarmComment existing, AlarmComment alarmComment) { + existing.setCustomerId(alarmComment.getCustomerId()); + existing.setComment(alarmComment.getComment()); + return existing; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index e24bde91fb..bd462eb6b6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -297,6 +297,15 @@ public class ModelConstants { public static final String ALARM_BY_ID_VIEW_NAME = "alarm_by_id"; + public static final String ALARM_COMMENT_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; + public static final String ALARM_COMMENT_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; + public static final String ALARM_COMMENT_COLUMN_FAMILY_NAME = "alarm_comment"; + public static final String ALARM_COMMENT_ALARM_ID = "alarm_id"; + public static final String ALARM_COMMENT_USER_ID = USER_ID_PROPERTY; + public static final String ALARM_COMMENT_TYPE = "type"; + public static final String ALARM_COMMENT_COMMENT = "comment"; + + /** * Cassandra entity relation constants. */ diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java new file mode 100644 index 0000000000..571c3007e1 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java @@ -0,0 +1,119 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.model.sql; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.dao.model.BaseEntity; +import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.util.mapping.JsonStringType; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.UUID; + +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_ALARM_ID; +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COMMENT; +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_CUSTOMER_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TENANT_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TYPE; + +@Data +@EqualsAndHashCode(callSuper = true) +@Entity +@TypeDef(name = "json", typeClass = JsonStringType.class) +@Table(name = ALARM_COMMENT_COLUMN_FAMILY_NAME) + +public class AlarmCommentEntity extends BaseSqlEntity implements BaseEntity { + + @Column(name = ALARM_COMMENT_TENANT_ID_PROPERTY, columnDefinition = "uuid") + private UUID tenantId; + + @Column(name = ALARM_COMMENT_CUSTOMER_ID_PROPERTY, columnDefinition = "uuid") + private UUID customerId; + @Column(name = ALARM_COMMENT_ALARM_ID, columnDefinition = "uuid") + private UUID alarmId; + + @Column(name = ModelConstants.ALARM_COMMENT_USER_ID) + private UUID userId; + + @Column(name = ALARM_COMMENT_TYPE) + private String type; + + @Type(type = "json") + @Column(name = ALARM_COMMENT_COMMENT) + private JsonNode comment; + + public AlarmCommentEntity() { + super(); + } + + public AlarmCommentEntity(AlarmComment alarmComment) { + if (alarmComment.getId() != null) { + this.setUuid(alarmComment.getUuidId()); + } + if (alarmComment.getTenantId() != null) { + this.tenantId = alarmComment.getTenantId().getId(); + } + if (alarmComment.getCustomerId() != null) { + this.customerId = alarmComment.getCustomerId().getId(); + } + this.setCreatedTime(alarmComment.getCreatedTime()); + this.setCreatedTime(alarmComment.getCreatedTime()); + if (alarmComment.getAlarmId() != null) { + this.alarmId = alarmComment.getAlarmId().getId(); + } + if (alarmComment.getUserId() != null) { + this.userId = alarmComment.getUserId().getId(); + } + if (alarmComment.getType() != null) { + this.type = alarmComment.getType(); + } + this.setComment(alarmComment.getComment()); + } + + @Override + public AlarmComment toData() { + AlarmComment alarmComment = new AlarmComment(new AlarmCommentId(id)); + alarmComment.setCreatedTime(createdTime); + alarmComment.setAlarmId(new AlarmId(alarmId)); + if (userId != null) { + alarmComment.setUserId(new UserId(userId)); + } + if (tenantId != null) { + alarmComment.setTenantId(TenantId.fromUUID(tenantId)); + } + if (customerId != null) { + alarmComment.setCustomerId(new CustomerId(customerId)); + } + alarmComment.setType(type); + alarmComment.setComment(comment); + return alarmComment; + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java new file mode 100644 index 0000000000..9969de6fe2 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java @@ -0,0 +1,44 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.service.validator; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.exception.DataValidationException; +import org.thingsboard.server.dao.service.DataValidator; +import org.thingsboard.server.dao.tenant.TenantService; + +@Component +@AllArgsConstructor +public class AlarmCommentDataValidator extends DataValidator { + + private final TenantService tenantService; + + @Override + protected void validateDataImpl(TenantId tenantId, AlarmComment alarmComment) { + if (alarmComment.getTenantId() == null) { + throw new DataValidationException("Alarm comment should be assigned to tenant!"); + } else { + if (!tenantService.tenantExists(alarmComment.getTenantId())) { + throw new DataValidationException("Alarm comment is referencing to non-existent tenant!"); + } + } + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java new file mode 100644 index 0000000000..1517b35554 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java @@ -0,0 +1,29 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.sql.alarm; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.thingsboard.server.dao.model.sql.AlarmCommentEntity; + +import java.util.UUID; + +public interface AlarmCommentRepository extends JpaRepository { + + Page findAllByAlarmId(UUID alarmId, Pageable pageable); + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java new file mode 100644 index 0000000000..440510f37b --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java @@ -0,0 +1,101 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.sql.alarm; + +import com.datastax.oss.driver.api.core.uuid.Uuids; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.alarm.AlarmCommentDao; +import org.thingsboard.server.dao.model.sql.AlarmCommentEntity; +import org.thingsboard.server.dao.sql.JpaAbstractDao; +import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; +import org.thingsboard.server.dao.util.SqlDao; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COLUMN_FAMILY_NAME; + +@Slf4j +@Component +@SqlDao +@RequiredArgsConstructor +public class JpaAlarmCommentDao extends JpaAbstractDao implements AlarmCommentDao { + private final SqlPartitioningRepository partitioningRepository; + @Value("${sql.alarm_comments.partition_size:168}") + private int partitionSizeInHours; + + @Autowired + private AlarmCommentRepository alarmCommentRepository; + + @Override + public AlarmComment createAlarmComment(AlarmComment alarmComment){ + log.debug("Saving entity {}", alarmComment); + if (alarmComment.getId() == null) { + UUID uuid = Uuids.timeBased(); + alarmComment.setId(new AlarmCommentId(uuid)); + alarmComment.setCreatedTime(Uuids.unixTimestamp(uuid)); + } + partitioningRepository.createPartitionIfNotExists(ALARM_COMMENT_COLUMN_FAMILY_NAME, alarmComment.getCreatedTime(), TimeUnit.HOURS.toMillis(partitionSizeInHours)); + AlarmCommentEntity saved = alarmCommentRepository.save(new AlarmCommentEntity(alarmComment)); + return DaoUtil.getData(saved); + } + + @Override + public void deleteAlarmComment(AlarmCommentId alarmCommentId){ + log.trace("Try to delete entity alarm comment by id using [{}]", alarmCommentId); + alarmCommentRepository.deleteById(alarmCommentId.getId()); + } + + @Override + public PageData findAlarmComments(AlarmId id, PageLink pageLink){ + log.trace("Try to find alarm comments by alard id using [{}]", id); + return DaoUtil.toPageData( + alarmCommentRepository.findAllByAlarmId(id.getId(), DaoUtil.toPageable(pageLink))); + } + + @Override + public AlarmComment findAlarmCommentById(TenantId tenantId, UUID key) { + return findById(tenantId, key); + } + + @Override + public ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, UUID key) { + return findByIdAsync(tenantId, key); + } + + @Override + protected Class getEntityClass() { + return AlarmCommentEntity.class; + } + + @Override + protected JpaRepository getRepository() { + return alarmCommentRepository; + } +} diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index 9851eead80..3f18d165de 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.rule.RuleNodeState; import org.thingsboard.server.common.data.script.ScriptLanguage; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.cassandra.CassandraCluster; @@ -231,6 +232,8 @@ public interface TbContext { RuleEngineAlarmService getAlarmService(); + AlarmCommentService getAlarmCommentService(); + RuleChainService getRuleChainService(); RuleEngineRpcService getRpcService(); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java index 245b671cf5..558e197064 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java @@ -22,6 +22,7 @@ import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.EntityFieldsData; +import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; @@ -56,6 +57,9 @@ public class EntitiesFieldsAsyncLoader { case ALARM: return getAsync(ctx.getAlarmService().findAlarmByIdAsync(ctx.getTenantId(), (AlarmId) original), EntityFieldsData::new); + case ALARM_COMMENT: + return getAsync(ctx.getAlarmCommentService().findAlarmCommentByIdAsync(ctx.getTenantId(), (AlarmCommentId) original), + EntityFieldsData::new); case RULE_CHAIN: return getAsync(ctx.getRuleChainService().findRuleChainByIdAsync(ctx.getTenantId(), (RuleChainId) original), EntityFieldsData::new); From 201078714c680fefd7c98383876a7ea81c0e4d35 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 14 Dec 2022 12:20:23 +0200 Subject: [PATCH 02/43] added alarm comment info object, refactoring --- .../main/data/upgrade/3.5/schema_update.sql | 2 - .../controller/AlarmCommentController.java | 43 +++++--- .../server/controller/BaseController.java | 6 +- .../DefaultTbNotificationEntityService.java | 8 +- .../entitiy/TbNotificationEntityService.java | 4 +- .../alarm/DefaultTbAlarmCommentService.java | 15 +-- .../entitiy/alarm/TbAlarmCommentService.java | 5 +- .../permission/CustomerUserPermissions.java | 15 +-- .../server/dao/alarm/AlarmCommentService.java | 7 +- .../common/data/alarm/AlarmComment.java | 15 +-- .../common/data/alarm/AlarmCommentInfo.java | 45 +++++++-- .../server/dao/alarm/AlarmCommentDao.java | 7 +- .../dao/alarm/BaseAlarmCommentService.java | 76 ++++++++++----- .../model/sql/AbstractAlarmCommentEntity.java | 97 +++++++++++++++++++ .../dao/model/sql/AlarmCommentEntity.java | 80 ++------------- .../dao/model/sql/AlarmCommentInfoEntity.java | 41 ++++++++ .../server/dao/service/DataValidator.java | 23 +++++ .../validator/AlarmCommentDataValidator.java | 16 +-- .../dao/sql/alarm/AlarmCommentRepository.java | 13 ++- .../dao/sql/alarm/JpaAlarmCommentDao.java | 17 ++-- .../resources/sql/schema-entities-idx.sql | 2 + .../main/resources/sql/schema-entities.sql | 10 ++ 22 files changed, 350 insertions(+), 197 deletions(-) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java diff --git a/application/src/main/data/upgrade/3.5/schema_update.sql b/application/src/main/data/upgrade/3.5/schema_update.sql index 506ac7e38c..e357089e97 100644 --- a/application/src/main/data/upgrade/3.5/schema_update.sql +++ b/application/src/main/data/upgrade/3.5/schema_update.sql @@ -16,8 +16,6 @@ CREATE TABLE IF NOT EXISTS alarm_comment ( id uuid NOT NULL, - tenant_id uuid NOT NULL, - customer_id uuid NOT NULL, created_time bigint NOT NULL, alarm_id uuid NOT NULL, user_id uuid, diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index c4c1bc8de2..256dad8f3d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -27,7 +27,9 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; @@ -36,12 +38,15 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService; import org.thingsboard.server.service.security.permission.Operation; -import org.thingsboard.server.service.security.permission.Resource; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.ALARM_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; +import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; @@ -69,10 +74,10 @@ public class AlarmCommentController extends BaseController { public AlarmComment saveAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = "A JSON value representing the comment.") @RequestBody AlarmComment alarmComment) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); - alarmComment.setTenantId(getTenantId()); - alarmComment.setAlarmId(new AlarmId(toUUID(strAlarmId))); - checkEntity(alarmComment.getId(), alarmComment, Resource.ALARM_COMMENT); - return tbAlarmCommentService.saveAlarmComment(alarmComment, getCurrentUser()); + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); + alarmComment.setAlarmId(alarmId); + return tbAlarmCommentService.saveAlarmComment(alarm.getTenantId(), alarmComment, getCurrentUser()); } @ApiOperation(value = "Delete Alarm comment(deleteAlarmComment)", @@ -82,9 +87,12 @@ public class AlarmCommentController extends BaseController { @ResponseBody public Boolean deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); - AlarmCommentId alarmCommentId = new AlarmCommentId(toUUID(strAlarmId)); - AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId, Operation.DELETE); - return tbAlarmCommentService.deleteAlarmComment(alarmComment, getCurrentUser()); + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); + + AlarmCommentId alarmCommentId = new AlarmCommentId(toUUID(strCommentId)); + AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId); + return tbAlarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment, getCurrentUser()); } @ApiOperation(value = "Get Alarm comments (getAlarmComments)", @@ -93,16 +101,23 @@ public class AlarmCommentController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.GET) @ResponseBody - public PageData getAlarmComments( + public PageData getAlarmComments( @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) - @PathVariable(ALARM_ID) String strAlarmCommentId, + @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) - @RequestParam int page + @RequestParam int page, + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_SORT_PROPERTY_ALLOWABLE_VALUES) + @RequestParam(required = false) String sortProperty, + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @RequestParam(required = false) String sortOrder ) throws Exception { - AlarmId alarmId = new AlarmId(toUUID(strAlarmCommentId)); - PageLink pageLink = createPageLink(pageSize, page, null, null, null); - return checkNotNull(alarmCommentService.findAlarmComments(alarmId, pageLink).get()); + checkParameter(ALARM_ID, strAlarmId); + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); + + PageLink pageLink = createPageLink(pageSize, page, null, sortProperty, sortOrder); + return checkNotNull(alarmCommentService.findAlarmComments(alarm.getTenantId(), alarmId, pageLink).get()); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 965842af46..91de0bf8bd 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -536,9 +536,6 @@ public abstract class BaseController { case ALARM: checkAlarmId(new AlarmId(entityId.getId()), operation); return; - case ALARM_COMMENT: - checkAlarmCommentId(new AlarmCommentId(entityId.getId()), operation); - return; case DEVICE: checkDeviceId(new DeviceId(entityId.getId()), operation); return; @@ -721,12 +718,11 @@ public abstract class BaseController { } } - AlarmComment checkAlarmCommentId(AlarmCommentId alarmCommentId, Operation operation) throws ThingsboardException { + AlarmComment checkAlarmCommentId(AlarmCommentId alarmCommentId) throws ThingsboardException { try { validateId(alarmCommentId, "Incorrect alarmCommentId " + alarmCommentId); AlarmComment alarmComment = alarmCommentService.findAlarmCommentByIdAsync(getCurrentUser().getTenantId(), alarmCommentId).get(); checkNotNull(alarmComment, "Alarm comment with id [" + alarmCommentId + "] is not found"); - accessControlService.checkPermission(getCurrentUser(), Resource.ALARM_COMMENT, operation, alarmCommentId, alarmComment); return alarmComment; } catch (Exception e) { throw handleException(e, false); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java index 0bcd605928..7ac30abf78 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java @@ -231,14 +231,14 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS } @Override - public void notifyCreateOrUpdateAlarmComment(AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo) { - logEntityAction(alarmComment.getTenantId(), alarmComment.getAlarmId(), alarmComment, alarmComment.getCustomerId(), actionType, user, additionalInfo); + public void notifyCreateOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo) { + logEntityAction(tenantId, alarmComment.getAlarmId(), alarmComment, null, actionType, user, additionalInfo); // TODO: should we send notification to edge? } @Override - public void notifyDeleteAlarmComment(AlarmComment alarmComment, User user, Object... additionalInfo) { - logEntityAction(alarmComment.getTenantId(), alarmComment.getAlarmId(), alarmComment, alarmComment.getCustomerId(), ActionType.DELETED, user, additionalInfo); + public void notifyDeleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user, Object... additionalInfo) { + logEntityAction(tenantId, alarmComment.getAlarmId(), alarmComment, null, ActionType.DELETED, user, additionalInfo); // TODO: should we send notification to edge? } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java index 6719394d5b..060d0f7a2d 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java @@ -103,9 +103,9 @@ public interface TbNotificationEntityService { void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, User user, Object... additionalInfo); - void notifyCreateOrUpdateAlarmComment(AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo); + void notifyCreateOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo); - void notifyDeleteAlarmComment(AlarmComment alarmComment, User user, Object... additionalInfo); + void notifyDeleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user, Object... additionalInfo); void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, I entityId, E entity, User user, ActionType actionType, boolean sendNotifyMsgToEdge, diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java index e0bfaf10e4..8381d6be32 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; @@ -29,22 +30,22 @@ import org.thingsboard.server.service.entitiy.AbstractTbEntityService; @AllArgsConstructor public class DefaultTbAlarmCommentService extends AbstractTbEntityService implements TbAlarmCommentService{ @Override - public AlarmComment saveAlarmComment(AlarmComment alarmComment, User user) throws ThingsboardException { + public AlarmComment saveAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) throws ThingsboardException { ActionType actionType = alarmComment.getId() == null ? ActionType.ADDED : ActionType.UPDATED; UserId userId = user.getId(); alarmComment.setUserId(userId); try { - AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarmComment).getAlarmComment()); - notificationEntityService.notifyCreateOrUpdateAlarmComment(savedAlarmComment, actionType, user); + AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment()); + notificationEntityService.notifyCreateOrUpdateAlarmComment(tenantId, savedAlarmComment, actionType, user); return savedAlarmComment; } catch (Exception e) { - notificationEntityService.logEntityAction(alarmComment.getTenantId(), emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e); + notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e); throw e; } } @Override - public Boolean deleteAlarmComment(AlarmComment alarmComment, User user) { - notificationEntityService.notifyDeleteAlarmComment(alarmComment, user); - return alarmCommentService.deleteAlarmComment(alarmComment.getId()).isSuccessful(); + public Boolean deleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) { + notificationEntityService.notifyDeleteAlarmComment(tenantId, alarmComment, user); + return alarmCommentService.deleteAlarmComment(tenantId, alarmComment.getId()).isSuccessful(); } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java index 375b655af8..7420b2e220 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java @@ -18,9 +18,10 @@ package org.thingsboard.server.service.entitiy.alarm; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.TenantId; public interface TbAlarmCommentService { - AlarmComment saveAlarmComment(AlarmComment alarmComment, User user) throws ThingsboardException; + AlarmComment saveAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) throws ThingsboardException; - Boolean deleteAlarmComment(AlarmComment alarmComment, User user); + Boolean deleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java index 489d9deb81..3c445b7682 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java @@ -32,7 +32,7 @@ public class CustomerUserPermissions extends AbstractPermissions { public CustomerUserPermissions() { super(); put(Resource.ALARM, customerAlarmPermissionChecker); - put(Resource.ALARM_COMMENT, customerAlarmCommentPermissionChecker); + put(Resource.ALARM_COMMENT, customerAlarmPermissionChecker); put(Resource.ASSET, customerEntityPermissionChecker); put(Resource.DEVICE, customerEntityPermissionChecker); put(Resource.CUSTOMER, customerPermissionChecker); @@ -60,19 +60,6 @@ public class CustomerUserPermissions extends AbstractPermissions { } }; - private static final PermissionChecker customerAlarmCommentPermissionChecker = new PermissionChecker() { - @Override - public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) { - if (!user.getTenantId().equals(entity.getTenantId())) { - return false; - } - if (!(entity instanceof HasCustomerId)) { - return false; - } - return user.getCustomerId().equals(((HasCustomerId) entity).getCustomerId()); - } - }; - private static final PermissionChecker customerEntityPermissionChecker = new PermissionChecker.GenericPermissionChecker(Operation.READ, Operation.READ_CREDENTIALS, Operation.READ_ATTRIBUTES, Operation.READ_TELEMETRY, Operation.RPC_CALL, Operation.CLAIM_DEVICES, diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java index 83e6216800..3e92871b85 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.TenantId; @@ -24,11 +25,11 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; public interface AlarmCommentService { - AlarmCommentOperationResult createOrUpdateAlarmComment(AlarmComment alarmComment); + AlarmCommentOperationResult createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment); - AlarmCommentOperationResult deleteAlarmComment(AlarmCommentId alarmCommentId); + AlarmCommentOperationResult deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); - ListenableFuture> findAlarmComments(AlarmId alarmId, PageLink pageLink); + ListenableFuture> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink); ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index ce2d11d12f..3271fcf9ff 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -22,25 +22,16 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import org.thingsboard.server.common.data.BaseData; -import org.thingsboard.server.common.data.HasCustomerId; import org.thingsboard.server.common.data.HasName; -import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.id.AlarmCommentId; -import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; @ApiModel @Data @Builder @AllArgsConstructor -public class AlarmComment extends BaseData implements HasName, HasTenantId, HasCustomerId { - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) - private TenantId tenantId; - - @ApiModelProperty(position = 4, value = "JSON object with Customer Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) - private CustomerId customerId; +public class AlarmComment extends BaseData implements HasName { @ApiModelProperty(position = 2, value = "JSON object with Alarm id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private EntityId alarmId; @ApiModelProperty(position = 3, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) @@ -81,11 +72,9 @@ public class AlarmComment extends BaseData implements HasName, H public AlarmComment(AlarmComment alarmComment) { super(alarmComment.getId()); this.createdTime = alarmComment.getCreatedTime(); - this.tenantId = alarmComment.getTenantId(); - this.customerId = alarmComment.getCustomerId(); + this.alarmId = alarmComment.getAlarmId(); this.type = alarmComment.getType(); this.comment = alarmComment.getComment(); this.userId = alarmComment.getUserId(); - } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java index 7cbff38d80..a9ece008ac 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java @@ -22,8 +22,11 @@ import io.swagger.annotations.ApiModelProperty; public class AlarmCommentInfo extends AlarmComment{ private static final long serialVersionUID = 2807343093519543377L; - @ApiModelProperty(position = 19, value = "Alarm originator name", example = "Thermostat") - private String userName; + @ApiModelProperty(position = 19, value = "User name", example = "John") + private String firstName; + + @ApiModelProperty(position = 19, value = "User name", example = "Brown") + private String lastName; public AlarmCommentInfo() { super(); @@ -33,17 +36,26 @@ public class AlarmCommentInfo extends AlarmComment{ super(alarmComment); } - public AlarmCommentInfo(AlarmComment alarmComment, String userName) { + public AlarmCommentInfo(AlarmComment alarmComment, String firstName, String lastName) { super(alarmComment); - this.userName = userName; + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; } - public String getUserName() { - return userName; + public void setFirstName(String firstName) { + this.firstName = firstName; } - public void setOriginatorName(String originatorName) { - this.userName = originatorName; + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; } @Override @@ -54,14 +66,27 @@ public class AlarmCommentInfo extends AlarmComment{ AlarmCommentInfo alarmCommentInfo = (AlarmCommentInfo) o; - return userName != null ? userName.equals(alarmCommentInfo.userName) : alarmCommentInfo.userName == null; + if (firstName == null) { + if (alarmCommentInfo.firstName != null) + return false; + } else if (!firstName.equals(alarmCommentInfo.firstName)) + return false; + + if (lastName == null) { + if (alarmCommentInfo.lastName != null) + return false; + } else if (!lastName.equals(alarmCommentInfo.lastName)) + return false; + + return true; } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + (userName != null ? userName.hashCode() : 0); + result = 31 * result + (firstName != null ? firstName.hashCode() : 0); + result = 31 * result + (lastName != null ? lastName.hashCode() : 0); return result; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java index e58ca14664..04f2674d39 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.TenantId; @@ -27,12 +28,12 @@ import org.thingsboard.server.dao.Dao; import java.util.UUID; public interface AlarmCommentDao extends Dao { - AlarmComment createAlarmComment(AlarmComment alarmComment); - void deleteAlarmComment(AlarmCommentId alarmCommentId); + AlarmComment createAlarmComment(TenantId tenantId, AlarmComment alarmComment); + void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); AlarmComment findAlarmCommentById(TenantId tenantId, UUID key); - PageData findAlarmComments(AlarmId id, PageLink pageLink); + PageData findAlarmComments(TenantId tenantId, AlarmId id, PageLink pageLink); ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, UUID key); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index d293531dd4..194ef41ffe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -15,13 +15,18 @@ */ package org.thingsboard.server.dao.alarm; +import com.datastax.oss.driver.api.core.uuid.Uuids; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.TenantId; @@ -30,6 +35,11 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.entity.EntityService; import org.thingsboard.server.dao.service.DataValidator; +import org.thingsboard.server.dao.user.UserService; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import static org.thingsboard.server.dao.service.Validator.validateId; @@ -40,33 +50,50 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al @Autowired private AlarmCommentDao alarmCommentDao; @Autowired + private UserService userService; + @Autowired private EntityService entityService; @Autowired private DataValidator alarmCommentDataValidator; @Override - public AlarmCommentOperationResult createOrUpdateAlarmComment(AlarmComment alarmComment) { - alarmCommentDataValidator.validate(alarmComment, AlarmComment::getTenantId); - alarmComment.setCustomerId(entityService.fetchEntityCustomerId(alarmComment.getTenantId(), alarmComment.getAlarmId())); + public AlarmCommentOperationResult createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment) { + alarmCommentDataValidator.validate(alarmComment, tenantId); if (alarmComment.getId() == null) { - return createAlarmComment(alarmComment); + return createAlarmComment(tenantId, alarmComment); } else { - return updateAlarmComment(alarmComment); + return updateAlarmComment(tenantId, alarmComment); } } @Override @Transactional - public AlarmCommentOperationResult deleteAlarmComment(AlarmCommentId alarmCommentId) { + public AlarmCommentOperationResult deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId) { log.debug("Deleting Alarm Comment with id: {}", alarmCommentId); AlarmCommentOperationResult result = new AlarmCommentOperationResult(new AlarmComment(), true); - alarmCommentDao.deleteAlarmComment(alarmCommentId); + alarmCommentDao.deleteAlarmComment(tenantId, alarmCommentId); return result; } @Override - public ListenableFuture> findAlarmComments(AlarmId alarmId, PageLink pageLink) { - PageData alarmComments = alarmCommentDao.findAlarmComments(alarmId, pageLink); - return Futures.immediateFuture(alarmComments); + public ListenableFuture> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink) { + PageData alarmComments = alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink); + return fetchAlarmCommentUserNames(tenantId,alarmComments); + } + + private ListenableFuture> fetchAlarmCommentUserNames(TenantId tenantId, PageData alarmComments) { + List> alarmCommentFutures = new ArrayList<>(alarmComments.getData().size()); + for (AlarmCommentInfo alarmCommentInfo : alarmComments.getData()) { + alarmCommentFutures.add(Futures.transform( + userService.findUserByIdAsync(tenantId, alarmCommentInfo.getUserId()), user -> { + alarmCommentInfo.setFirstName(user.getFirstName()); + alarmCommentInfo.setLastName(user.getLastName()); + return alarmCommentInfo; + }, MoreExecutors.directExecutor() + )); + } + return Futures.transform(Futures.successfulAsList(alarmCommentFutures), + alarmCommentInfos -> new PageData<>(alarmCommentInfos, alarmComments.getTotalPages(), alarmComments.getTotalElements(), + alarmComments.hasNext()), MoreExecutors.directExecutor()); } @Override @@ -76,30 +103,35 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al return alarmCommentDao.findAlarmCommentByIdAsync(tenantId, alarmCommentId.getId()); } - private AlarmCommentOperationResult createAlarmComment(AlarmComment alarmComment) { + private AlarmCommentOperationResult createAlarmComment(TenantId tenantId, AlarmComment alarmComment) { log.debug("New Alarm comment : {}", alarmComment); if (alarmComment.getType() == null) { alarmComment.setType("OTHER"); } - AlarmComment saved = alarmCommentDao.createAlarmComment(alarmComment); + if (alarmComment.getId() == null) { + UUID uuid = Uuids.timeBased(); + alarmComment.setId(new AlarmCommentId(uuid)); + alarmComment.setCreatedTime(Uuids.unixTimestamp(uuid)); + } + AlarmComment saved = alarmCommentDao.createAlarmComment(tenantId, alarmComment); return new AlarmCommentOperationResult(saved, true, true); } - private AlarmCommentOperationResult updateAlarmComment(AlarmComment newAlarmComment) { + private AlarmCommentOperationResult updateAlarmComment(TenantId tenantId, AlarmComment newAlarmComment) { log.debug("Update Alarm comment : {}", newAlarmComment); - validateId(newAlarmComment.getId(), "Alarm comment id should be specified!"); - AlarmComment existing = alarmCommentDao.findAlarmCommentById(newAlarmComment.getTenantId(), newAlarmComment.getId().getId()); + AlarmComment existing = alarmCommentDao.findAlarmCommentById(tenantId, newAlarmComment.getId().getId()); if (existing != null) { - AlarmComment result = alarmCommentDao.save(newAlarmComment.getTenantId(), merge(existing, newAlarmComment)); + if (newAlarmComment.getComment() != null) { + JsonNode comment = newAlarmComment.getComment(); + UUID uuid = Uuids.timeBased(); + ((ObjectNode) comment).put("edited", "true"); + ((ObjectNode) comment).put("editedOn", Uuids.unixTimestamp(uuid)); + existing.setComment(comment); + } + AlarmComment result = alarmCommentDao.save(tenantId, existing); return new AlarmCommentOperationResult(result, true, true); } return null; } - - private AlarmComment merge(AlarmComment existing, AlarmComment alarmComment) { - existing.setCustomerId(alarmComment.getCustomerId()); - existing.setComment(alarmComment.getComment()); - return existing; - } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java new file mode 100644 index 0000000000..089ba0709a --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java @@ -0,0 +1,97 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.model.sql; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.dao.model.BaseEntity; +import org.thingsboard.server.dao.model.BaseSqlEntity; +import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.util.mapping.JsonStringType; + +import javax.persistence.Column; +import javax.persistence.MappedSuperclass; +import java.util.UUID; + +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_ALARM_ID; +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COMMENT; +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TYPE; + +@Data +@EqualsAndHashCode(callSuper = true) +@TypeDef(name = "json", typeClass = JsonStringType.class) +@MappedSuperclass +public abstract class AbstractAlarmCommentEntity extends BaseSqlEntity implements BaseEntity { + + @Column(name = ALARM_COMMENT_ALARM_ID, columnDefinition = "uuid") + private UUID alarmId; + + @Column(name = ModelConstants.ALARM_COMMENT_USER_ID) + private UUID userId; + + @Column(name = ALARM_COMMENT_TYPE) + private String type; + + @Type(type = "json") + @Column(name = ALARM_COMMENT_COMMENT) + private JsonNode comment; + + public AbstractAlarmCommentEntity() { + super(); + } + + public AbstractAlarmCommentEntity(AlarmComment alarmComment) { + if (alarmComment.getId() != null) { + this.setUuid(alarmComment.getUuidId()); + } + this.setCreatedTime(alarmComment.getCreatedTime()); + if (alarmComment.getAlarmId() != null) { + this.alarmId = alarmComment.getAlarmId().getId(); + } + if (alarmComment.getUserId() != null) { + this.userId = alarmComment.getUserId().getId(); + } + if (alarmComment.getType() != null) { + this.type = alarmComment.getType(); + } + this.setComment(alarmComment.getComment()); + } + + public AbstractAlarmCommentEntity(AlarmCommentEntity alarmCommentEntity) { + this.setId(alarmCommentEntity.getId()); + this.setCreatedTime(alarmCommentEntity.getCreatedTime()); + this.userId = alarmCommentEntity.getUserId(); + this.alarmId = alarmCommentEntity.getAlarmId(); + this.type = alarmCommentEntity.getType(); + this.comment = alarmCommentEntity.getComment(); + } + protected AlarmComment toAlarmComment() { + AlarmComment alarmComment = new AlarmComment(new AlarmCommentId(id)); + alarmComment.setCreatedTime(createdTime); + alarmComment.setAlarmId(new AlarmId(alarmId)); + alarmComment.setUserId(new UserId(userId)); + alarmComment.setType(type); + alarmComment.setComment(comment); + return alarmComment; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java index 571c3007e1..6f9a507cbd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java @@ -15,33 +15,17 @@ */ package org.thingsboard.server.dao.model.sql; -import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.alarm.AlarmComment; -import org.thingsboard.server.common.data.id.AlarmCommentId; -import org.thingsboard.server.common.data.id.AlarmId; -import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.dao.model.BaseEntity; -import org.thingsboard.server.dao.model.BaseSqlEntity; -import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.dao.util.mapping.JsonStringType; -import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; -import java.util.UUID; -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_ALARM_ID; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COLUMN_FAMILY_NAME; -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COMMENT; -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_CUSTOMER_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TENANT_ID_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TYPE; @Data @EqualsAndHashCode(callSuper = true) @@ -49,71 +33,23 @@ import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TYPE @TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ALARM_COMMENT_COLUMN_FAMILY_NAME) -public class AlarmCommentEntity extends BaseSqlEntity implements BaseEntity { - - @Column(name = ALARM_COMMENT_TENANT_ID_PROPERTY, columnDefinition = "uuid") - private UUID tenantId; - - @Column(name = ALARM_COMMENT_CUSTOMER_ID_PROPERTY, columnDefinition = "uuid") - private UUID customerId; - @Column(name = ALARM_COMMENT_ALARM_ID, columnDefinition = "uuid") - private UUID alarmId; - - @Column(name = ModelConstants.ALARM_COMMENT_USER_ID) - private UUID userId; - - @Column(name = ALARM_COMMENT_TYPE) - private String type; - - @Type(type = "json") - @Column(name = ALARM_COMMENT_COMMENT) - private JsonNode comment; +public class AlarmCommentEntity extends AbstractAlarmCommentEntity { public AlarmCommentEntity() { super(); } + public AlarmCommentEntity(AlarmCommentInfo alarmCommentInfo) { + super(alarmCommentInfo); + } + public AlarmCommentEntity(AlarmComment alarmComment) { - if (alarmComment.getId() != null) { - this.setUuid(alarmComment.getUuidId()); - } - if (alarmComment.getTenantId() != null) { - this.tenantId = alarmComment.getTenantId().getId(); - } - if (alarmComment.getCustomerId() != null) { - this.customerId = alarmComment.getCustomerId().getId(); - } - this.setCreatedTime(alarmComment.getCreatedTime()); - this.setCreatedTime(alarmComment.getCreatedTime()); - if (alarmComment.getAlarmId() != null) { - this.alarmId = alarmComment.getAlarmId().getId(); - } - if (alarmComment.getUserId() != null) { - this.userId = alarmComment.getUserId().getId(); - } - if (alarmComment.getType() != null) { - this.type = alarmComment.getType(); - } - this.setComment(alarmComment.getComment()); + super(alarmComment); } @Override public AlarmComment toData() { - AlarmComment alarmComment = new AlarmComment(new AlarmCommentId(id)); - alarmComment.setCreatedTime(createdTime); - alarmComment.setAlarmId(new AlarmId(alarmId)); - if (userId != null) { - alarmComment.setUserId(new UserId(userId)); - } - if (tenantId != null) { - alarmComment.setTenantId(TenantId.fromUUID(tenantId)); - } - if (customerId != null) { - alarmComment.setCustomerId(new CustomerId(customerId)); - } - alarmComment.setType(type); - alarmComment.setComment(comment); - return alarmComment; + return super.toAlarmComment(); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java new file mode 100644 index 0000000000..3d5dde1fd6 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java @@ -0,0 +1,41 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.model.sql; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; + +@Data +@EqualsAndHashCode(callSuper = true) +public class AlarmCommentInfoEntity extends AbstractAlarmCommentEntity { + + private String firstName; + private String lastName; + + public AlarmCommentInfoEntity() { + super(); + } + + public AlarmCommentInfoEntity(AlarmCommentEntity alarmCommentEntity) { + super(alarmCommentEntity); + } + + @Override + public AlarmCommentInfo toData() { + return new AlarmCommentInfo(super.toAlarmComment(), this.firstName, this.lastName); + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java index beb4a7ebc1..6efe89df4f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java @@ -67,6 +67,29 @@ public abstract class DataValidator> { } } + public D validate(D data, TenantId tenantId) { + try { + if (data == null) { + throw new DataValidationException("Data object can't be null!"); + } + + ConstraintValidator.validateFields(data); + + validateDataImpl(tenantId, data); + D old; + if (data.getId() == null) { + validateCreate(tenantId, data); + old = null; + } else { + old = validateUpdate(tenantId, data); + } + return old; + } catch (DataValidationException e) { + log.error("{} object is invalid: [{}]", data == null ? "Data" : data.getClass().getSimpleName(), e.getMessage()); + throw e; + } + } + protected void validateDataImpl(TenantId tenantId, D data) { } diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java index 9969de6fe2..d85a58bc6d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/AlarmCommentDataValidator.java @@ -17,28 +17,22 @@ package org.thingsboard.server.dao.service.validator; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.data.StringUtils; -import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DataValidator; -import org.thingsboard.server.dao.tenant.TenantService; @Component @AllArgsConstructor public class AlarmCommentDataValidator extends DataValidator { - private final TenantService tenantService; - @Override protected void validateDataImpl(TenantId tenantId, AlarmComment alarmComment) { - if (alarmComment.getTenantId() == null) { - throw new DataValidationException("Alarm comment should be assigned to tenant!"); - } else { - if (!tenantService.tenantExists(alarmComment.getTenantId())) { - throw new DataValidationException("Alarm comment is referencing to non-existent tenant!"); - } + if (alarmComment.getComment() == null) { + throw new DataValidationException("Alarm comment should be specified!"); + } + if (alarmComment.getAlarmId() == null) { + throw new DataValidationException("Alarm id should be specified!"); } } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java index 1517b35554..be97cb1ee3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmCommentRepository.java @@ -18,12 +18,21 @@ package org.thingsboard.server.dao.sql.alarm; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.AlarmCommentEntity; +import org.thingsboard.server.dao.model.sql.AlarmCommentInfoEntity; import java.util.UUID; public interface AlarmCommentRepository extends JpaRepository { - Page findAllByAlarmId(UUID alarmId, Pageable pageable); - + @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmCommentInfoEntity(a) FROM AlarmCommentEntity a " + + "WHERE a.alarmId = :alarmId ", + countQuery = "" + + "SELECT count(a) " + + "FROM AlarmCommentEntity a " + + "WHERE a.alarmId = :alarmId ") + Page findAllByAlarmId(@Param("alarmId") UUID alarmId, + Pageable pageable); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java index 440510f37b..39524b565f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.sql.alarm; -import com.datastax.oss.driver.api.core.uuid.Uuids; import com.google.common.util.concurrent.ListenableFuture; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -24,6 +23,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.TenantId; @@ -54,34 +54,29 @@ public class JpaAlarmCommentDao extends JpaAbstractDao findAlarmComments(AlarmId id, PageLink pageLink){ + public PageData findAlarmComments(TenantId tenantId, AlarmId id, PageLink pageLink){ log.trace("Try to find alarm comments by alard id using [{}]", id); return DaoUtil.toPageData( alarmCommentRepository.findAllByAlarmId(id.getId(), DaoUtil.toPageable(pageLink))); } - @Override + public AlarmComment findAlarmCommentById(TenantId tenantId, UUID key) { - return findById(tenantId, key); + return DaoUtil.getData(alarmCommentRepository.findById(key)); } @Override diff --git a/dao/src/main/resources/sql/schema-entities-idx.sql b/dao/src/main/resources/sql/schema-entities-idx.sql index e7586b17a8..302e20a619 100644 --- a/dao/src/main/resources/sql/schema-entities-idx.sql +++ b/dao/src/main/resources/sql/schema-entities-idx.sql @@ -75,3 +75,5 @@ CREATE INDEX IF NOT EXISTS idx_rule_node_external_id ON rule_node(rule_chain_id, CREATE INDEX IF NOT EXISTS idx_rule_node_type ON rule_node(type); CREATE INDEX IF NOT EXISTS idx_api_usage_state_entity_id ON api_usage_state(entity_id); + +CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id ASC); diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 73039274a6..4bf12332b2 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -776,3 +776,13 @@ CREATE TABLE IF NOT EXISTS user_auth_settings ( user_id uuid UNIQUE NOT NULL CONSTRAINT fk_user_auth_settings_user_id REFERENCES tb_user(id), two_fa_settings varchar ); + +REATE TABLE IF NOT EXISTS alarm_comment ( + id uuid NOT NULL, + created_time bigint NOT NULL, + alarm_id uuid NOT NULL, + user_id uuid, + type varchar(255) NOT NULL, + comment varchar(1000000), + CONSTRAINT fk_alarm_comment_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE +) PARTITION BY RANGE (created_time); \ No newline at end of file From cdbb5232f12ebbe08be9263019fb073742fc073d Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 14 Dec 2022 12:29:38 +0200 Subject: [PATCH 03/43] updated sql schema update --- application/src/main/data/upgrade/3.5/schema_update.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/data/upgrade/3.5/schema_update.sql b/application/src/main/data/upgrade/3.5/schema_update.sql index e357089e97..bdc9d1b4fc 100644 --- a/application/src/main/data/upgrade/3.5/schema_update.sql +++ b/application/src/main/data/upgrade/3.5/schema_update.sql @@ -23,4 +23,4 @@ CREATE TABLE IF NOT EXISTS alarm_comment ( comment varchar(1000000), CONSTRAINT fk_alarm_comment_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE ) PARTITION BY RANGE (created_time); -CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id ASC); \ No newline at end of file +CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id); \ No newline at end of file From 5580b1795371990c985c94623fbdeee3f80e775c Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 19 Dec 2022 23:22:11 +0200 Subject: [PATCH 04/43] Correctly set root rule chain on initial sync --- .../edge/rpc/fetch/RuleChainsEdgeEventFetcher.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java index 8d2a8adc51..91f453d3de 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/RuleChainsEdgeEventFetcher.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.service.edge.rpc.fetch; +import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; @@ -28,6 +30,8 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.rule.RuleChainService; +import static org.thingsboard.server.service.edge.DefaultEdgeNotificationService.EDGE_IS_ROOT_BODY_KEY; + @Slf4j @AllArgsConstructor public class RuleChainsEdgeEventFetcher extends BasePageableEdgeEventFetcher { @@ -41,7 +45,13 @@ public class RuleChainsEdgeEventFetcher extends BasePageableEdgeEventFetcher Date: Tue, 20 Dec 2022 11:26:11 +0200 Subject: [PATCH 05/43] added tests for alarm comment services --- .../controller/AlarmCommentController.java | 4 +- .../DefaultTbNotificationEntityService.java | 10 +- .../entitiy/TbNotificationEntityService.java | 4 +- .../alarm/DefaultTbAlarmCommentService.java | 16 +- .../entitiy/alarm/TbAlarmCommentService.java | 5 +- .../src/main/resources/thingsboard.yml | 1 + .../controller/AbstractNotifyEntityTest.java | 8 +- .../BaseAlarmCommentControllerTest.java | 384 ++++++++++++++++++ .../sql/AlarmCommentControllerSqlTest.java | 23 ++ .../DefaultTbAlarmCommentServiceTest.java | 96 +++++ .../common/data/alarm/AlarmComment.java | 3 + .../common/data/alarm/AlarmCommentInfo.java | 2 +- .../dao/alarm/BaseAlarmCommentService.java | 11 +- .../main/resources/sql/schema-entities.sql | 2 +- .../dao/service/AbstractServiceTest.java | 3 + .../service/BaseAlarmCommentServiceTest.java | 160 ++++++++ .../sql/AlarmCommentServiceSqlTest.java | 23 ++ .../dao/sql/alarm/JpaAlarmCommentDaoTest.java | 90 ++++ 18 files changed, 816 insertions(+), 29 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java create mode 100644 application/src/test/java/org/thingsboard/server/controller/sql/AlarmCommentControllerSqlTest.java create mode 100644 application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java create mode 100644 dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java create mode 100644 dao/src/test/java/org/thingsboard/server/dao/service/sql/AlarmCommentServiceSqlTest.java create mode 100644 dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index 256dad8f3d..1541b40955 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -77,7 +77,7 @@ public class AlarmCommentController extends BaseController { AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); alarmComment.setAlarmId(alarmId); - return tbAlarmCommentService.saveAlarmComment(alarm.getTenantId(), alarmComment, getCurrentUser()); + return tbAlarmCommentService.saveAlarmComment(alarm, alarmComment, getCurrentUser()); } @ApiOperation(value = "Delete Alarm comment(deleteAlarmComment)", @@ -92,7 +92,7 @@ public class AlarmCommentController extends BaseController { AlarmCommentId alarmCommentId = new AlarmCommentId(toUUID(strCommentId)); AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId); - return tbAlarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment, getCurrentUser()); + return tbAlarmCommentService.deleteAlarmComment(alarm, alarmComment, getCurrentUser()); } @ApiOperation(value = "Get Alarm comments (getAlarmComments)", diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java index 7ac30abf78..c06d6e8d04 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java @@ -231,15 +231,13 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS } @Override - public void notifyCreateOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo) { - logEntityAction(tenantId, alarmComment.getAlarmId(), alarmComment, null, actionType, user, additionalInfo); - // TODO: should we send notification to edge? + public void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user) { + logEntityAction(alarm.getTenantId(), alarmComment.getId(), alarmComment, alarm.getCustomerId(), actionType, user); } @Override - public void notifyDeleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user, Object... additionalInfo) { - logEntityAction(tenantId, alarmComment.getAlarmId(), alarmComment, null, ActionType.DELETED, user, additionalInfo); - // TODO: should we send notification to edge? + public void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { + logEntityAction(alarm.getTenantId(), alarmComment.getId(), alarmComment, alarm.getCustomerId(), ActionType.DELETED, user); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java index 060d0f7a2d..744fa9ddaa 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java @@ -103,9 +103,9 @@ public interface TbNotificationEntityService { void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, User user, Object... additionalInfo); - void notifyCreateOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment, ActionType actionType, User user, Object... additionalInfo); + void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user); - void notifyDeleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user, Object... additionalInfo); + void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user); void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, I entityId, E entity, User user, ActionType actionType, boolean sendNotifyMsgToEdge, diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java index 8381d6be32..5359f02b17 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java @@ -19,10 +19,10 @@ import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; -import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; @@ -30,22 +30,22 @@ import org.thingsboard.server.service.entitiy.AbstractTbEntityService; @AllArgsConstructor public class DefaultTbAlarmCommentService extends AbstractTbEntityService implements TbAlarmCommentService{ @Override - public AlarmComment saveAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) throws ThingsboardException { + public AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException { ActionType actionType = alarmComment.getId() == null ? ActionType.ADDED : ActionType.UPDATED; UserId userId = user.getId(); alarmComment.setUserId(userId); try { - AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment()); - notificationEntityService.notifyCreateOrUpdateAlarmComment(tenantId, savedAlarmComment, actionType, user); + AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment).getAlarmComment()); + notificationEntityService.notifyCreateOrUpdateAlarmComment(alarm, savedAlarmComment, actionType, user); return savedAlarmComment; } catch (Exception e) { - notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e); + notificationEntityService.logEntityAction(alarm.getTenantId(), emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e); throw e; } } @Override - public Boolean deleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) { - notificationEntityService.notifyDeleteAlarmComment(tenantId, alarmComment, user); - return alarmCommentService.deleteAlarmComment(tenantId, alarmComment.getId()).isSuccessful(); + public Boolean deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { + notificationEntityService.notifyDeleteAlarmComment(alarm, alarmComment, user); + return alarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment.getId()).isSuccessful(); } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java index 7420b2e220..5c4b868097 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java @@ -16,12 +16,13 @@ package org.thingsboard.server.service.entitiy.alarm; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; public interface TbAlarmCommentService { - AlarmComment saveAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user) throws ThingsboardException; + AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException; - Boolean deleteAlarmComment(TenantId tenantId, AlarmComment alarmComment, User user); + Boolean deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user); } diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 67f9928c18..cf42b8681f 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -584,6 +584,7 @@ audit-log: "user": "${AUDIT_LOG_MASK_USER:W}" "rule_chain": "${AUDIT_LOG_MASK_RULE_CHAIN:W}" "alarm": "${AUDIT_LOG_MASK_ALARM:W}" + "alarm_comment": "${AUDIT_LOG_MASK_ALARM_COMMENT:W}" "entity_view": "${AUDIT_LOG_MASK_ENTITY_VIEW:W}" "device_profile": "${AUDIT_LOG_MASK_DEVICE_PROFILE:W}" "asset_profile": "${AUDIT_LOG_MASK_ASSET_PROFILE:W}" diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java index 39421a4364..373c5143ac 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java @@ -340,6 +340,12 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { Mockito.argThat(matcherOriginatorId), Mockito.any(TbMsg.class), Mockito.isNull()); } + protected void testPushMsgToRuleEngineTime(EntityId matcherOriginatorId, TenantId tenantId, HasName entity, int cntTime) { + tenantId = tenantId.isNullUid() && ((HasTenantId) entity).getTenantId() != null ? ((HasTenantId) entity).getTenantId() : tenantId; + Mockito.verify(tbClusterService, times(cntTime)).pushMsgToRuleEngine(Mockito.eq(tenantId), + Mockito.eq(matcherOriginatorId), Mockito.any(TbMsg.class), Mockito.isNull()); + } + private void testNotificationMsgToEdgeServiceTime(EntityId entityId, TenantId tenantId, ActionType actionType, int cntTime) { EdgeEventActionType edgeEventActionType = ActionType.CREDENTIALS_UPDATED.equals(actionType) ? EdgeEventActionType.CREDENTIALS_UPDATED : edgeTypeByActionType(actionType); @@ -367,7 +373,7 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { Mockito.verify(tbClusterService, times(cntTime)).pushMsgToCore(Mockito.any(ToDeviceActorNotificationMsg.class), Mockito.isNull()); } - private void testLogEntityAction(HasName entity, EntityId originatorId, TenantId tenantId, + protected void testLogEntityAction(HasName entity, EntityId originatorId, TenantId tenantId, CustomerId customerId, UserId userId, String userName, ActionType actionType, int cntTime, Object... additionalInfo) { ArgumentMatcher matcherEntityEquals = entity == null ? Objects::isNull : argument -> argument.toString().equals(entity.toString()); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java new file mode 100644 index 0000000000..5fe3673154 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java @@ -0,0 +1,384 @@ +/** + * 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. + */ +package org.thingsboard.server.controller; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.TextNode; +import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.AdditionalAnswers; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.test.context.ContextConfiguration; +import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.dao.alarm.AlarmDao; + +import java.util.LinkedList; +import java.util.List; + +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@Slf4j +@ContextConfiguration(classes = {BaseAlarmCommentControllerTest.Config.class}) +public abstract class BaseAlarmCommentControllerTest extends AbstractControllerTest { + + protected Device customerDevice; + protected Alarm alarm; + + static class Config { + @Bean + @Primary + public AlarmDao alarmDao(AlarmDao alarmDao) { + return Mockito.mock(AlarmDao.class, AdditionalAnswers.delegatesTo(alarmDao)); + } + } + + @Before + public void setup() throws Exception { + loginTenantAdmin(); + + Device device = new Device(); + device.setTenantId(tenantId); + device.setName("Test device"); + device.setLabel("Label"); + device.setType("Type"); + device.setCustomerId(customerId); + customerDevice = doPost("/api/device", device, Device.class); + + alarm = Alarm.builder() + .tenantId(tenantId) + .customerId(customerId) + .originator(customerDevice.getId()) + .status(AlarmStatus.ACTIVE_UNACK) + .severity(AlarmSeverity.CRITICAL) + .type("test alarm type") + .build(); + + alarm = doPost("/api/alarm", alarm, Alarm.class); + + resetTokens(); + } + + @After + public void teardown() throws Exception { + Mockito.reset(tbClusterService, auditLogService); + loginSysAdmin(); + deleteDifferentTenant(); + } + + @Test + public void testCreateAlarmCommentViaCustomer() throws Exception { + loginCustomerUser(); + + Mockito.reset(tbClusterService, auditLogService); + + AlarmComment createdComment = createAlarmComment(alarm.getId()); + + testLogEntityAction(createdComment, createdComment.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ADDED, 1); + testPushMsgToRuleEngineTime(createdComment.getId(), tenantId, createdComment, 1); + } + + @Test + public void testCreateAlarmCommentViaTenant() throws Exception { + loginTenantAdmin(); + + Mockito.reset(tbClusterService, auditLogService); + + AlarmComment createdComment = createAlarmComment(alarm.getId()); + Assert.assertEquals("OTHER", createdComment.getType()); + + testLogEntityAction(createdComment, createdComment.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ADDED, 1); + testPushMsgToRuleEngineTime(createdComment.getId(), tenantId, createdComment, 1); + } + + @Test + public void testUpdateAlarmCommentViaCustomer() throws Exception { + loginCustomerUser(); + AlarmComment savedComment = createAlarmComment(alarm.getId()); + + Mockito.reset(tbClusterService, auditLogService); + + JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment")); + savedComment.setComment(newComment); + AlarmComment updatedAlarmComment = saveAlarmComment(alarm.getId(), savedComment); + + Assert.assertNotNull(updatedAlarmComment); + Assert.assertEquals(newComment.get("text"), updatedAlarmComment.getComment().get("text")); + Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText()); + Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn")); + + testNotifyEntityAllOneTime(updatedAlarmComment, updatedAlarmComment.getId(), updatedAlarmComment.getId(), + tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.UPDATED); + } + + @Test + public void testUpdateAlarmViaTenant() throws Exception { + loginTenantAdmin(); + AlarmComment savedComment = createAlarmComment(alarm.getId()); + + Mockito.reset(tbClusterService, auditLogService); + + JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment")); + savedComment.setComment(newComment); + AlarmComment updatedAlarmComment = saveAlarmComment(alarm.getId(), savedComment); + + Assert.assertNotNull(updatedAlarmComment); + Assert.assertEquals(newComment.get("text"), updatedAlarmComment.getComment().get("text")); + Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText()); + Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn")); + + testNotifyEntityAllOneTime(updatedAlarmComment, updatedAlarmComment.getId(), updatedAlarmComment.getId(), + tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.UPDATED); + } + + @Test + public void testUpdateAlarmViaDifferentTenant() throws Exception { + loginTenantAdmin(); + AlarmComment savedComment = createAlarmComment(alarm.getId()); + + loginDifferentTenant(); + + Mockito.reset(tbClusterService, auditLogService); + JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment")); + savedComment.setComment(newComment); + + doPost("/api/alarm/" + alarm.getId() + "/comment", savedComment) + .andExpect(status().isForbidden()) + .andExpect(statusReason(containsString(msgErrorPermission))); + + testNotifyEntityNever(savedComment.getId(), savedComment); + } + + @Test + public void testUpdateAlarmViaDifferentCustomer() throws Exception { + loginCustomerUser(); + AlarmComment savedComment = createAlarmComment(alarm.getId()); + + loginDifferentCustomer(); + + Mockito.reset(tbClusterService, auditLogService); + JsonNode newComment = JacksonUtil.newObjectNode().set("text", new TextNode("Updated comment")); + savedComment.setComment(newComment); + + doPost("/api/alarm/" + alarm.getId() + "/comment", savedComment) + .andExpect(status().isForbidden()) + .andExpect(statusReason(containsString(msgErrorPermission))); + + testNotifyEntityNever(savedComment.getId(), savedComment); + } + + @Test + public void testDeleteAlarmViaCustomer() throws Exception { + loginCustomerUser(); + AlarmComment alarmComment = createAlarmComment(alarm.getId()); + + Mockito.reset(tbClusterService, auditLogService); + + doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId()) + .andExpect(status().isOk()); + + testNotifyEntityOneTimeMsgToEdgeServiceNever(alarmComment, alarmComment.getId(), alarmComment.getId(), + tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.DELETED); + } + + @Test + public void testDeleteAlarmViaTenant() throws Exception { + loginTenantAdmin(); + AlarmComment alarmComment = createAlarmComment(alarm.getId()); + + Mockito.reset(tbClusterService, auditLogService); + + doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId()) + .andExpect(status().isOk()); + + testNotifyEntityOneTimeMsgToEdgeServiceNever(alarmComment, alarmComment.getId(), alarmComment.getId(), + tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.DELETED); + } + + @Test + public void testDeleteAlarmViaDifferentTenant() throws Exception { + loginTenantAdmin(); + AlarmComment alarmComment = createAlarmComment(alarm.getId()); + + loginDifferentTenant(); + + Mockito.reset(tbClusterService, auditLogService); + + doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId()) + .andExpect(status().isForbidden()) + .andExpect(statusReason(containsString(msgErrorPermission))); + + testNotifyEntityNever(alarm.getId(), alarm); + } + + @Test + public void testDeleteAlarmViaDifferentCustomer() throws Exception { + loginCustomerUser(); + AlarmComment alarmComment = createAlarmComment(alarm.getId()); + + loginDifferentCustomer(); + + Mockito.reset(tbClusterService, auditLogService); + + doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId()) + .andExpect(status().isForbidden()) + .andExpect(statusReason(containsString(msgErrorPermission))); + + testNotifyEntityNever(alarm.getId(), alarm); + } + + @Test + public void testClearAlarmViaCustomer() throws Exception { + loginCustomerUser(); + AlarmComment alarmComment = createAlarmComment(alarm.getId()); + + Mockito.reset(tbClusterService, auditLogService); + + doPost("/api/alarm/" + alarm.getId() + "/clear").andExpect(status().isOk()); + + Alarm foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class); + Assert.assertNotNull(foundAlarm); + Assert.assertEquals(AlarmStatus.CLEARED_UNACK, foundAlarm.getStatus()); + + } + + @Test + public void testFindAlarmCommentsViaCustomerUser() throws Exception { + loginCustomerUser(); + + List createdAlarmComments = new LinkedList<>(); + + final int size = 10; + for (int i = 0; i < size; i++) { + createdAlarmComments.add( + createAlarmComment(alarm.getId(), RandomStringUtils.randomAlphanumeric(10)) + ); + } + + var response = doGetTyped( + "/api/alarm/" + alarm.getId() + "/comment?page=0&pageSize=" + size, + new TypeReference>() {} + ); + var foundAlarmCommentInfos = response.getData(); + Assert.assertNotNull("Found pageData is null", foundAlarmCommentInfos); + Assert.assertNotEquals( + "Expected alarms are not found!", + 0, foundAlarmCommentInfos.size() + ); + + boolean allMatch = createdAlarmComments.stream() + .allMatch(alarmComment -> foundAlarmCommentInfos.stream() + .map(AlarmCommentInfo::getComment) + .anyMatch(comment -> alarmComment.getComment().equals(comment)) + ); + Assert.assertTrue("Created alarm comment doesn't match any found!", allMatch); + } + + @Test + public void testFindAlarmsViaDifferentCustomerUser() throws Exception { + loginCustomerUser(); + + final int size = 10; + List createdAlarmComments = new LinkedList<>(); + for (int i = 0; i < size; i++) { + createdAlarmComments.add( + createAlarmComment(alarm.getId(), RandomStringUtils.randomAlphanumeric(10)) + ); + } + + loginDifferentCustomer(); + doGet("/api/alarm/" + alarm.getId() + "/comment?page=0&pageSize=" + size) + .andExpect(status().isForbidden()) + .andExpect(statusReason(containsString(msgErrorPermission))); + } + + @Test + public void testFindAlarmCommentsViaPublicCustomer() throws Exception { + loginTenantAdmin(); + + Device device = new Device(); + device.setName("Test Public Device"); + device.setLabel("Label"); + device.setCustomerId(customerId); + device = doPost("/api/device", device, Device.class); + device = doPost("/api/customer/public/device/" + device.getUuidId(), Device.class); + + String publicId = device.getCustomerId().toString(); + + Alarm alarm = Alarm.builder() + .originator(device.getId()) + .status(AlarmStatus.ACTIVE_UNACK) + .severity(AlarmSeverity.CRITICAL) + .type("Test") + .build(); + + alarm = doPost("/api/alarm", alarm, Alarm.class); + + Mockito.reset(tbClusterService, auditLogService); + AlarmComment alarmComment = createAlarmComment(alarm.getId()); + + resetTokens(); + + JsonNode publicLoginRequest = JacksonUtil.toJsonNode("{\"publicId\": \"" + publicId + "\"}"); + JsonNode tokens = doPost("/api/auth/login/public", publicLoginRequest, JsonNode.class); + this.token = tokens.get("token").asText(); + + PageData pageData = doGetTyped( + "/api/alarm/" + alarm.getId() + "/comment" + "?page=0&pageSize=1", new TypeReference>() {} + ); + + Assert.assertNotNull("Found pageData is null", pageData); + Assert.assertNotEquals("Expected alarms are not found!", 0, pageData.getTotalElements()); + + AlarmCommentInfo alarmCommentInfo = pageData.getData().get(0); + boolean equals = alarmComment.getId().equals(alarmCommentInfo.getId()) && alarmComment.getComment().equals(alarmCommentInfo.getComment()); + Assert.assertTrue("Created alarm doesn't match the found one!", equals); + } + + private AlarmComment createAlarmComment(AlarmId alarmId, String text) { + AlarmComment alarmComment = AlarmComment.builder() + .comment(JacksonUtil.newObjectNode().set("text", new TextNode(text))) + .build(); + + return saveAlarmComment(alarmId, alarmComment); + } + private AlarmComment createAlarmComment(AlarmId alarmId) { + return createAlarmComment(alarmId, "Please take a look"); + } + private AlarmComment saveAlarmComment(AlarmId alarmId, AlarmComment alarmComment) { + alarmComment = doPost("/api/alarm/" + alarmId + "/comment", alarmComment, AlarmComment.class); + Assert.assertNotNull(alarmComment); + + return alarmComment; + } +} diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/AlarmCommentControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/AlarmCommentControllerSqlTest.java new file mode 100644 index 0000000000..ecf2791c1c --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/sql/AlarmCommentControllerSqlTest.java @@ -0,0 +1,23 @@ +/** + * 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. + */ +package org.thingsboard.server.controller.sql; + +import org.thingsboard.server.controller.BaseAlarmCommentControllerTest; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +public class AlarmCommentControllerSqlTest extends BaseAlarmCommentControllerTest { +} diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java new file mode 100644 index 0000000000..808af7d2a1 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java @@ -0,0 +1,96 @@ +/** + * 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. + */ +package org.thingsboard.server.service.entitiy.alarmComment; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.thingsboard.server.cluster.TbClusterService; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.dao.alarm.AlarmCommentOperationResult; +import org.thingsboard.server.dao.alarm.AlarmCommentService; +import org.thingsboard.server.dao.alarm.AlarmService; +import org.thingsboard.server.dao.customer.CustomerService; +import org.thingsboard.server.service.entitiy.TbNotificationEntityService; +import org.thingsboard.server.service.entitiy.alarm.DefaultTbAlarmCommentService; +import org.thingsboard.server.service.executors.DbCallbackExecutorService; +import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; + +import java.util.UUID; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@Slf4j +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = DefaultTbAlarmCommentService.class) +@TestPropertySource(properties = { + "server.log_controller_error_stack_trace=false" +}) +public class DefaultTbAlarmCommentServiceTest { + + @MockBean + protected DbCallbackExecutorService dbExecutor; + @MockBean + protected TbNotificationEntityService notificationEntityService; + @MockBean + protected AlarmService alarmService; + @MockBean + protected AlarmCommentService alarmCommentService; + @MockBean + protected AlarmSubscriptionService alarmSubscriptionService; + @MockBean + protected CustomerService customerService; + @MockBean + protected TbClusterService tbClusterService; + @SpyBean + DefaultTbAlarmCommentService service; + + @Test + public void testSave() throws ThingsboardException { + var alarm = new Alarm(); + var alarmComment = new AlarmComment(); + when(alarmCommentService.createOrUpdateAlarmComment(Mockito.any(), eq(alarmComment))).thenReturn(new AlarmCommentOperationResult(alarmComment, true)); + service.saveAlarmComment(alarm, alarmComment, new User()); + + verify(notificationEntityService, times(1)).notifyCreateOrUpdateAlarmComment(any(), any(), any(), any()); + } + + @Test + public void testDelete() { + var alarmId = new AlarmId(UUID.randomUUID()); + var alarmCommentId = new AlarmCommentId(UUID.randomUUID()); + + when(alarmCommentService.deleteAlarmComment(Mockito.any(), eq(alarmCommentId))).thenReturn(new AlarmCommentOperationResult(new AlarmComment(), true)); + service.deleteAlarmComment(new Alarm(alarmId), new AlarmComment(alarmCommentId), new User()); + + verify(notificationEntityService, times(1)).notifyDeleteAlarmComment(any(), any(), any()); + } +} \ No newline at end of file diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index 3271fcf9ff..2e3d4eb459 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.alarm; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -65,6 +66,8 @@ public class AlarmComment extends BaseData implements HasName { } @Override + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @ApiModelProperty(position = 5, required = true, value = "representing comment text", example = "Please take a look") public String getName() { return comment.toString(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java index a9ece008ac..247e0e5236 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java @@ -19,7 +19,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @ApiModel -public class AlarmCommentInfo extends AlarmComment{ +public class AlarmCommentInfo extends AlarmComment { private static final long serialVersionUID = 2807343093519543377L; @ApiModelProperty(position = 19, value = "User name", example = "John") diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 194ef41ffe..f55a3564d9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -33,7 +33,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.AbstractEntityService; -import org.thingsboard.server.dao.entity.EntityService; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.user.UserService; @@ -52,8 +51,6 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al @Autowired private UserService userService; @Autowired - private EntityService entityService; - @Autowired private DataValidator alarmCommentDataValidator; @Override public AlarmCommentOperationResult createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment) { @@ -77,7 +74,7 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al @Override public ListenableFuture> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink) { PageData alarmComments = alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink); - return fetchAlarmCommentUserNames(tenantId,alarmComments); + return fetchAlarmCommentUserNames(tenantId, alarmComments); } private ListenableFuture> fetchAlarmCommentUserNames(TenantId tenantId, PageData alarmComments) { @@ -85,8 +82,10 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al for (AlarmCommentInfo alarmCommentInfo : alarmComments.getData()) { alarmCommentFutures.add(Futures.transform( userService.findUserByIdAsync(tenantId, alarmCommentInfo.getUserId()), user -> { - alarmCommentInfo.setFirstName(user.getFirstName()); - alarmCommentInfo.setLastName(user.getLastName()); + if (user != null) { + alarmCommentInfo.setFirstName(user.getFirstName()); + alarmCommentInfo.setLastName(user.getLastName()); + } return alarmCommentInfo; }, MoreExecutors.directExecutor() )); diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 4bf12332b2..290e330630 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -777,7 +777,7 @@ CREATE TABLE IF NOT EXISTS user_auth_settings ( two_fa_settings varchar ); -REATE TABLE IF NOT EXISTS alarm_comment ( +CREATE TABLE IF NOT EXISTS alarm_comment ( id uuid NOT NULL, created_time bigint NOT NULL, alarm_id uuid NOT NULL, diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java index 5ea3874d19..61147120bc 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java @@ -47,6 +47,7 @@ import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; import org.thingsboard.server.common.data.ota.OtaPackageType; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.asset.AssetProfileService; import org.thingsboard.server.dao.asset.AssetService; @@ -149,6 +150,8 @@ public abstract class AbstractServiceTest { @Autowired protected AlarmService alarmService; + @Autowired + protected AlarmCommentService alarmCommentService; @Autowired protected RuleChainService ruleChainService; diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java new file mode 100644 index 0000000000..e879910515 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java @@ -0,0 +1,160 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.service; + +import com.datastax.oss.driver.api.core.uuid.Uuids; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.security.Authority; + +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { + + public static final String TEST_ALARM = "TEST_ALARM"; + private TenantId tenantId; + private Alarm alarm; + private User user; + + @Before + public void before() { + Tenant tenant = new Tenant(); + tenant.setTitle("My tenant"); + Tenant savedTenant = tenantService.saveTenant(tenant); + Assert.assertNotNull(savedTenant); + tenantId = savedTenant.getId(); + + alarm = Alarm.builder().tenantId(tenantId).originator(new AssetId(Uuids.timeBased())) + .type(TEST_ALARM) + .severity(AlarmSeverity.CRITICAL).status(AlarmStatus.ACTIVE_UNACK) + .startTs(System.currentTimeMillis()).build(); + alarm = alarmService.createOrUpdateAlarm(alarm).getAlarm(); + + user = new User(); + user.setAuthority(Authority.TENANT_ADMIN); + user.setTenantId(tenantId); + user.setEmail("tenant@thingsboard.org"); + user = userService.saveUser(user); + } + + @After + public void after() { + alarmService.deleteAlarm(tenantId, alarm.getId()); + tenantService.deleteTenant(tenantId); + } + + + @Test + public void testSaveAndFetchAlarmComment() throws ExecutionException, InterruptedException { + AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId()) + .userId(user.getId()) + .type("OTHER") + .comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))) + .build(); + + AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment(); + + Assert.assertNotNull(createdComment); + Assert.assertNotNull(createdComment.getId()); + + Assert.assertEquals(alarm.getId(), createdComment.getAlarmId()); + Assert.assertEquals(user.getId(), createdComment.getUserId()); + Assert.assertEquals("OTHER", createdComment.getType()); + Assert.assertTrue(createdComment.getCreatedTime() > 0); + + AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get(); + Assert.assertEquals(createdComment, fetched); + + PageData alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)).get(); + Assert.assertNotNull(alarmComments.getData()); + Assert.assertEquals(1, alarmComments.getData().size()); + Assert.assertEquals(createdComment, alarmComments.getData().get(0)); + } + + @Test + public void testUpdateAlarmComment() throws ExecutionException, InterruptedException { + UserId userId = new UserId(UUID.randomUUID()); + AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId()) + .userId(userId) + .type("OTHER") + .comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))) + .build(); + + AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment(); + + Assert.assertNotNull(createdComment); + Assert.assertNotNull(createdComment.getId()); + + //update comment + String newComment = "new comment"; + createdComment.setComment(JacksonUtil.newObjectNode().put("text", newComment)); + AlarmComment updatedComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, createdComment).getAlarmComment(); + + Assert.assertEquals(alarm.getId(), updatedComment.getAlarmId()); + Assert.assertEquals(userId, updatedComment.getUserId()); + Assert.assertEquals("OTHER", updatedComment.getType()); + Assert.assertTrue(updatedComment.getCreatedTime() > 0); + Assert.assertEquals(newComment, updatedComment.getComment().get("text").asText()); + Assert.assertEquals("true", updatedComment.getComment().get("edited").asText()); + Assert.assertNotNull(updatedComment.getComment().get("editedOn").asText()); + + AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get(); + Assert.assertEquals(updatedComment, fetched); + + PageData alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)).get(); + Assert.assertNotNull(alarmComments.getData()); + Assert.assertEquals(1, alarmComments.getData().size()); + Assert.assertEquals(new AlarmCommentInfo(updatedComment), alarmComments.getData().get(0)); + } + + @Test + public void testDeleteAlarmComment() throws ExecutionException, InterruptedException { + UserId userId = new UserId(UUID.randomUUID()); + AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId()) + .userId(userId) + .type("OTHER") + .comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))) + .build(); + + AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment(); + + Assert.assertNotNull(createdComment); + Assert.assertNotNull(createdComment.getId()); + + Assert.assertTrue("Alarm comment was not deleted when expected", alarmCommentService.deleteAlarmComment(tenantId, createdComment.getId()).isSuccessful()); + + AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get(); + + Assert.assertNull("Alarm comment was returned when it was expected to be null", fetched); + } +} diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/sql/AlarmCommentServiceSqlTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/sql/AlarmCommentServiceSqlTest.java new file mode 100644 index 0000000000..510b8659e9 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/service/sql/AlarmCommentServiceSqlTest.java @@ -0,0 +1,23 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.service.sql; + +import org.thingsboard.server.dao.service.BaseAlarmCommentServiceTest; +import org.thingsboard.server.dao.service.DaoSqlTest; + +@DaoSqlTest +public class AlarmCommentServiceSqlTest extends BaseAlarmCommentServiceTest { +} diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java new file mode 100644 index 0000000000..8530525a63 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java @@ -0,0 +1,90 @@ +/** + * 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. + */ +package org.thingsboard.server.dao.sql.alarm; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.dao.AbstractJpaDaoTest; +import org.thingsboard.server.dao.alarm.AlarmCommentDao; +import org.thingsboard.server.dao.alarm.AlarmDao; + +import java.util.UUID; +import static org.junit.Assert.assertEquals; + +@Slf4j +public class JpaAlarmCommentDaoTest extends AbstractJpaDaoTest { + + @Autowired + private AlarmCommentDao alarmCommentDao; + @Autowired + private AlarmDao alarmDao; + + + @Test + public void testFindAlarmCommentsByAlarmId() { + log.info("Current system time in millis = {}", System.currentTimeMillis()); + UUID tenantId = UUID.randomUUID(); + UUID userId = UUID.randomUUID(); + UUID alarmId1 = UUID.randomUUID(); + UUID alarmId2 = UUID.randomUUID(); + UUID commentId1 = UUID.randomUUID(); + UUID commentId2 = UUID.randomUUID(); + UUID commentId3 = UUID.randomUUID(); + saveAlarm(alarmId1, UUID.randomUUID(), UUID.randomUUID(), "TEST_ALARM"); + saveAlarm(alarmId2, UUID.randomUUID(), UUID.randomUUID(), "TEST_ALARM"); + + saveAlarmComment(commentId1, alarmId1, userId, "OTHER"); + saveAlarmComment(commentId2, alarmId1, userId, "OTHER"); + saveAlarmComment(commentId3, alarmId2, userId, "OTHER"); + + int count = alarmCommentDao.findAlarmComments(TenantId.fromUUID(tenantId), new AlarmId(alarmId1), new PageLink(10, 0)).getData().size(); + assertEquals(2, count); + } + + private void saveAlarm(UUID id, UUID tenantId, UUID deviceId, String type) { + Alarm alarm = new Alarm(); + alarm.setId(new AlarmId(id)); + alarm.setTenantId(TenantId.fromUUID(tenantId)); + alarm.setOriginator(new DeviceId(deviceId)); + alarm.setType(type); + alarm.setPropagate(true); + alarm.setStartTs(System.currentTimeMillis()); + alarm.setEndTs(System.currentTimeMillis()); + alarm.setStatus(AlarmStatus.ACTIVE_UNACK); + alarmDao.save(TenantId.fromUUID(tenantId), alarm); + } + private void saveAlarmComment(UUID id, UUID alarmId, UUID userId, String type) { + AlarmComment alarmComment = new AlarmComment(); + alarmComment.setId(new AlarmCommentId(id)); + alarmComment.setAlarmId(TenantId.fromUUID(alarmId)); + alarmComment.setUserId(new UserId(userId)); + alarmComment.setType(type); + alarmComment.setComment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))); + alarmCommentDao.createAlarmComment(TenantId.fromUUID(UUID.randomUUID()), alarmComment); + } +} From 7203c15dec6d47ae34f4d75bf308b473020e6280 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 20 Dec 2022 15:07:50 +0200 Subject: [PATCH 06/43] fixed pull request comments --- .../main/data/upgrade/{3.5 => 3.4.3}/schema_update.sql | 0 .../server/controller/AlarmCommentController.java | 2 +- .../service/entitiy/TbNotificationEntityService.java | 1 + .../entitiy/alarm/DefaultTbAlarmCommentService.java | 1 + .../server/dao/alarm/AlarmCommentOperationResult.java | 1 - .../server/dao/alarm/AlarmCommentService.java | 2 +- .../server/common/data/alarm/AlarmComment.java | 8 ++++---- .../server/dao/alarm/BaseAlarmCommentService.java | 5 ++--- .../server/dao/model/sql/AlarmCommentInfoEntity.java | 9 +++++++++ .../server/dao/sql/alarm/AlarmCommentRepository.java | 3 ++- .../server/dao/sql/alarm/JpaAlarmCommentDao.java | 4 ++-- .../server/dao/service/BaseAlarmCommentServiceTest.java | 4 ++-- 12 files changed, 25 insertions(+), 15 deletions(-) rename application/src/main/data/upgrade/{3.5 => 3.4.3}/schema_update.sql (100%) diff --git a/application/src/main/data/upgrade/3.5/schema_update.sql b/application/src/main/data/upgrade/3.4.3/schema_update.sql similarity index 100% rename from application/src/main/data/upgrade/3.5/schema_update.sql rename to application/src/main/data/upgrade/3.4.3/schema_update.sql diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index 1541b40955..db8853122b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -118,6 +118,6 @@ public class AlarmCommentController extends BaseController { Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); PageLink pageLink = createPageLink(pageSize, page, null, sortProperty, sortOrder); - return checkNotNull(alarmCommentService.findAlarmComments(alarm.getTenantId(), alarmId, pageLink).get()); + return checkNotNull(alarmCommentService.findAlarmComments(alarm.getTenantId(), alarmId, pageLink)); } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java index 744fa9ddaa..6ef53fd7f6 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java @@ -106,6 +106,7 @@ public interface TbNotificationEntityService { void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user); void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user); + void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, I entityId, E entity, User user, ActionType actionType, boolean sendNotifyMsgToEdge, diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java index 5359f02b17..5904745088 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java @@ -43,6 +43,7 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem throw e; } } + @Override public Boolean deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { notificationEntityService.notifyDeleteAlarmComment(alarm, alarmComment, user); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java index 3687a03eca..3dc25e02ab 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java @@ -24,7 +24,6 @@ public class AlarmCommentOperationResult { private final boolean successful; private final boolean created; - public AlarmCommentOperationResult(AlarmComment alarmComment, boolean successful) { this(alarmComment, successful, false); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java index 3e92871b85..04eac2cc15 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -29,7 +29,7 @@ public interface AlarmCommentService { AlarmCommentOperationResult deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); - ListenableFuture> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink); + PageDatafindAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink); ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index 2e3d4eb459..05aecdc7f0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -33,13 +33,13 @@ import org.thingsboard.server.common.data.id.UserId; @Builder @AllArgsConstructor public class AlarmComment extends BaseData implements HasName { - @ApiModelProperty(position = 2, value = "JSON object with Alarm id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @ApiModelProperty(position = 3, value = "JSON object with Alarm id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private EntityId alarmId; - @ApiModelProperty(position = 3, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @ApiModelProperty(position = 4, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private UserId userId; - @ApiModelProperty(position = 4, value = "Defines origination of comment", example = "System/Other", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @ApiModelProperty(position = 5, value = "Defines origination of comment", example = "System/Other", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String type; - @ApiModelProperty(position = 5, value = "JSON object with text of comment.", dataType = "com.fasterxml.jackson.databind.JsonNode") + @ApiModelProperty(position = 6, value = "JSON object with text of comment.", dataType = "com.fasterxml.jackson.databind.JsonNode") private transient JsonNode comment; @ApiModelProperty(position = 1, value = "JSON object with the alarm comment Id. " + diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index f55a3564d9..33258f58cd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -72,9 +72,8 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al } @Override - public ListenableFuture> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink) { - PageData alarmComments = alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink); - return fetchAlarmCommentUserNames(tenantId, alarmComments); + public PageData findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink) { + return alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink); } private ListenableFuture> fetchAlarmCommentUserNames(TenantId tenantId, PageData alarmComments) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java index 3d5dde1fd6..3bcb49f260 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java @@ -19,6 +19,9 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; +import java.util.HashMap; +import java.util.Map; + @Data @EqualsAndHashCode(callSuper = true) public class AlarmCommentInfoEntity extends AbstractAlarmCommentEntity { @@ -34,6 +37,12 @@ public class AlarmCommentInfoEntity extends AbstractAlarmCommentEntity { - @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmCommentInfoEntity(a) FROM AlarmCommentEntity a " + + @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmCommentInfoEntity(a, u.firstName, u.lastName) FROM AlarmCommentEntity a " + + "LEFT JOIN UserEntity u on u.id = a.userId " + "WHERE a.alarmId = :alarmId ", countQuery = "" + "SELECT count(a) " + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java index 39524b565f..8b8b845b2e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java @@ -55,7 +55,7 @@ public class JpaAlarmCommentDao extends JpaAbstractDao alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)).get(); + PageData alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)); Assert.assertNotNull(alarmComments.getData()); Assert.assertEquals(1, alarmComments.getData().size()); Assert.assertEquals(createdComment, alarmComments.getData().get(0)); @@ -131,7 +131,7 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get(); Assert.assertEquals(updatedComment, fetched); - PageData alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)).get(); + PageData alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)); Assert.assertNotNull(alarmComments.getData()); Assert.assertEquals(1, alarmComments.getData().size()); Assert.assertEquals(new AlarmCommentInfo(updatedComment), alarmComments.getData().get(0)); From 955369a7f15eb6a44b4537cf6028cfc1c3e58e05 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 20 Dec 2022 15:14:45 +0200 Subject: [PATCH 07/43] refactoring --- .../dao/alarm/BaseAlarmCommentService.java | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 33258f58cd..b7a1554d67 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -76,24 +76,6 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al return alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink); } - private ListenableFuture> fetchAlarmCommentUserNames(TenantId tenantId, PageData alarmComments) { - List> alarmCommentFutures = new ArrayList<>(alarmComments.getData().size()); - for (AlarmCommentInfo alarmCommentInfo : alarmComments.getData()) { - alarmCommentFutures.add(Futures.transform( - userService.findUserByIdAsync(tenantId, alarmCommentInfo.getUserId()), user -> { - if (user != null) { - alarmCommentInfo.setFirstName(user.getFirstName()); - alarmCommentInfo.setLastName(user.getLastName()); - } - return alarmCommentInfo; - }, MoreExecutors.directExecutor() - )); - } - return Futures.transform(Futures.successfulAsList(alarmCommentFutures), - alarmCommentInfos -> new PageData<>(alarmCommentInfos, alarmComments.getTotalPages(), alarmComments.getTotalElements(), - alarmComments.hasNext()), MoreExecutors.directExecutor()); - } - @Override public ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId) { log.trace("Executing findAlarmCommentByIdAsync [{}]", alarmCommentId); From df31723f580e9e595db04e0249c8d605f82917e6 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 20 Dec 2022 15:37:37 +0200 Subject: [PATCH 08/43] pull request comments --- .../common/data/alarm/AlarmCommentInfo.java | 56 ++----------------- .../server/common/data/id/AlarmCommentId.java | 2 +- .../dao/alarm/BaseAlarmCommentService.java | 6 +- .../dao/sql/alarm/JpaAlarmCommentDao.java | 4 +- 4 files changed, 13 insertions(+), 55 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java index 247e0e5236..dbf603fdbc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java @@ -17,15 +17,19 @@ package org.thingsboard.server.common.data.alarm; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; @ApiModel +@Data +@EqualsAndHashCode(callSuper = true) public class AlarmCommentInfo extends AlarmComment { private static final long serialVersionUID = 2807343093519543377L; - @ApiModelProperty(position = 19, value = "User name", example = "John") + @ApiModelProperty(position = 19, value = "User first name", example = "John") private String firstName; - @ApiModelProperty(position = 19, value = "User name", example = "Brown") + @ApiModelProperty(position = 19, value = "User last name", example = "Brown") private String lastName; public AlarmCommentInfo() { @@ -41,52 +45,4 @@ public class AlarmCommentInfo extends AlarmComment { this.firstName = firstName; this.lastName = lastName; } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - - AlarmCommentInfo alarmCommentInfo = (AlarmCommentInfo) o; - - if (firstName == null) { - if (alarmCommentInfo.firstName != null) - return false; - } else if (!firstName.equals(alarmCommentInfo.firstName)) - return false; - - if (lastName == null) { - if (alarmCommentInfo.lastName != null) - return false; - } else if (!lastName.equals(alarmCommentInfo.lastName)) - return false; - - return true; - - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = 31 * result + (firstName != null ? firstName.hashCode() : 0); - result = 31 * result + (lastName != null ? lastName.hashCode() : 0); - return result; - } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java index b13b5837a0..3e0c415b0f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java @@ -26,7 +26,7 @@ import java.util.UUID; @ApiModel public class AlarmCommentId extends UUIDBased implements EntityId{ - private static final long serialVersionUID = 2L; + private static final long serialVersionUID = 1L; @JsonCreator public AlarmCommentId(@JsonProperty("id") UUID id) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index b7a1554d67..1de9080a00 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -63,7 +63,6 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al } @Override - @Transactional public AlarmCommentOperationResult deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId) { log.debug("Deleting Alarm Comment with id: {}", alarmCommentId); AlarmCommentOperationResult result = new AlarmCommentOperationResult(new AlarmComment(), true); @@ -73,13 +72,14 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al @Override public PageData findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink) { + log.trace("Executing findAlarmComments by alarmId [{}]", alarmId); return alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink); } @Override public ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId) { - log.trace("Executing findAlarmCommentByIdAsync [{}]", alarmCommentId); - validateId(alarmCommentId, "Incorrect alarmId " + alarmCommentId); + log.trace("Executing findAlarmCommentByIdAsync by alarmCommentId [{}]", alarmCommentId); + validateId(alarmCommentId, "Incorrect alarmCommentId " + alarmCommentId); return alarmCommentDao.findAlarmCommentByIdAsync(tenantId, alarmCommentId.getId()); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java index 8b8b845b2e..f36405ce1c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java @@ -69,18 +69,20 @@ public class JpaAlarmCommentDao extends JpaAbstractDao findAlarmComments(TenantId tenantId, AlarmId id, PageLink pageLink){ - log.trace("Try to find alarm comments by alard id using [{}]", id); + log.trace("Try to find alarm comments by alarm id using [{}]", id); return DaoUtil.toPageData( alarmCommentRepository.findAllByAlarmId(id.getId(), DaoUtil.toPageable(pageLink))); } @Override public AlarmComment findAlarmCommentById(TenantId tenantId, UUID key) { + log.trace("Try to find alarm comment by id using [{}]", key); return DaoUtil.getData(alarmCommentRepository.findById(key)); } @Override public ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, UUID key) { + log.trace("Try to find alarm comment by id using [{}]", key); return findByIdAsync(tenantId, key); } From 5ba574af36ef80572e2c86bcf880ad0cd1e5acf0 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 20 Dec 2022 15:42:41 +0200 Subject: [PATCH 09/43] fixed pull request comments --- .../java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java | 2 ++ .../thingsboard/server/dao/alarm/BaseAlarmCommentService.java | 3 +++ .../java/org/thingsboard/server/dao/model/ModelConstants.java | 1 - 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java index 04f2674d39..ff4c77bf7f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java @@ -28,7 +28,9 @@ import org.thingsboard.server.dao.Dao; import java.util.UUID; public interface AlarmCommentDao extends Dao { + AlarmComment createAlarmComment(TenantId tenantId, AlarmComment alarmComment); + void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); AlarmComment findAlarmCommentById(TenantId tenantId, UUID key); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 1de9080a00..766cac8fbe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -48,10 +48,13 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al @Autowired private AlarmCommentDao alarmCommentDao; + @Autowired private UserService userService; + @Autowired private DataValidator alarmCommentDataValidator; + @Override public AlarmCommentOperationResult createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment) { alarmCommentDataValidator.validate(alarmComment, tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index bd462eb6b6..fc5c663d7c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -305,7 +305,6 @@ public class ModelConstants { public static final String ALARM_COMMENT_TYPE = "type"; public static final String ALARM_COMMENT_COMMENT = "comment"; - /** * Cassandra entity relation constants. */ From c81e442b35523d1d46e0e69eb33683b360b72acd Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 20 Dec 2022 18:05:33 +0200 Subject: [PATCH 10/43] fixed NPE --- .../server/dao/model/sql/AbstractAlarmCommentEntity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java index 089ba0709a..c8651b86c8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java @@ -89,7 +89,9 @@ public abstract class AbstractAlarmCommentEntity extends AlarmComment alarmComment = new AlarmComment(new AlarmCommentId(id)); alarmComment.setCreatedTime(createdTime); alarmComment.setAlarmId(new AlarmId(alarmId)); - alarmComment.setUserId(new UserId(userId)); + if (userId != null) { + alarmComment.setUserId(new UserId(userId)); + } alarmComment.setType(type); alarmComment.setComment(comment); return alarmComment; From 2db28e2296787cd2de6202d88e07dafabe87eb8b Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 21 Dec 2022 13:41:42 +0200 Subject: [PATCH 11/43] fixed test --- .../thingsboard/server/dao/alarm/AlarmCommentService.java | 2 +- .../server/dao/service/BaseAlarmCommentServiceTest.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java index 04eac2cc15..4759e2c9f3 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -29,7 +29,7 @@ public interface AlarmCommentService { AlarmCommentOperationResult deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); - PageDatafindAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink); + PageData findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink); ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java index ccdbd08e98..7d9b258ba6 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java @@ -64,6 +64,8 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { user.setAuthority(Authority.TENANT_ADMIN); user.setTenantId(tenantId); user.setEmail("tenant@thingsboard.org"); + user.setFirstName("John"); + user.setLastName("Brown"); user = userService.saveUser(user); } @@ -98,7 +100,7 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { PageData alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)); Assert.assertNotNull(alarmComments.getData()); Assert.assertEquals(1, alarmComments.getData().size()); - Assert.assertEquals(createdComment, alarmComments.getData().get(0)); + Assert.assertEquals(createdComment, new AlarmComment(alarmComments.getData().get(0))); } @Test @@ -134,7 +136,7 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { PageData alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)); Assert.assertNotNull(alarmComments.getData()); Assert.assertEquals(1, alarmComments.getData().size()); - Assert.assertEquals(new AlarmCommentInfo(updatedComment), alarmComments.getData().get(0)); + Assert.assertEquals(updatedComment, new AlarmComment(alarmComments.getData().get(0))); } @Test From 408afb67f33977449f9bb9e6d1b7c9f141a4efc0 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 21 Dec 2022 16:10:34 +0200 Subject: [PATCH 12/43] fixed test --- .../server/dao/alarm/AlarmCommentService.java | 2 ++ .../server/dao/alarm/BaseAlarmCommentService.java | 7 +++++++ .../rule/engine/util/TenantIdLoader.java | 6 ++++++ .../rule/engine/util/TenantIdLoaderTest.java | 13 +++++++++++++ 4 files changed, 28 insertions(+) diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java index 4759e2c9f3..f9274f9a87 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -33,4 +33,6 @@ public interface AlarmCommentService { ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId); + AlarmComment findAlarmCommentById(TenantId tenantId, AlarmCommentId alarmCommentId); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 766cac8fbe..96ecf8cf96 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -86,6 +86,13 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al return alarmCommentDao.findAlarmCommentByIdAsync(tenantId, alarmCommentId.getId()); } + @Override + public AlarmComment findAlarmCommentById(TenantId tenantId, AlarmCommentId alarmCommentId) { + log.trace("Executing findAlarmCommentByIdAsync by alarmCommentId [{}]", alarmCommentId); + validateId(alarmCommentId, "Incorrect alarmCommentId " + alarmCommentId); + return alarmCommentDao.findById(tenantId, alarmCommentId.getId()); + } + private AlarmCommentOperationResult createAlarmComment(TenantId tenantId, AlarmComment alarmComment) { log.debug("New Alarm comment : {}", alarmComment); if (alarmComment.getType() == null) { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java index b687246789..344e35084d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java @@ -18,6 +18,8 @@ package org.thingsboard.rule.engine.util; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.HasTenantId; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.ApiUsageStateId; import org.thingsboard.server.common.data.id.AssetId; @@ -69,6 +71,10 @@ public class TenantIdLoader { case ALARM: tenantEntity = ctx.getAlarmService().findAlarmById(ctxTenantId, new AlarmId(id)); break; + case ALARM_COMMENT: + AlarmComment alarmComment = ctx.getAlarmCommentService().findAlarmCommentById(ctxTenantId, new AlarmCommentId(id)); + tenantEntity = ctx.getAlarmService().findAlarmById(ctxTenantId, new AlarmId(alarmComment.getAlarmId().getId())); + break; case RULE_CHAIN: tenantEntity = ctx.getRuleChainService().findRuleChainById(ctxTenantId, new RuleChainId(id)); break; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java index 8a53148204..4990439e60 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java @@ -41,9 +41,11 @@ import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.EntityId; @@ -56,6 +58,7 @@ import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleNode; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetsBundle; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.dashboard.DashboardService; @@ -93,6 +96,8 @@ public class TenantIdLoaderTest { @Mock private RuleEngineAlarmService alarmService; @Mock + private AlarmCommentService alarmCommentService; + @Mock private RuleChainService ruleChainService; @Mock private EntityViewService entityViewService; @@ -190,6 +195,14 @@ public class TenantIdLoaderTest { when(ctx.getAlarmService()).thenReturn(alarmService); doReturn(alarm).when(alarmService).findAlarmById(eq(tenantId), any()); + break; + case ALARM_COMMENT: + AlarmComment alarmComment = new AlarmComment(); + alarmComment.setAlarmId(new AlarmId(UUID.randomUUID())); + + when(ctx.getAlarmCommentService()).thenReturn(alarmCommentService); + doReturn(alarmComment).when(alarmCommentService).findAlarmCommentById(eq(tenantId), any()); + break; case RULE_CHAIN: RuleChain ruleChain = new RuleChain(); From 419380712e8a46b0c8bb33d023113cd9000b18d8 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 22 Dec 2022 12:37:48 +0200 Subject: [PATCH 13/43] fixed security test --- .../controller/AlarmCommentController.java | 7 ++++-- .../BaseAlarmCommentControllerTest.java | 23 ++++--------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index db8853122b..b884d5ab6a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService; import org.thingsboard.server.service.security.permission.Operation; +import org.thingsboard.server.service.security.permission.Resource; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_SORT_PROPERTY_ALLOWABLE_VALUES; @@ -88,7 +89,7 @@ public class AlarmCommentController extends BaseController { public Boolean deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); + Alarm alarm = checkAlarmId(alarmId, Operation.DELETE); AlarmCommentId alarmCommentId = new AlarmCommentId(toUUID(strCommentId)); AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId); @@ -115,7 +116,9 @@ public class AlarmCommentController extends BaseController { ) throws Exception { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); + Alarm alarm = alarmService.findAlarmByIdAsync(getCurrentUser().getTenantId(), alarmId).get(); + checkNotNull(alarm, "Alarm with id [" + alarmId + "] is not found"); + checkEntityId(alarm.getOriginator(), Operation.READ); PageLink pageLink = createPageLink(pageSize, page, null, sortProperty, sortOrder); return checkNotNull(alarmCommentService.findAlarmComments(alarm.getTenantId(), alarmId, pageLink)); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java index 5fe3673154..087c77b391 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java @@ -137,8 +137,8 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText()); Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn")); - testNotifyEntityAllOneTime(updatedAlarmComment, updatedAlarmComment.getId(), updatedAlarmComment.getId(), - tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.UPDATED); + testLogEntityAction(updatedAlarmComment, updatedAlarmComment.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.UPDATED, 1); + testPushMsgToRuleEngineTime(updatedAlarmComment.getId(), tenantId, updatedAlarmComment, 1); } @Test @@ -157,8 +157,8 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText()); Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn")); - testNotifyEntityAllOneTime(updatedAlarmComment, updatedAlarmComment.getId(), updatedAlarmComment.getId(), - tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.UPDATED); + testLogEntityAction(updatedAlarmComment, updatedAlarmComment.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.UPDATED, 1); + testPushMsgToRuleEngineTime(updatedAlarmComment.getId(), tenantId, updatedAlarmComment, 1); } @Test @@ -257,21 +257,6 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT testNotifyEntityNever(alarm.getId(), alarm); } - @Test - public void testClearAlarmViaCustomer() throws Exception { - loginCustomerUser(); - AlarmComment alarmComment = createAlarmComment(alarm.getId()); - - Mockito.reset(tbClusterService, auditLogService); - - doPost("/api/alarm/" + alarm.getId() + "/clear").andExpect(status().isOk()); - - Alarm foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class); - Assert.assertNotNull(foundAlarm); - Assert.assertEquals(AlarmStatus.CLEARED_UNACK, foundAlarm.getStatus()); - - } - @Test public void testFindAlarmCommentsViaCustomerUser() throws Exception { loginCustomerUser(); From c89374e5069c0a174a7e9e32b594566442891e79 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 22 Dec 2022 13:56:45 +0200 Subject: [PATCH 14/43] added ttl service --- .../ttl/AlarmCommentsCleanUpService.java | 62 +++++++++++++++++++ .../src/main/resources/thingsboard.yml | 4 ++ .../alarm/DefaultTbAlarmServiceTest.java | 3 + .../server/dao/alarm/AlarmCommentDao.java | 1 + .../dao/sql/alarm/JpaAlarmCommentDao.java | 8 +++ 5 files changed, 78 insertions(+) create mode 100644 application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java new file mode 100644 index 0000000000..3ea68c90e3 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java @@ -0,0 +1,62 @@ +/** + * 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. + */ +package org.thingsboard.server.service.ttl; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.thingsboard.server.dao.alarm.AlarmCommentDao; +import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; +import org.thingsboard.server.queue.discovery.PartitionService; + +import java.util.concurrent.TimeUnit; + +import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_COLUMN_FAMILY_NAME; + +@Service +@ConditionalOnExpression("${sql.ttl.alarm_comments.enabled:true} && ${sql.ttl.alarm_comments.ttl:0} > 0") +@Slf4j +public class AlarmCommentsCleanUpService extends AbstractCleanUpService { + + private final AlarmCommentDao alarmCommentDao; + private final SqlPartitioningRepository partitioningRepository; + + @Value("${sql.ttl.alarm_comments.ttl:0}") + private long ttlInSec; + @Value("${sql.alarm_comments.partition_size:168}") + private int partitionSizeInHours; + + public AlarmCommentsCleanUpService(PartitionService partitionService, AlarmCommentDao alarmCommentDao, SqlPartitioningRepository partitioningRepository) { + super(partitionService); + this.alarmCommentDao = alarmCommentDao; + this.partitioningRepository = partitioningRepository; + } + + @Scheduled(initialDelayString = "#{T(org.apache.commons.lang3.RandomUtils).nextLong(0, ${sql.ttl.audit_logs.checking_interval_ms})}", + fixedDelayString = "${sql.ttl.audit_logs.checking_interval_ms}") + public void cleanUp() { + long auditLogsExpTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(ttlInSec); + if (isSystemTenantPartitionMine()) { + alarmCommentDao.cleanUpAlarmComments(auditLogsExpTime); + } else { + partitioningRepository.cleanupPartitionsCache(ALARM_COMMENT_COLUMN_FAMILY_NAME, auditLogsExpTime, TimeUnit.HOURS.toMillis(partitionSizeInHours)); + } + } + +} diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index cf42b8681f..bc16437f2c 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -314,6 +314,10 @@ sql: alarms: checking_interval: "${SQL_ALARMS_TTL_CHECKING_INTERVAL:7200000}" # Number of milliseconds. The current value corresponds to two hours removal_batch_size: "${SQL_ALARMS_TTL_REMOVAL_BATCH_SIZE:3000}" # To delete outdated alarms not all at once but in batches + alarms_comments: + enabled: "${SQL_TTL_ALARM_COMMENTS_ENABLED:true}" + ttl: "${SQL_TTL_ALARM_COMMENTS_SECS:0}" # Disabled by default. Accuracy of the cleanup depends on the sql.alarm_comments.partition_size + checking_interval_ms: "${SQL_TTL_ALARM_COMMENTS_CHECKING_INTERVAL_MS:86400000}" # Default value - 1 day rpc: enabled: "${SQL_TTL_RPC_ENABLED:true}" checking_interval: "${SQL_RPC_TTL_CHECKING_INTERVAL:7200000}" # Number of milliseconds. The current value corresponds to two hours diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java index dba6546fc0..0314788065 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.edge.EdgeService; @@ -62,6 +63,8 @@ public class DefaultTbAlarmServiceTest { @MockBean protected AlarmService alarmService; @MockBean + protected AlarmCommentService alarmCommentService; + @MockBean protected AlarmSubscriptionService alarmSubscriptionService; @MockBean protected CustomerService customerService; diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java index ff4c77bf7f..aa1d3913cb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java @@ -39,4 +39,5 @@ public interface AlarmCommentDao extends Dao { ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, UUID key); + void cleanUpAlarmComments(long auditLogsExpTime); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java index f36405ce1c..5691f7a861 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.alarm.AlarmCommentDao; +import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.sql.AlarmCommentEntity; import org.thingsboard.server.dao.sql.JpaAbstractDao; import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; @@ -53,6 +54,8 @@ public class JpaAlarmCommentDao extends JpaAbstractDao getEntityClass() { return AlarmCommentEntity.class; From ae62d2434c71154fdc2736eeb913ddef8bbf70bb Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 23 Dec 2022 11:18:35 +0200 Subject: [PATCH 15/43] updated swagger docs --- .../server/controller/AlarmCommentController.java | 13 ++++++++----- .../server/controller/ControllerConstants.java | 1 + .../service/ttl/AlarmCommentsCleanUpService.java | 10 +++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index b884d5ab6a..4a586027b4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -40,6 +40,8 @@ import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import static org.thingsboard.server.controller.ControllerConstants.ALARM_COMMENT_ID_PARAM_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.ALARM_COMMENT_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; @@ -66,7 +68,8 @@ public class AlarmCommentController extends BaseController { "When creating comment, platform generates Alarm Comment Id as " + UUID_WIKI_LINK + "The newly created Alarm Comment id will be present in the response. Specify existing Alarm Comment id to update the alarm. " + "Referencing non-existing Alarm Comment Id will cause 'Not Found' error. " + - "\nRemove 'id' and optionally 'userId' from the request body example (below) to create new Alarm comment entity. " + + "\n\n To create new Alarm comment entity it is enough to specify 'comment' json element with 'text' node, for example: {\"comment\": { \"text\": \"my comment\"}}. " + + "\n\n If comment type is not specified the default value 'OTHER' will be saved. If 'alarmId' or 'userId' specified in body it will be ignored." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH , produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @@ -81,12 +84,12 @@ public class AlarmCommentController extends BaseController { return tbAlarmCommentService.saveAlarmComment(alarm, alarmComment, getCurrentUser()); } - @ApiOperation(value = "Delete Alarm comment(deleteAlarmComment)", + @ApiOperation(value = "Delete Alarm comment (deleteAlarmComment)", notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment/{commentId}", method = RequestMethod.DELETE) @ResponseBody - public Boolean deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { + public Boolean deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_COMMENT_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.DELETE); @@ -97,7 +100,7 @@ public class AlarmCommentController extends BaseController { } @ApiOperation(value = "Get Alarm comments (getAlarmComments)", - notes = "Returns a page of alarm comments. " + + notes = "Returns a page of alarm comments for specified alarm. " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.GET) @@ -109,7 +112,7 @@ public class AlarmCommentController extends BaseController { @RequestParam int pageSize, @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_SORT_PROPERTY_ALLOWABLE_VALUES) + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_COMMENT_SORT_PROPERTY_ALLOWABLE_VALUES) @RequestParam(required = false) String sortProperty, @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @RequestParam(required = false) String sortOrder diff --git a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java index 5e7622ece5..2deef1e13e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java +++ b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java @@ -102,6 +102,7 @@ public class ControllerConstants { protected static final String ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault"; protected static final String ASSET_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle"; protected static final String ALARM_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, startTs, endTs, type, ackTs, clearTs, severity, status"; + protected static final String ALARM_COMMENT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime"; protected static final String EVENT_SORT_PROPERTY_ALLOWABLE_VALUES = "ts, id"; protected static final String EDGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle"; protected static final String RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, root"; diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java index 3ea68c90e3..1c4c2e700b 100644 --- a/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java +++ b/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java @@ -48,14 +48,14 @@ public class AlarmCommentsCleanUpService extends AbstractCleanUpService { this.partitioningRepository = partitioningRepository; } - @Scheduled(initialDelayString = "#{T(org.apache.commons.lang3.RandomUtils).nextLong(0, ${sql.ttl.audit_logs.checking_interval_ms})}", - fixedDelayString = "${sql.ttl.audit_logs.checking_interval_ms}") + @Scheduled(initialDelayString = "#{T(org.apache.commons.lang3.RandomUtils).nextLong(0, ${sql.ttl.alarm_comments.checking_interval_ms})}", + fixedDelayString = "${sql.ttl.alarm_comments.checking_interval_ms}") public void cleanUp() { - long auditLogsExpTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(ttlInSec); + long commentsExpTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(ttlInSec); if (isSystemTenantPartitionMine()) { - alarmCommentDao.cleanUpAlarmComments(auditLogsExpTime); + alarmCommentDao.cleanUpAlarmComments(commentsExpTime); } else { - partitioningRepository.cleanupPartitionsCache(ALARM_COMMENT_COLUMN_FAMILY_NAME, auditLogsExpTime, TimeUnit.HOURS.toMillis(partitionSizeInHours)); + partitioningRepository.cleanupPartitionsCache(ALARM_COMMENT_COLUMN_FAMILY_NAME, commentsExpTime, TimeUnit.HOURS.toMillis(partitionSizeInHours)); } } From d8ada35182284216e4d7793e811beaf67f9ef0fe Mon Sep 17 00:00:00 2001 From: Tarnavskiy Date: Tue, 27 Dec 2022 12:43:07 +0200 Subject: [PATCH 16/43] Remove dashboard-select component from the DOM-structure when it is hedden --- .../components/dashboard-page/dashboard-page.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html index ca1bae3de7..692d67e292 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html @@ -135,7 +135,7 @@ (click)="openDashboardSettings($event)"> settings - Date: Tue, 27 Dec 2022 15:32:47 +0200 Subject: [PATCH 17/43] Get currentEntity data from stateParams instead doing find-request --- ui-ngx/src/app/core/http/entity.service.ts | 34 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index b66399de6c..2493b11a64 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -869,8 +869,38 @@ export class EntityService { }; aliasInfo.currentEntity = null; if (!aliasInfo.resolveMultiple && aliasInfo.entityFilter) { - return this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, - {ignoreLoading: true, ignoreErrors: true}).pipe( + let entityInfoObservable: Observable; + if (result.stateEntity && aliasInfo.entityFilter.type === AliasFilterType.singleEntity) { + let currentEntity: EntityInfo = null; + if (stateParams) { + if (result.entityParamName && result.entityParamName.length) { + const stateEntity = stateParams[result.entityParamName]; + if (stateEntity) { + currentEntity = { + id: stateEntity.entityId.id, + entityType: stateEntity.entityId.entityType, + name: stateEntity.entityName, + label: stateEntity.entityLabel + }; + } + } else { + if (stateParams.entityId) { + currentEntity = { + id: stateParams.entityId.id, + entityType: stateParams.entityId.entityType as EntityType, + name: stateParams.entityName, + label: stateParams.entityLabel + }; + } + } + } + entityInfoObservable = currentEntity ? of(currentEntity) : this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, + {ignoreLoading: true, ignoreErrors: true}); + } else { + entityInfoObservable = this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, + {ignoreLoading: true, ignoreErrors: true}); + } + return entityInfoObservable.pipe( map((entity) => { aliasInfo.currentEntity = entity; return aliasInfo; From bcb1601e59bf912f0742b47e3bf318d83d117990 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 27 Dec 2022 18:09:34 +0200 Subject: [PATCH 18/43] Set default edge root rule chain during creation --- .../server/service/entitiy/edge/DefaultTbEdgeService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java index 697fe35a42..b3b70a174e 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java @@ -48,6 +48,9 @@ public class DefaultTbEdgeService extends AbstractTbEntityService implements TbE ActionType actionType = edge.getId() == null ? ActionType.ADDED : ActionType.UPDATED; TenantId tenantId = edge.getTenantId(); try { + if (actionType == ActionType.ADDED && edge.getRootRuleChainId() == null) { + edge.setRootRuleChainId(edgeTemplateRootRuleChain.getId()); + } Edge savedEdge = checkNotNull(edgeService.saveEdge(edge)); EdgeId edgeId = savedEdge.getId(); From 51a3620b11ef6fe6dd1baf5e12f934a686fd4f29 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Tue, 27 Dec 2022 18:22:28 +0200 Subject: [PATCH 19/43] Edge sync test - add check for rule chain msg is root --- .../server/controller/BaseEdgeControllerTest.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java index fa466ce93f..9106b5d824 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java @@ -825,26 +825,30 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { assertThat(edgeImitator.waitForMessages()).as("await for messages on first connect").isTrue(); assertThat(edgeImitator.findAllMessagesByType(QueueUpdateMsg.class)).as("one msg during sync process").hasSize(1); - assertThat(edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class)).as("one msg during sync process, another from edge creation").hasSize(2); + List ruleChainUpdateMsgs = edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class); + assertThat(ruleChainUpdateMsgs).as("one msg during sync process, another from edge creation").hasSize(2); assertThat(edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class)).as("one msg during sync process for 'default' device profile").hasSize(3); assertThat(edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class)).as("one msg once device assigned to edge").hasSize(2); assertThat(edgeImitator.findAllMessagesByType(AssetProfileUpdateMsg.class)).as("two msgs during sync process for 'default' and 'test' asset profiles").hasSize(4); assertThat(edgeImitator.findAllMessagesByType(AssetUpdateMsg.class)).as("two msgs - one during sync process, and one more once asset assigned to edge").hasSize(2); assertThat(edgeImitator.findAllMessagesByType(UserUpdateMsg.class)).as("one msg during sync process for tenant admin user").hasSize(1); assertThat(edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class)).as("admin setting update").hasSize(4); + verifyRuleChainMsgsAreRoot(ruleChainUpdateMsgs); edgeImitator.expectMessageAmount(14); doPost("/api/edge/sync/" + edge.getId()); assertThat(edgeImitator.waitForMessages()).as("await for messages after edge sync rest api call").isTrue(); assertThat(edgeImitator.findAllMessagesByType(QueueUpdateMsg.class)).as("queue msg").hasSize(1); - assertThat(edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class)).as("rule chain msg").hasSize(1); + ruleChainUpdateMsgs = edgeImitator.findAllMessagesByType(RuleChainUpdateMsg.class); + assertThat(ruleChainUpdateMsgs).as("rule chain msg").hasSize(1); assertThat(edgeImitator.findAllMessagesByType(DeviceProfileUpdateMsg.class)).as("device profile msg").hasSize(2); assertThat(edgeImitator.findAllMessagesByType(AssetProfileUpdateMsg.class)).as("asset profile msg").hasSize(3); assertThat(edgeImitator.findAllMessagesByType(AssetUpdateMsg.class)).as("asset update msg").hasSize(1); assertThat(edgeImitator.findAllMessagesByType(UserUpdateMsg.class)).as("user update msg").hasSize(1); assertThat(edgeImitator.findAllMessagesByType(AdminSettingsUpdateMsg.class)).as("admin setting update msg").hasSize(4); assertThat(edgeImitator.findAllMessagesByType(DeviceUpdateMsg.class)).as("asset update msg").hasSize(1); + verifyRuleChainMsgsAreRoot(ruleChainUpdateMsgs); edgeImitator.allowIgnoredTypes(); try { @@ -860,6 +864,12 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest { .andExpect(status().isOk()); } + private void verifyRuleChainMsgsAreRoot(List ruleChainUpdateMsgs) { + for (RuleChainUpdateMsg ruleChainUpdateMsg : ruleChainUpdateMsgs) { + Assert.assertTrue(ruleChainUpdateMsg.getRoot()); + } + } + @Test public void testDeleteEdgeWithDeleteRelationsOk() throws Exception { EdgeId edgeId = savedEdge("Edge for Test WithRelationsOk").getId(); From 2b0fa4c47850036abddec2e0e59b7cf74191478a Mon Sep 17 00:00:00 2001 From: Tarnavskiy Date: Tue, 27 Dec 2022 19:16:23 +0200 Subject: [PATCH 20/43] Solved issue of a re-init Widget-Component service and widgets-info Cache. --- .../dashboard-page.component.ts | 6 +++- .../home/components/home-components.module.ts | 2 -- .../widget/widget-component.service.ts | 31 +++++++++++-------- .../components/widget/widget.component.ts | 7 +++-- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index 04cc676d95..b9ce6e977b 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -30,6 +30,7 @@ import { Optional, Renderer2, StaticProvider, + Type, ViewChild, ViewContainerRef, ViewEncapsulation @@ -148,6 +149,7 @@ import { TbPopoverService } from '@shared/components/popover.service'; import { tap } from 'rxjs/operators'; import { LayoutFixedSize, LayoutWidthType } from '@home/components/dashboard-page/layout/layout.models'; import { TbPopoverComponent } from '@shared/components/popover.component'; +import { HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens'; // @dynamic @Component({ @@ -331,6 +333,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC constructor(protected store: Store, @Inject(WINDOW) private window: Window, @Inject(DOCUMENT) private document: Document, + @Inject(HOME_COMPONENTS_MODULE_TOKEN) private homeComponentsModule: Type, private breakpointObserver: BreakpointObserver, private route: ActivatedRoute, private router: Router, @@ -1112,7 +1115,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC addWidgetFromType(widget: WidgetInfo) { this.onAddWidgetClosed(); this.searchBundle = ''; - this.widgetComponentService.getWidgetInfo(widget.bundleAlias, widget.typeAlias, widget.isSystemType).subscribe( + this.widgetComponentService.getWidgetInfo(widget.bundleAlias, widget.typeAlias, widget.isSystemType, + [this.homeComponentsModule]).subscribe( (widgetTypeInfo) => { const config: WidgetConfig = JSON.parse(widgetTypeInfo.defaultConfig); config.title = 'New ' + widgetTypeInfo.widgetName; diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index 7cfcf269de..669fde14ff 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -35,7 +35,6 @@ import { AddAttributeDialogComponent } from '@home/components/attribute/add-attr import { EditAttributeValuePanelComponent } from '@home/components/attribute/edit-attribute-value-panel.component'; import { DashboardComponent } from '@home/components/dashboard/dashboard.component'; import { WidgetComponent } from '@home/components/widget/widget.component'; -import { WidgetComponentService } from '@home/components/widget/widget-component.service'; import { LegendComponent } from '@home/components/widget/legend.component'; import { AliasesEntitySelectPanelComponent } from '@home/components/alias/aliases-entity-select-panel.component'; import { AliasesEntitySelectComponent } from '@home/components/alias/aliases-entity-select.component'; @@ -456,7 +455,6 @@ import { AssetProfileAutocompleteComponent } from '@home/components/profile/asse RateLimitsDetailsDialogComponent ], providers: [ - WidgetComponentService, CustomDialogService, ImportExportService, {provide: EMBED_DASHBOARD_DIALOG_TOKEN, useValue: EmbedDashboardDialogComponent}, diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index 38b14fe485..9a4f941211 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -45,13 +45,13 @@ import { MODULES_MAP } from '@shared/public-api'; import * as tinycolor_ from 'tinycolor2'; import moment from 'moment'; import { IModulesMap } from '@modules/common/modules-map.models'; -import { HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens'; import { widgetSettingsComponentsMap } from '@home/components/widget/lib/settings/widget-settings.module'; const tinycolor = tinycolor_; -// @dynamic -@Injectable() +@Injectable({ + providedIn: 'root' +}) export class WidgetComponentService { private cssParser = new cssjs(); @@ -68,7 +68,6 @@ export class WidgetComponentService { constructor(@Inject(WINDOW) private window: Window, @Optional() @Inject(MODULES_MAP) private modulesMap: IModulesMap, - @Inject(HOME_COMPONENTS_MODULE_TOKEN) private homeComponentsModule: Type, private dynamicComponentFactoryService: DynamicComponentFactoryService, private widgetService: WidgetService, private utils: UtilsService, @@ -185,9 +184,9 @@ export class WidgetComponentService { () => { const loadDefaultWidgetInfoTasks = [ this.loadWidgetResources(this.missingWidgetType, 'global-widget-missing-type', - [SharedModule, WidgetComponentsModule, this.homeComponentsModule]), + [SharedModule, WidgetComponentsModule]), this.loadWidgetResources(this.errorWidgetType, 'global-widget-error-type', - [SharedModule, WidgetComponentsModule, this.homeComponentsModule]), + [SharedModule, WidgetComponentsModule]), ]; forkJoin(loadDefaultWidgetInfoTasks).subscribe( () => { @@ -231,13 +230,14 @@ export class WidgetComponentService { } } - public getWidgetInfo(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): Observable { + public getWidgetInfo(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean, modules?: Type[]): Observable { return this.init().pipe( - mergeMap(() => this.getWidgetInfoInternal(bundleAlias, widgetTypeAlias, isSystem)) + mergeMap(() => this.getWidgetInfoInternal(bundleAlias, widgetTypeAlias, isSystem, modules)) ); } - private getWidgetInfoInternal(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): Observable { + private getWidgetInfoInternal(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean, + modules?: Type[]): Observable { const widgetInfoSubject = new ReplaySubject(); const widgetInfo = this.getWidgetInfoFromCache(bundleAlias, widgetTypeAlias, isSystem); if (widgetInfo) { @@ -245,7 +245,7 @@ export class WidgetComponentService { widgetInfoSubject.complete(); } else { if (this.utils.widgetEditMode) { - this.loadWidget(this.editingWidgetType, bundleAlias, isSystem, widgetInfoSubject); + this.loadWidget(this.editingWidgetType, bundleAlias, isSystem, widgetInfoSubject, modules); } else { const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); let fetchQueue = this.widgetsInfoFetchQueue.get(key); @@ -256,7 +256,7 @@ export class WidgetComponentService { this.widgetsInfoFetchQueue.set(key, fetchQueue); this.widgetService.getWidgetType(bundleAlias, widgetTypeAlias, isSystem, {ignoreErrors: true}).subscribe( (widgetType) => { - this.loadWidget(widgetType, bundleAlias, isSystem, widgetInfoSubject); + this.loadWidget(widgetType, bundleAlias, isSystem, widgetInfoSubject, modules); }, () => { widgetInfoSubject.next(this.missingWidgetType); @@ -270,7 +270,8 @@ export class WidgetComponentService { return widgetInfoSubject.asObservable(); } - private loadWidget(widgetType: WidgetType, bundleAlias: string, isSystem: boolean, widgetInfoSubject: Subject) { + private loadWidget(widgetType: WidgetType, bundleAlias: string, isSystem: boolean, widgetInfoSubject: Subject, + modules?: Type[]) { const widgetInfo = toWidgetInfo(widgetType); const key = this.createWidgetInfoCacheKey(bundleAlias, widgetInfo.alias, isSystem); let widgetControllerDescriptor: WidgetControllerDescriptor = null; @@ -283,7 +284,11 @@ export class WidgetComponentService { } if (widgetControllerDescriptor) { const widgetNamespace = `widget-type-${(isSystem ? 'sys-' : '')}${bundleAlias}-${widgetInfo.alias}`; - this.loadWidgetResources(widgetInfo, widgetNamespace, [SharedModule, WidgetComponentsModule, this.homeComponentsModule]).subscribe( + const widgetModules = [SharedModule, WidgetComponentsModule]; + if (modules) { + widgetModules.push(...modules); + } + this.loadWidgetResources(widgetInfo, widgetNamespace, widgetModules).subscribe( () => { if (widgetControllerDescriptor.settingsSchema) { widgetInfo.typeSettingsSchema = widgetControllerDescriptor.settingsSchema; diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index baa0664a31..cfb95ef97a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -31,6 +31,7 @@ import { OnInit, Renderer2, SimpleChanges, + Type, ViewChild, ViewContainerRef, ViewEncapsulation @@ -114,7 +115,7 @@ import { MobileService } from '@core/services/mobile.service'; import { DialogService } from '@core/services/dialog.service'; import { PopoverPlacement } from '@shared/components/popover.models'; import { TbPopoverService } from '@shared/components/popover.service'; -import { DASHBOARD_PAGE_COMPONENT_TOKEN } from '@home/components/tokens'; +import { DASHBOARD_PAGE_COMPONENT_TOKEN, HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens'; @Component({ selector: 'tb-widget', @@ -190,6 +191,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI private popoverService: TbPopoverService, @Inject(EMBED_DASHBOARD_DIALOG_TOKEN) private embedDashboardDialogComponent: ComponentType, @Inject(DASHBOARD_PAGE_COMPONENT_TOKEN) private dashboardPageComponent: ComponentType, + @Inject(HOME_COMPONENTS_MODULE_TOKEN) private homeComponentsModule: Type, private widgetService: WidgetService, private resources: ResourcesService, private timeService: TimeService, @@ -354,7 +356,8 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI this.subscriptionContext.widgetUtils = this.widgetContext.utils; this.subscriptionContext.getServerTimeDiff = this.dashboardService.getServerTimeDiff.bind(this.dashboardService); - this.widgetComponentService.getWidgetInfo(this.widget.bundleAlias, this.widget.typeAlias, this.widget.isSystemType).subscribe( + this.widgetComponentService.getWidgetInfo(this.widget.bundleAlias, this.widget.typeAlias, this.widget.isSystemType, + [this.homeComponentsModule]).subscribe( (widgetInfo) => { this.widgetInfo = widgetInfo; this.loadFromWidgetInfo(); From 16eb835d46708c97a1a506f3acb9bc8f51bb13c8 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 28 Dec 2022 12:22:04 +0200 Subject: [PATCH 21/43] UI: Fixed incorrect calculate width when used right layout dashboard --- .../dashboard-page.component.html | 10 +-- .../dashboard-page.component.ts | 66 +++++++++++++------ 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html index ca1bae3de7..5fcce69f76 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html @@ -168,9 +168,9 @@ [ngClass]="{ 'tb-shrinked' : isEditingWidget }"> + [ngStyle]="{width: mainLayoutSize.width, + height: mainLayoutSize.height}"> this.dashboard, @@ -402,6 +409,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC .observe(MediaBreakpoints['gt-sm']) .subscribe((state: BreakpointState) => { this.isMobile = !state.matches; + this.updateLayoutSizes(); } )); if (this.isMobileApp && this.syncStateWithQueryParam) { @@ -414,6 +422,13 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } } + ngAfterViewInit() { + this.dashboardResize$ = new ResizeObserver(() => { + this.updateLayoutSizes(); + }); + this.dashboardResize$.observe(this.dashboardContainer.nativeElement); + } + private init(data: DashboardPageInitData) { this.reset(); @@ -537,6 +552,9 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC subscription.unsubscribe(); }); this.rxSubscriptions.length = 0; + if (this.dashboardResize$) { + this.dashboardResize$.disconnect(); + } } public runChangeDetection() { @@ -672,34 +690,45 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC public toggleLayouts() { this.isRightLayoutOpened = !this.isRightLayoutOpened; this.mobileService.onDashboardRightLayoutChanged(this.isRightLayoutOpened); + this.updateLayoutSizes(); } public openRightLayout() { this.isRightLayoutOpened = true; this.mobileService.onDashboardRightLayoutChanged(this.isRightLayoutOpened); + this.updateLayoutSizes(); } - public mainLayoutWidth(): string { - if (this.isEditingWidget && this.editingLayoutCtx.id === 'main') { - return '100%'; - } else { - return this.layouts.right.show && !this.isMobile ? this.calculateWidth('main') : '100%'; + private updateLayoutSizes() { + if (this.dashboardCtx.state) { + this.updateMainLayoutSize(); + this.updateRightLayoutSize(); } } - public mainLayoutHeight(): string { + private updateMainLayoutSize() { + if (this.isEditingWidget && this.editingLayoutCtx.id === 'main') { + this.mainLayoutSize.width = '100%'; + } else { + this.mainLayoutSize.width = this.layouts.right.show && !this.isMobile ? this.calculateWidth('main') : '100%'; + } if (!this.isEditingWidget || this.editingLayoutCtx.id === 'main') { - return '100%'; + this.mainLayoutSize.height = '100%'; } else { - return '0px'; + this.mainLayoutSize.height = '0px'; } } - public rightLayoutWidth(): string { + private updateRightLayoutSize() { if (this.isEditingWidget && this.editingLayoutCtx.id === 'right') { - return '100%'; + this.rightLayoutSize.width = '100%'; } else { - return this.isMobile ? '100%' : this.calculateWidth('right'); + this.rightLayoutSize.width = this.isMobile ? '100%' : this.calculateWidth('right'); + } + if (!this.isEditingWidget || this.editingLayoutCtx.id === 'right') { + this.rightLayoutSize.height = '100%'; + } else { + this.rightLayoutSize.height = '0px'; } } @@ -743,14 +772,6 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } } - public rightLayoutHeight(): string { - if (!this.isEditingWidget || this.editingLayoutCtx.id === 'right') { - return '100%'; - } else { - return '0px'; - } - } - public isPublicUser(): boolean { return this.authUser.isPublic; } @@ -977,6 +998,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC layout.layoutCtx.ctrl.reload(); } layout.layoutCtx.ignoreLoading = true; + this.updateLayoutSizes(); } private setEditMode(isEdit: boolean, revert: boolean) { @@ -1191,6 +1213,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC this.editingLayoutCtx = null; this.editingWidgetSubtitle = null; this.isEditingWidget = false; + this.updateLayoutSizes(); this.resetHighlight(); this.forceDashboardMobileMode = false; } @@ -1216,6 +1239,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC this.editingWidgetSubtitle = this.widgetComponentService.getInstantWidgetInfo(this.editingWidget).widgetName; this.forceDashboardMobileMode = true; this.isEditingWidget = true; + this.updateLayoutSizes(); if (layoutCtx) { const delayOffset = transition ? 350 : 0; const delay = transition ? 400 : 300; From 59df8e7942109af83f2076bc4d727d069d675a25 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 28 Dec 2022 12:38:20 +0200 Subject: [PATCH 22/43] UI: Fixed import --- .../home/components/dashboard-page/dashboard-page.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index a6dd046ade..4db291424b 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -150,6 +150,7 @@ import { TbPopoverService } from '@shared/components/popover.service'; import { tap } from 'rxjs/operators'; import { LayoutFixedSize, LayoutWidthType } from '@home/components/dashboard-page/layout/layout.models'; import { TbPopoverComponent } from '@shared/components/popover.component'; +import { ResizeObserver } from '@juggle/resize-observer'; // @dynamic @Component({ From 85557231a8ed5480fe1cd93a7541ce49084cccdb Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 28 Dec 2022 13:04:49 +0200 Subject: [PATCH 23/43] UI: Optimize call calculate new layout resize --- .../dashboard-page.component.ts | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index 4db291424b..b0984a65fb 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -691,23 +691,28 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC public toggleLayouts() { this.isRightLayoutOpened = !this.isRightLayoutOpened; this.mobileService.onDashboardRightLayoutChanged(this.isRightLayoutOpened); - this.updateLayoutSizes(); } public openRightLayout() { this.isRightLayoutOpened = true; this.mobileService.onDashboardRightLayoutChanged(this.isRightLayoutOpened); - this.updateLayoutSizes(); } private updateLayoutSizes() { + let changeMainLayoutSize = false; + let changeRightLayoutSize = false; if (this.dashboardCtx.state) { - this.updateMainLayoutSize(); - this.updateRightLayoutSize(); + changeMainLayoutSize = this.updateMainLayoutSize(); + changeRightLayoutSize = this.updateRightLayoutSize(); + } + if (changeMainLayoutSize || changeRightLayoutSize) { + this.cd.markForCheck(); } } - private updateMainLayoutSize() { + private updateMainLayoutSize(): boolean { + const prevMainLayoutWidth = this.mainLayoutSize.width; + const prevMainLayoutHeight = this.mainLayoutSize.height; if (this.isEditingWidget && this.editingLayoutCtx.id === 'main') { this.mainLayoutSize.width = '100%'; } else { @@ -718,9 +723,12 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } else { this.mainLayoutSize.height = '0px'; } + return prevMainLayoutWidth !== this.mainLayoutSize.width || prevMainLayoutHeight !== this.mainLayoutSize.height; } - private updateRightLayoutSize() { + private updateRightLayoutSize(): boolean { + const prevRightLayoutWidth = this.rightLayoutSize.width; + const prevRightLayoutHeight = this.rightLayoutSize.height; if (this.isEditingWidget && this.editingLayoutCtx.id === 'right') { this.rightLayoutSize.width = '100%'; } else { @@ -731,6 +739,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC } else { this.rightLayoutSize.height = '0px'; } + return prevRightLayoutWidth !== this.rightLayoutSize.width || prevRightLayoutHeight !== this.rightLayoutSize.height; } private calculateWidth(layout: DashboardLayoutId): string { From f65397618b4a884fade0143217fffd89f66c2402 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 28 Dec 2022 13:27:32 +0200 Subject: [PATCH 24/43] UI: Improve resolve alias function --- ui-ngx/src/app/core/http/entity.service.ts | 38 ++++++++-------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index 2493b11a64..035381af69 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -869,37 +869,25 @@ export class EntityService { }; aliasInfo.currentEntity = null; if (!aliasInfo.resolveMultiple && aliasInfo.entityFilter) { - let entityInfoObservable: Observable; + let currentEntity: EntityInfo = null; if (result.stateEntity && aliasInfo.entityFilter.type === AliasFilterType.singleEntity) { - let currentEntity: EntityInfo = null; if (stateParams) { + let targetParams = stateParams; if (result.entityParamName && result.entityParamName.length) { - const stateEntity = stateParams[result.entityParamName]; - if (stateEntity) { - currentEntity = { - id: stateEntity.entityId.id, - entityType: stateEntity.entityId.entityType, - name: stateEntity.entityName, - label: stateEntity.entityLabel - }; - } - } else { - if (stateParams.entityId) { - currentEntity = { - id: stateParams.entityId.id, - entityType: stateParams.entityId.entityType as EntityType, - name: stateParams.entityName, - label: stateParams.entityLabel - }; - } + targetParams = stateParams[result.entityParamName]; + } + if (targetParams && targetParams.entityId) { + currentEntity = { + id: targetParams.entityId.id, + entityType: targetParams.entityId.entityType as EntityType, + name: targetParams.entityName, + label: targetParams.entityLabel + }; } } - entityInfoObservable = currentEntity ? of(currentEntity) : this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, - {ignoreLoading: true, ignoreErrors: true}); - } else { - entityInfoObservable = this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, - {ignoreLoading: true, ignoreErrors: true}); } + const entityInfoObservable = currentEntity ? of(currentEntity) : this.findSingleEntityInfoByEntityFilter(aliasInfo.entityFilter, + {ignoreLoading: true, ignoreErrors: true}); return entityInfoObservable.pipe( map((entity) => { aliasInfo.currentEntity = entity; From 4c3154da4b53b0f984ec865b8df7b9e0ce54eb38 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 28 Dec 2022 13:33:57 +0200 Subject: [PATCH 25/43] Version set to 3.4.4-SNAPSHOT --- application/pom.xml | 2 +- common/actor/pom.xml | 2 +- common/cache/pom.xml | 2 +- common/cluster-api/pom.xml | 2 +- common/coap-server/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/script/pom.xml | 2 +- common/script/remote-js-client/pom.xml | 2 +- common/script/script-api/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/lwm2m/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/snmp/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- common/version-control/pom.xml | 2 +- dao/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/js-executor/package.json | 2 +- msa/js-executor/pom.xml | 2 +- msa/pom.xml | 2 +- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/lwm2m/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/transport/snmp/pom.xml | 2 +- msa/vc-executor-docker/pom.xml | 2 +- msa/vc-executor/pom.xml | 2 +- msa/web-ui/package.json | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 ++-- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/lwm2m/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- transport/snmp/pom.xml | 2 +- ui-ngx/package.json | 2 +- ui-ngx/pom.xml | 2 +- 56 files changed, 57 insertions(+), 57 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index 61fa75cf49..4d89099d5b 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard application diff --git a/common/actor/pom.xml b/common/actor/pom.xml index 8f2c1e1b13..baab985d07 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/cache/pom.xml b/common/cache/pom.xml index e48d232b16..8c7b3231c2 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index a8dfc522ce..74a89a4c8b 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml index 57bb96d2c2..7d82d8344a 100644 --- a/common/coap-server/pom.xml +++ b/common/coap-server/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index cba811343a..749e704170 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index 9a95c08b65..4d18c99cc6 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index e09de1135f..71fc82184f 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index 5176e4af1a..b52053252b 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index c7b6d86eaf..20847853d7 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index 8485c2d63d..f4a72cc427 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/script/pom.xml b/common/script/pom.xml index a849cf2684..7b22c4e0b0 100644 --- a/common/script/pom.xml +++ b/common/script/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml index 651eb153ed..cc2c129c3f 100644 --- a/common/script/remote-js-client/pom.xml +++ b/common/script/remote-js-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT script org.thingsboard.common.script diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index 01fef3059b..08b6490376 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT script org.thingsboard.common.script diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 2fcac6e059..f20e313725 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index f4089d9a79..20665d1708 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index c6c8f9869d..4da59fc93f 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index 3c6fae874f..724b140d87 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index 9442a66646..fa01fb61ad 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index 47432f47f2..8c017fa757 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml index 939eecb009..fcba445de8 100644 --- a/common/transport/snmp/pom.xml +++ b/common/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 06fbfc5771..1221d42bcf 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index 1a178b4c1e..b38f26abd1 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index 6ff68da760..0843494c49 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 5335492759..563fc6b1e2 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard dao diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index eb7872ef7a..665650df89 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index e094dcc4e5..f9fde3328d 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "3.4.3", + "version": "3.4.4", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 860eb3891a..76edeee65c 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/pom.xml b/msa/pom.xml index 9e628b0f70..2542e0d1d0 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index 7119da74d8..bb53c84a2f 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index fe79951126..b717881833 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 82d7e02da6..80f316318a 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index a596c5000f..a5e2a7d73d 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml index 0a43e7deb5..01a9fc5628 100644 --- a/msa/transport/lwm2m/pom.xml +++ b/msa/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 2fe358fe5d..82856357f6 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index 3339d93577..4df10d1b46 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml index 1a352f47fb..f6cb54dfd2 100644 --- a/msa/transport/snmp/pom.xml +++ b/msa/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.msa transport - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT org.thingsboard.msa.transport diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml index 05884931d3..fbded58c33 100644 --- a/msa/vc-executor-docker/pom.xml +++ b/msa/vc-executor-docker/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml index 31c96c583c..9b6050e029 100644 --- a/msa/vc-executor/pom.xml +++ b/msa/vc-executor/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 035b8a3072..868215ad08 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "3.4.3", + "version": "3.4.4", "description": "ThingsBoard Web UI Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index 5a0a444687..fe94b5bd40 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 99d05fc583..fdc53f6b36 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard netty-mqtt - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 929ebf69f1..df1cf68006 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index 24f8453786..943466a411 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index 126885cd22..fc27ede39e 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 665158a44f..c696866004 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index d32d8163a6..0c92fe9672 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index d414a7a777..de23ae355d 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index 2640d1d80d..64afdbfd66 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index 7820c585ec..4f7ad8cd01 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml index b36c8372ef..e6970f8ac1 100644 --- a/transport/lwm2m/pom.xml +++ b/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 91ce12908b..1dd97ec2ea 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 26af07f6a2..be6eceaec1 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard transport diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml index 0701f7aa57..6f9acc0d7c 100644 --- a/transport/snmp/pom.xml +++ b/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 6b8112adad..3edaefcf35 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "3.4.3", + "version": "3.4.4", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index f78d168144..a2640113e3 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.3-SNAPSHOT + 3.4.4-SNAPSHOT thingsboard org.thingsboard From 2aec503830587684d130e4fbe36f9f4de984beb6 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 28 Dec 2022 14:35:29 +0200 Subject: [PATCH 26/43] Revert "Solved issue of a re-init Widget-Component service and widgets-info Cache." This reverts commit 2b0fa4c4 --- .../dashboard-page.component.ts | 6 +--- .../home/components/home-components.module.ts | 2 ++ .../widget/widget-component.service.ts | 31 ++++++++----------- .../components/widget/widget.component.ts | 7 ++--- 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index fb91752830..b0984a65fb 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -31,7 +31,6 @@ import { Optional, Renderer2, StaticProvider, - Type, ViewChild, ViewContainerRef, ViewEncapsulation @@ -152,7 +151,6 @@ import { tap } from 'rxjs/operators'; import { LayoutFixedSize, LayoutWidthType } from '@home/components/dashboard-page/layout/layout.models'; import { TbPopoverComponent } from '@shared/components/popover.component'; import { ResizeObserver } from '@juggle/resize-observer'; -import { HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens'; // @dynamic @Component({ @@ -341,7 +339,6 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC constructor(protected store: Store, @Inject(WINDOW) private window: Window, @Inject(DOCUMENT) private document: Document, - @Inject(HOME_COMPONENTS_MODULE_TOKEN) private homeComponentsModule: Type, private breakpointObserver: BreakpointObserver, private route: ActivatedRoute, private router: Router, @@ -1147,8 +1144,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC addWidgetFromType(widget: WidgetInfo) { this.onAddWidgetClosed(); this.searchBundle = ''; - this.widgetComponentService.getWidgetInfo(widget.bundleAlias, widget.typeAlias, widget.isSystemType, - [this.homeComponentsModule]).subscribe( + this.widgetComponentService.getWidgetInfo(widget.bundleAlias, widget.typeAlias, widget.isSystemType).subscribe( (widgetTypeInfo) => { const config: WidgetConfig = JSON.parse(widgetTypeInfo.defaultConfig); config.title = 'New ' + widgetTypeInfo.widgetName; diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index 669fde14ff..7cfcf269de 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -35,6 +35,7 @@ import { AddAttributeDialogComponent } from '@home/components/attribute/add-attr import { EditAttributeValuePanelComponent } from '@home/components/attribute/edit-attribute-value-panel.component'; import { DashboardComponent } from '@home/components/dashboard/dashboard.component'; import { WidgetComponent } from '@home/components/widget/widget.component'; +import { WidgetComponentService } from '@home/components/widget/widget-component.service'; import { LegendComponent } from '@home/components/widget/legend.component'; import { AliasesEntitySelectPanelComponent } from '@home/components/alias/aliases-entity-select-panel.component'; import { AliasesEntitySelectComponent } from '@home/components/alias/aliases-entity-select.component'; @@ -455,6 +456,7 @@ import { AssetProfileAutocompleteComponent } from '@home/components/profile/asse RateLimitsDetailsDialogComponent ], providers: [ + WidgetComponentService, CustomDialogService, ImportExportService, {provide: EMBED_DASHBOARD_DIALOG_TOKEN, useValue: EmbedDashboardDialogComponent}, diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index 9a4f941211..38b14fe485 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -45,13 +45,13 @@ import { MODULES_MAP } from '@shared/public-api'; import * as tinycolor_ from 'tinycolor2'; import moment from 'moment'; import { IModulesMap } from '@modules/common/modules-map.models'; +import { HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens'; import { widgetSettingsComponentsMap } from '@home/components/widget/lib/settings/widget-settings.module'; const tinycolor = tinycolor_; -@Injectable({ - providedIn: 'root' -}) +// @dynamic +@Injectable() export class WidgetComponentService { private cssParser = new cssjs(); @@ -68,6 +68,7 @@ export class WidgetComponentService { constructor(@Inject(WINDOW) private window: Window, @Optional() @Inject(MODULES_MAP) private modulesMap: IModulesMap, + @Inject(HOME_COMPONENTS_MODULE_TOKEN) private homeComponentsModule: Type, private dynamicComponentFactoryService: DynamicComponentFactoryService, private widgetService: WidgetService, private utils: UtilsService, @@ -184,9 +185,9 @@ export class WidgetComponentService { () => { const loadDefaultWidgetInfoTasks = [ this.loadWidgetResources(this.missingWidgetType, 'global-widget-missing-type', - [SharedModule, WidgetComponentsModule]), + [SharedModule, WidgetComponentsModule, this.homeComponentsModule]), this.loadWidgetResources(this.errorWidgetType, 'global-widget-error-type', - [SharedModule, WidgetComponentsModule]), + [SharedModule, WidgetComponentsModule, this.homeComponentsModule]), ]; forkJoin(loadDefaultWidgetInfoTasks).subscribe( () => { @@ -230,14 +231,13 @@ export class WidgetComponentService { } } - public getWidgetInfo(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean, modules?: Type[]): Observable { + public getWidgetInfo(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): Observable { return this.init().pipe( - mergeMap(() => this.getWidgetInfoInternal(bundleAlias, widgetTypeAlias, isSystem, modules)) + mergeMap(() => this.getWidgetInfoInternal(bundleAlias, widgetTypeAlias, isSystem)) ); } - private getWidgetInfoInternal(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean, - modules?: Type[]): Observable { + private getWidgetInfoInternal(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): Observable { const widgetInfoSubject = new ReplaySubject(); const widgetInfo = this.getWidgetInfoFromCache(bundleAlias, widgetTypeAlias, isSystem); if (widgetInfo) { @@ -245,7 +245,7 @@ export class WidgetComponentService { widgetInfoSubject.complete(); } else { if (this.utils.widgetEditMode) { - this.loadWidget(this.editingWidgetType, bundleAlias, isSystem, widgetInfoSubject, modules); + this.loadWidget(this.editingWidgetType, bundleAlias, isSystem, widgetInfoSubject); } else { const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); let fetchQueue = this.widgetsInfoFetchQueue.get(key); @@ -256,7 +256,7 @@ export class WidgetComponentService { this.widgetsInfoFetchQueue.set(key, fetchQueue); this.widgetService.getWidgetType(bundleAlias, widgetTypeAlias, isSystem, {ignoreErrors: true}).subscribe( (widgetType) => { - this.loadWidget(widgetType, bundleAlias, isSystem, widgetInfoSubject, modules); + this.loadWidget(widgetType, bundleAlias, isSystem, widgetInfoSubject); }, () => { widgetInfoSubject.next(this.missingWidgetType); @@ -270,8 +270,7 @@ export class WidgetComponentService { return widgetInfoSubject.asObservable(); } - private loadWidget(widgetType: WidgetType, bundleAlias: string, isSystem: boolean, widgetInfoSubject: Subject, - modules?: Type[]) { + private loadWidget(widgetType: WidgetType, bundleAlias: string, isSystem: boolean, widgetInfoSubject: Subject) { const widgetInfo = toWidgetInfo(widgetType); const key = this.createWidgetInfoCacheKey(bundleAlias, widgetInfo.alias, isSystem); let widgetControllerDescriptor: WidgetControllerDescriptor = null; @@ -284,11 +283,7 @@ export class WidgetComponentService { } if (widgetControllerDescriptor) { const widgetNamespace = `widget-type-${(isSystem ? 'sys-' : '')}${bundleAlias}-${widgetInfo.alias}`; - const widgetModules = [SharedModule, WidgetComponentsModule]; - if (modules) { - widgetModules.push(...modules); - } - this.loadWidgetResources(widgetInfo, widgetNamespace, widgetModules).subscribe( + this.loadWidgetResources(widgetInfo, widgetNamespace, [SharedModule, WidgetComponentsModule, this.homeComponentsModule]).subscribe( () => { if (widgetControllerDescriptor.settingsSchema) { widgetInfo.typeSettingsSchema = widgetControllerDescriptor.settingsSchema; diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index cfb95ef97a..baa0664a31 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -31,7 +31,6 @@ import { OnInit, Renderer2, SimpleChanges, - Type, ViewChild, ViewContainerRef, ViewEncapsulation @@ -115,7 +114,7 @@ import { MobileService } from '@core/services/mobile.service'; import { DialogService } from '@core/services/dialog.service'; import { PopoverPlacement } from '@shared/components/popover.models'; import { TbPopoverService } from '@shared/components/popover.service'; -import { DASHBOARD_PAGE_COMPONENT_TOKEN, HOME_COMPONENTS_MODULE_TOKEN } from '@home/components/tokens'; +import { DASHBOARD_PAGE_COMPONENT_TOKEN } from '@home/components/tokens'; @Component({ selector: 'tb-widget', @@ -191,7 +190,6 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI private popoverService: TbPopoverService, @Inject(EMBED_DASHBOARD_DIALOG_TOKEN) private embedDashboardDialogComponent: ComponentType, @Inject(DASHBOARD_PAGE_COMPONENT_TOKEN) private dashboardPageComponent: ComponentType, - @Inject(HOME_COMPONENTS_MODULE_TOKEN) private homeComponentsModule: Type, private widgetService: WidgetService, private resources: ResourcesService, private timeService: TimeService, @@ -356,8 +354,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI this.subscriptionContext.widgetUtils = this.widgetContext.utils; this.subscriptionContext.getServerTimeDiff = this.dashboardService.getServerTimeDiff.bind(this.dashboardService); - this.widgetComponentService.getWidgetInfo(this.widget.bundleAlias, this.widget.typeAlias, this.widget.isSystemType, - [this.homeComponentsModule]).subscribe( + this.widgetComponentService.getWidgetInfo(this.widget.bundleAlias, this.widget.typeAlias, this.widget.isSystemType).subscribe( (widgetInfo) => { this.widgetInfo = widgetInfo; this.loadFromWidgetInfo(); From 572421487ac25ad33d62ad8f61354a46c1468547 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 28 Dec 2022 15:10:09 +0200 Subject: [PATCH 27/43] UI: Move widgets cache to widget service. --- ui-ngx/src/app/core/http/widget.service.ts | 51 +++++++++++++----- .../widget/widget-component.service.ts | 53 +++---------------- 2 files changed, 45 insertions(+), 59 deletions(-) diff --git a/ui-ngx/src/app/core/http/widget.service.ts b/ui-ngx/src/app/core/http/widget.service.ts index 31788122a9..dd9449032e 100644 --- a/ui-ngx/src/app/core/http/widget.service.ts +++ b/ui-ngx/src/app/core/http/widget.service.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; -import { Observable, of, ReplaySubject, Subject } from 'rxjs'; +import { Observable, of, ReplaySubject } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { PageLink } from '@shared/models/page/page-link'; import { PageData } from '@shared/models/page/page-data'; @@ -43,15 +43,14 @@ import { ActivationEnd, Router } from '@angular/router'; }) export class WidgetService { - private widgetTypeUpdatedSubject = new Subject(); - private widgetsBundleDeletedSubject = new Subject(); - private allWidgetsBundles: Array; private systemWidgetsBundles: Array; private tenantWidgetsBundles: Array; private widgetTypeInfosCache = new Map>(); + private widgetsInfoInMemoryCache = new Map(); + private loadWidgetsBundleCacheSubject: ReplaySubject; constructor( @@ -117,7 +116,7 @@ export class WidgetService { defaultHttpOptionsFromConfig(config)).pipe( tap(() => { this.invalidateWidgetsBundleCache(); - this.widgetsBundleDeletedSubject.next(widgetsBundle); + this.widgetsBundleDeleted(widgetsBundle); }) ); } @@ -217,7 +216,7 @@ export class WidgetService { return this.http.post('/api/widgetType', widgetTypeDetails, defaultHttpOptionsFromConfig(config)).pipe( tap((savedWidgetType) => { - this.widgetTypeUpdatedSubject.next(savedWidgetType); + this.widgetTypeUpdated(savedWidgetType); })); } @@ -226,7 +225,7 @@ export class WidgetService { return this.http.post('/api/widgetType', widgetTypeDetails, defaultHttpOptionsFromConfig(config)).pipe( tap((savedWidgetType) => { - this.widgetTypeUpdatedSubject.next(savedWidgetType); + this.widgetTypeUpdated(savedWidgetType); })); } @@ -237,7 +236,7 @@ export class WidgetService { return this.http.delete(`/api/widgetType/${widgetTypeInstance.id.id}`, defaultHttpOptionsFromConfig(config)).pipe( tap(() => { - this.widgetTypeUpdatedSubject.next(widgetTypeInstance); + this.widgetTypeUpdated(widgetTypeInstance); }) ); } @@ -263,12 +262,40 @@ export class WidgetService { ); } - public onWidgetTypeUpdated(): Observable { - return this.widgetTypeUpdatedSubject.asObservable(); + public createWidgetInfoCacheKey(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): string { + return `${isSystem ? 'sys_' : ''}${bundleAlias}_${widgetTypeAlias}`; + } + + public getWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): WidgetInfo | undefined { + const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); + return this.widgetsInfoInMemoryCache.get(key); } - public onWidgetBundleDeleted(): Observable { - return this.widgetsBundleDeletedSubject.asObservable(); + public putWidgetInfoToCache(widgetInfo: WidgetInfo, bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) { + const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); + this.widgetsInfoInMemoryCache.set(key, widgetInfo); + } + + private widgetTypeUpdated(updatedWidgetType: WidgetType): void { + this.deleteWidgetInfoFromCache(updatedWidgetType.bundleAlias, updatedWidgetType.alias, updatedWidgetType.tenantId.id === NULL_UUID); + } + + private widgetsBundleDeleted(widgetsBundle: WidgetsBundle): void { + this.deleteWidgetsBundleFromCache(widgetsBundle.alias, widgetsBundle.tenantId.id === NULL_UUID); + } + + private deleteWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) { + const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); + this.widgetsInfoInMemoryCache.delete(key); + } + + private deleteWidgetsBundleFromCache(bundleAlias: string, isSystem: boolean) { + const key = (isSystem ? 'sys_' : '') + bundleAlias; + this.widgetsInfoInMemoryCache.forEach((widgetInfo, cacheKey) => { + if (cacheKey.startsWith(key)) { + this.widgetsInfoInMemoryCache.delete(cacheKey); + } + }); } private loadWidgetsBundleCache(config?: RequestConfig): Observable { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index 38b14fe485..f8a75239ad 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -50,14 +50,11 @@ import { widgetSettingsComponentsMap } from '@home/components/widget/lib/setting const tinycolor = tinycolor_; -// @dynamic @Injectable() export class WidgetComponentService { private cssParser = new cssjs(); - private widgetsInfoInMemoryCache = new Map(); - private widgetsInfoFetchQueue = new Map>>(); private init$: Observable; @@ -77,14 +74,6 @@ export class WidgetComponentService { this.cssParser.testMode = false; - this.widgetService.onWidgetTypeUpdated().subscribe((widgetType) => { - this.deleteWidgetInfoFromCache(widgetType.bundleAlias, widgetType.alias, widgetType.tenantId.id === NULL_UUID); - }); - - this.widgetService.onWidgetBundleDeleted().subscribe((widgetsBundle) => { - this.deleteWidgetsBundleFromCache(widgetsBundle.alias, widgetsBundle.tenantId.id === NULL_UUID); - }); - this.init(); } @@ -223,7 +212,7 @@ export class WidgetComponentService { } public getInstantWidgetInfo(widget: Widget): WidgetInfo { - const widgetInfo = this.getWidgetInfoFromCache(widget.bundleAlias, widget.typeAlias, widget.isSystemType); + const widgetInfo = this.widgetService.getWidgetInfoFromCache(widget.bundleAlias, widget.typeAlias, widget.isSystemType); if (widgetInfo) { return widgetInfo; } else { @@ -239,7 +228,7 @@ export class WidgetComponentService { private getWidgetInfoInternal(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): Observable { const widgetInfoSubject = new ReplaySubject(); - const widgetInfo = this.getWidgetInfoFromCache(bundleAlias, widgetTypeAlias, isSystem); + const widgetInfo = this.widgetService.getWidgetInfoFromCache(bundleAlias, widgetTypeAlias, isSystem); if (widgetInfo) { widgetInfoSubject.next(widgetInfo); widgetInfoSubject.complete(); @@ -247,7 +236,7 @@ export class WidgetComponentService { if (this.utils.widgetEditMode) { this.loadWidget(this.editingWidgetType, bundleAlias, isSystem, widgetInfoSubject); } else { - const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); + const key = this.widgetService.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); let fetchQueue = this.widgetsInfoFetchQueue.get(key); if (fetchQueue) { fetchQueue.push(widgetInfoSubject); @@ -272,7 +261,7 @@ export class WidgetComponentService { private loadWidget(widgetType: WidgetType, bundleAlias: string, isSystem: boolean, widgetInfoSubject: Subject) { const widgetInfo = toWidgetInfo(widgetType); - const key = this.createWidgetInfoCacheKey(bundleAlias, widgetInfo.alias, isSystem); + const key = this.widgetService.createWidgetInfoCacheKey(bundleAlias, widgetInfo.alias, isSystem); let widgetControllerDescriptor: WidgetControllerDescriptor = null; try { widgetControllerDescriptor = this.createWidgetControllerDescriptor(widgetInfo, key); @@ -297,7 +286,7 @@ export class WidgetComponentService { widgetInfo.typeParameters = widgetControllerDescriptor.typeParameters; widgetInfo.actionSources = widgetControllerDescriptor.actionSources; widgetInfo.widgetTypeFunction = widgetControllerDescriptor.widgetTypeFunction; - this.putWidgetInfoToCache(widgetInfo, bundleAlias, widgetInfo.alias, isSystem); + this.widgetService.putWidgetInfoToCache(widgetInfo, bundleAlias, widgetInfo.alias, isSystem); if (widgetInfoSubject) { widgetInfoSubject.next(widgetInfo); widgetInfoSubject.complete(); @@ -331,7 +320,7 @@ export class WidgetComponentService { (resource) => { resourceTasks.push( this.resources.loadResource(resource.url).pipe( - catchError(e => of(`Failed to load widget resource: '${resource.url}'`)) + catchError(() => of(`Failed to load widget resource: '${resource.url}'`)) ) ); } @@ -586,34 +575,4 @@ export class WidgetComponentService { this.widgetsInfoFetchQueue.delete(key); } } - - // Cache functions - - private createWidgetInfoCacheKey(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): string { - return `${isSystem ? 'sys_' : ''}${bundleAlias}_${widgetTypeAlias}`; - } - - private getWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean): WidgetInfo | undefined { - const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); - return this.widgetsInfoInMemoryCache.get(key); - } - - private putWidgetInfoToCache(widgetInfo: WidgetInfo, bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) { - const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); - this.widgetsInfoInMemoryCache.set(key, widgetInfo); - } - - private deleteWidgetInfoFromCache(bundleAlias: string, widgetTypeAlias: string, isSystem: boolean) { - const key = this.createWidgetInfoCacheKey(bundleAlias, widgetTypeAlias, isSystem); - this.widgetsInfoInMemoryCache.delete(key); - } - - private deleteWidgetsBundleFromCache(bundleAlias: string, isSystem: boolean) { - const key = (isSystem ? 'sys_' : '') + bundleAlias; - this.widgetsInfoInMemoryCache.forEach((widgetInfo, cacheKey) => { - if (cacheKey.startsWith(key)) { - this.widgetsInfoInMemoryCache.delete(cacheKey); - } - }); - } } From 3e65430470cb81ec32c915c7034f293e15fdad8c Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Wed, 28 Dec 2022 16:31:26 +0200 Subject: [PATCH 28/43] UI: Fixed switching dashboard layout --- .../layout/manage-dashboard-layouts-dialog.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts index 4d593a7c57..ae0d699af7 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts @@ -297,6 +297,7 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent Date: Wed, 28 Dec 2022 17:04:33 +0200 Subject: [PATCH 29/43] UI: Refactoring --- .../layout/manage-dashboard-layouts-dialog.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts index ae0d699af7..801238d602 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/layout/manage-dashboard-layouts-dialog.component.ts @@ -297,7 +297,7 @@ export class ManageDashboardLayoutsDialogComponent extends DialogComponent Date: Mon, 9 Jan 2023 13:06:55 +0200 Subject: [PATCH 30/43] Added email for AlarmCommentInfo --- .../server/common/data/alarm/AlarmCommentInfo.java | 6 +++++- .../server/dao/model/sql/AlarmCommentInfoEntity.java | 7 +++++-- .../server/dao/sql/alarm/AlarmCommentRepository.java | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java index dbf603fdbc..66300e4cdb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java @@ -32,6 +32,9 @@ public class AlarmCommentInfo extends AlarmComment { @ApiModelProperty(position = 19, value = "User last name", example = "Brown") private String lastName; + @ApiModelProperty(position = 19, value = "User email address", example = "johnBrown@gmail.com") + private String email; + public AlarmCommentInfo() { super(); } @@ -40,9 +43,10 @@ public class AlarmCommentInfo extends AlarmComment { super(alarmComment); } - public AlarmCommentInfo(AlarmComment alarmComment, String firstName, String lastName) { + public AlarmCommentInfo(AlarmComment alarmComment, String firstName, String lastName, String email) { super(alarmComment); this.firstName = firstName; this.lastName = lastName; + this.email = email; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java index 3bcb49f260..bc9c5841c5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java @@ -29,6 +29,8 @@ public class AlarmCommentInfoEntity extends AbstractAlarmCommentEntity { - @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmCommentInfoEntity(a, u.firstName, u.lastName) FROM AlarmCommentEntity a " + + @Query(value = "SELECT new org.thingsboard.server.dao.model.sql.AlarmCommentInfoEntity(a, u.firstName, u.lastName, u.email) FROM AlarmCommentEntity a " + "LEFT JOIN UserEntity u on u.id = a.userId " + "WHERE a.alarmId = :alarmId ", countQuery = "" + From ed7cd2c25525d2436756eb0d89877caf49ac833f Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 9 Jan 2023 17:53:46 +0200 Subject: [PATCH 31/43] Added Noxss annotations --- .../thingsboard/server/common/data/alarm/AlarmComment.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index 05aecdc7f0..dae96eb0c2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -27,6 +27,8 @@ import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.validation.Length; +import org.thingsboard.server.common.data.validation.NoXss; @ApiModel @Data @@ -38,6 +40,8 @@ public class AlarmComment extends BaseData implements HasName { @ApiModelProperty(position = 4, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private UserId userId; @ApiModelProperty(position = 5, value = "Defines origination of comment", example = "System/Other", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @NoXss + @Length(fieldName = "type") private String type; @ApiModelProperty(position = 6, value = "JSON object with text of comment.", dataType = "com.fasterxml.jackson.databind.JsonNode") private transient JsonNode comment; From 76082c7177ad5b80474ba3429b1f8d949017330a Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Tue, 10 Jan 2023 17:24:26 +0200 Subject: [PATCH 32/43] Version set to 3.5.0-SNAPSHOT --- application/pom.xml | 2 +- common/actor/pom.xml | 2 +- common/cache/pom.xml | 2 +- common/cluster-api/pom.xml | 2 +- common/coap-server/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/script/pom.xml | 2 +- common/script/remote-js-client/pom.xml | 2 +- common/script/script-api/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/lwm2m/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/snmp/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- common/version-control/pom.xml | 2 +- dao/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/js-executor/package.json | 2 +- msa/js-executor/pom.xml | 2 +- msa/pom.xml | 2 +- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/lwm2m/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/transport/snmp/pom.xml | 2 +- msa/vc-executor-docker/pom.xml | 2 +- msa/vc-executor/pom.xml | 2 +- msa/web-ui/package.json | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 ++-- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/lwm2m/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- transport/snmp/pom.xml | 2 +- ui-ngx/package.json | 2 +- ui-ngx/pom.xml | 2 +- 56 files changed, 57 insertions(+), 57 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index 47d69d34dd..815243f85b 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard application diff --git a/common/actor/pom.xml b/common/actor/pom.xml index baab985d07..2b9b91db6c 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/cache/pom.xml b/common/cache/pom.xml index 8c7b3231c2..d26d4ff937 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index 74a89a4c8b..226a274ba0 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml index 7d82d8344a..6e22b45768 100644 --- a/common/coap-server/pom.xml +++ b/common/coap-server/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 749e704170..acf757439f 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index 4d18c99cc6..6464c80471 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index 71fc82184f..daad429299 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index b52053252b..72ea8ae0f3 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index 20847853d7..84ca8fdcb2 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index f4a72cc427..90911569bc 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/script/pom.xml b/common/script/pom.xml index 7b22c4e0b0..0463e2d2e9 100644 --- a/common/script/pom.xml +++ b/common/script/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml index cc2c129c3f..8190cb18d0 100644 --- a/common/script/remote-js-client/pom.xml +++ b/common/script/remote-js-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT script org.thingsboard.common.script diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index 08b6490376..e979207c10 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT script org.thingsboard.common.script diff --git a/common/stats/pom.xml b/common/stats/pom.xml index f20e313725..d72ca8e81c 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index 20665d1708..b1ee7f3774 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index 4da59fc93f..ee2c13d8b5 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index 724b140d87..b6cb46e8cf 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index fa01fb61ad..4f7384bb82 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index 8c017fa757..11cd48b9f1 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml index fcba445de8..a15e7feeef 100644 --- a/common/transport/snmp/pom.xml +++ b/common/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 1221d42bcf..fa1e93ea4c 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index b38f26abd1..13d9c502cf 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index 0843494c49..2ab1f45eec 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 563fc6b1e2..95a337c9c2 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard dao diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index 665650df89..a7889dbe8c 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index f9fde3328d..add59eb610 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "3.4.4", + "version": "3.5.0", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 76edeee65c..226e48a375 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/pom.xml b/msa/pom.xml index 2542e0d1d0..09e890cf10 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index bb53c84a2f..806374f8ba 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index b717881833..4c94013482 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 80f316318a..ceeec9ebce 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index a5e2a7d73d..de388ba261 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml index 01a9fc5628..526dc66605 100644 --- a/msa/transport/lwm2m/pom.xml +++ b/msa/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 82856357f6..1e91823e8d 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index 4df10d1b46..df2b9943a9 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml index f6cb54dfd2..3a60f83568 100644 --- a/msa/transport/snmp/pom.xml +++ b/msa/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.msa transport - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT org.thingsboard.msa.transport diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml index fbded58c33..b1241b330a 100644 --- a/msa/vc-executor-docker/pom.xml +++ b/msa/vc-executor-docker/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml index 9b6050e029..61468af189 100644 --- a/msa/vc-executor/pom.xml +++ b/msa/vc-executor/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 868215ad08..18cc80481f 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "3.4.4", + "version": "3.5.0", "description": "ThingsBoard Web UI Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index fe94b5bd40..4372bbcf0d 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index fdc53f6b36..c246ab7c5c 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard netty-mqtt - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 92f13121d6..991a95d1b6 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index 943466a411..f2b1eca351 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index fc27ede39e..d1f2bacea6 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index c696866004..5016186a5c 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 0c92fe9672..a79134b811 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index de23ae355d..bb9c5f9958 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index 64afdbfd66..a915e0ef1a 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index 4f7ad8cd01..71869bf1b0 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml index e6970f8ac1..bd1bb0500c 100644 --- a/transport/lwm2m/pom.xml +++ b/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 1dd97ec2ea..55d5d04c7c 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index be6eceaec1..318bc794d1 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard transport diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml index 6f9acc0d7c..9aa4039b31 100644 --- a/transport/snmp/pom.xml +++ b/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 3edaefcf35..0758e39948 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "3.4.4", + "version": "3.5.0", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index a2640113e3..6361c082e5 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.4.4-SNAPSHOT + 3.5.0-SNAPSHOT thingsboard org.thingsboard From 0eb51cb17d95b178ce0f0ed44728e07996d87f62 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 11 Jan 2023 17:36:22 +0200 Subject: [PATCH 33/43] Added Noxss, Length validation for alarm comment, deleted ttl service for alarm comments, added comment creation for ack, clear, severity updated events, fixed tests. --- .../controller/AlarmCommentController.java | 6 +- .../server/controller/BaseController.java | 7 ++- .../alarm/DefaultTbAlarmCommentService.java | 6 +- .../entitiy/alarm/DefaultTbAlarmService.java | 14 +++++ .../entitiy/alarm/TbAlarmCommentService.java | 2 +- .../permission/CustomerUserPermissions.java | 1 - .../service/security/permission/Resource.java | 1 - .../permission/TenantAdminPermissions.java | 1 - .../DefaultAlarmSubscriptionService.java | 18 +++++- .../ttl/AlarmCommentsCleanUpService.java | 62 ------------------- .../src/main/resources/thingsboard.yml | 4 -- .../BaseAlarmCommentControllerTest.java | 3 +- .../DefaultTbAlarmCommentServiceTest.java | 6 +- .../alarm/AlarmCommentOperationResult.java | 36 ----------- .../server/dao/alarm/AlarmCommentService.java | 7 ++- .../dao/alarm/AlarmOperationResult.java | 7 ++- .../common/data/alarm/AlarmComment.java | 8 +-- .../common/data/alarm/AlarmCommentType.java | 22 +++++++ .../server/dao/alarm/AlarmCommentDao.java | 2 - .../dao/alarm/BaseAlarmCommentService.java | 44 ++++++------- .../server/dao/alarm/BaseAlarmService.java | 5 +- .../model/sql/AbstractAlarmCommentEntity.java | 7 +-- .../server/dao/service/DataValidator.java | 23 ------- .../dao/service/StringLengthValidator.java | 15 +++-- .../dao/sql/alarm/JpaAlarmCommentDao.java | 7 --- .../resources/sql/schema-entities-idx.sql | 2 +- .../service/BaseAlarmCommentServiceTest.java | 22 ++++--- .../dao/sql/alarm/JpaAlarmCommentDaoTest.java | 9 +-- 28 files changed, 141 insertions(+), 206 deletions(-) delete mode 100644 application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java delete mode 100644 common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentType.java diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index 4a586027b4..b86becd132 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -89,14 +89,14 @@ public class AlarmCommentController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment/{commentId}", method = RequestMethod.DELETE) @ResponseBody - public Boolean deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_COMMENT_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { + public void deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_COMMENT_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.DELETE); AlarmCommentId alarmCommentId = new AlarmCommentId(toUUID(strCommentId)); - AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId); - return tbAlarmCommentService.deleteAlarmComment(alarm, alarmComment, getCurrentUser()); + AlarmComment alarmComment = checkAlarmCommentId(alarmCommentId, alarmId); + tbAlarmCommentService.deleteAlarmComment(alarm, alarmComment, getCurrentUser()); } @ApiOperation(value = "Get Alarm comments (getAlarmComments)", diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index eecf507a90..ed92636e66 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -722,12 +722,15 @@ public abstract class BaseController { } } - AlarmComment checkAlarmCommentId(AlarmCommentId alarmCommentId) throws ThingsboardException { + AlarmComment checkAlarmCommentId(AlarmCommentId alarmCommentId, AlarmId alarmId) throws ThingsboardException { try { validateId(alarmCommentId, "Incorrect alarmCommentId " + alarmCommentId); AlarmComment alarmComment = alarmCommentService.findAlarmCommentByIdAsync(getCurrentUser().getTenantId(), alarmCommentId).get(); checkNotNull(alarmComment, "Alarm comment with id [" + alarmCommentId + "] is not found"); - return alarmComment; + if (!alarmId.equals(alarmComment.getAlarmId())) { + throw new ThingsboardException("Alarm id does not match with comment alarm id", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } + return alarmComment; } catch (Exception e) { throw handleException(e, false); } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java index 5904745088..af8fa287a4 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java @@ -35,7 +35,7 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem UserId userId = user.getId(); alarmComment.setUserId(userId); try { - AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment).getAlarmComment()); + AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment)); notificationEntityService.notifyCreateOrUpdateAlarmComment(alarm, savedAlarmComment, actionType, user); return savedAlarmComment; } catch (Exception e) { @@ -45,8 +45,8 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem } @Override - public Boolean deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { + public void deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { + alarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment.getId()); notificationEntityService.notifyDeleteAlarmComment(alarm, alarmComment, user); - return alarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment.getId()).isSuccessful(); } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java index 8157eff3e5..6a0d00e992 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -24,6 +24,8 @@ import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; @@ -56,6 +58,12 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb long ackTs = System.currentTimeMillis(); ListenableFuture future = alarmSubscriptionService.ackAlarm(alarm.getTenantId(), alarm.getId(), ackTs); return Futures.transform(future, result -> { + AlarmComment alarmComment = AlarmComment.builder() + .alarmId(alarm.getId()) + .type(AlarmCommentType.SYSTEM) + .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was acknowledged by user %s", user.getName()))) + .build(); + alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment); alarm.setAckTs(ackTs); alarm.setStatus(alarm.getStatus().isCleared() ? AlarmStatus.CLEARED_ACK : AlarmStatus.ACTIVE_ACK); notificationEntityService.notifyCreateOrUpdateAlarm(alarm, ActionType.ALARM_ACK, user); @@ -68,6 +76,12 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb long clearTs = System.currentTimeMillis(); ListenableFuture future = alarmSubscriptionService.clearAlarm(alarm.getTenantId(), alarm.getId(), null, clearTs); return Futures.transform(future, result -> { + AlarmComment alarmComment = AlarmComment.builder() + .alarmId(alarm.getId()) + .type(AlarmCommentType.SYSTEM) + .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was cleared by user %s", user.getName()))) + .build(); + alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment); alarm.setClearTs(clearTs); alarm.setStatus(alarm.getStatus().isAck() ? AlarmStatus.CLEARED_ACK : AlarmStatus.CLEARED_UNACK); notificationEntityService.notifyCreateOrUpdateAlarm(alarm, ActionType.ALARM_CLEAR, user); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java index 5c4b868097..74f207138e 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java @@ -24,5 +24,5 @@ import org.thingsboard.server.common.data.id.TenantId; public interface TbAlarmCommentService { AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException; - Boolean deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user); + void deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java index 3c445b7682..cdd84b0478 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/CustomerUserPermissions.java @@ -32,7 +32,6 @@ public class CustomerUserPermissions extends AbstractPermissions { public CustomerUserPermissions() { super(); put(Resource.ALARM, customerAlarmPermissionChecker); - put(Resource.ALARM_COMMENT, customerAlarmPermissionChecker); put(Resource.ASSET, customerEntityPermissionChecker); put(Resource.DEVICE, customerEntityPermissionChecker); put(Resource.CUSTOMER, customerPermissionChecker); diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java index 0979c0969d..a9484a2bd3 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java @@ -22,7 +22,6 @@ import java.util.Optional; public enum Resource { ADMIN_SETTINGS(), ALARM(EntityType.ALARM), - ALARM_COMMENT(EntityType.ALARM_COMMENT), DEVICE(EntityType.DEVICE), ASSET(EntityType.ASSET), CUSTOMER(EntityType.CUSTOMER), diff --git a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java index 7027fda414..ef7991e5de 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java +++ b/application/src/main/java/org/thingsboard/server/service/security/permission/TenantAdminPermissions.java @@ -30,7 +30,6 @@ public class TenantAdminPermissions extends AbstractPermissions { super(); put(Resource.ADMIN_SETTINGS, PermissionChecker.allowAllPermissionChecker); put(Resource.ALARM, tenantEntityPermissionChecker); - put(Resource.ALARM_COMMENT, tenantEntityPermissionChecker); put(Resource.ASSET, tenantEntityPermissionChecker); put(Resource.DEVICE, tenantEntityPermissionChecker); put(Resource.CUSTOMER, tenantEntityPermissionChecker); diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java index 956dde8024..0b6eaf162e 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultAlarmSubscriptionService.java @@ -23,8 +23,11 @@ import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; @@ -41,6 +44,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.stats.TbApiUsageReportClient; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.alarm.AlarmOperationResult; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.gen.transport.TransportProtos; @@ -61,6 +65,7 @@ import java.util.Optional; public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService implements AlarmSubscriptionService { private final AlarmService alarmService; + private final AlarmCommentService alarmCommentService; private final TbApiUsageReportClient apiUsageClient; private final TbApiUsageStateService apiUsageStateService; @@ -68,11 +73,13 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService PartitionService partitionService, AlarmService alarmService, TbApiUsageReportClient apiUsageClient, - TbApiUsageStateService apiUsageStateService) { + TbApiUsageStateService apiUsageStateService, + AlarmCommentService alarmCommentService) { super(clusterService, partitionService); this.alarmService = alarmService; this.apiUsageClient = apiUsageClient; this.apiUsageStateService = apiUsageStateService; + this.alarmCommentService = alarmCommentService; } @Autowired(required = false) @@ -90,6 +97,15 @@ public class DefaultAlarmSubscriptionService extends AbstractSubscriptionService AlarmOperationResult result = alarmService.createOrUpdateAlarm(alarm, apiUsageStateService.getApiUsageState(alarm.getTenantId()).isAlarmCreationEnabled()); if (result.isSuccessful()) { onAlarmUpdated(result); + AlarmSeverity oldSeverity = result.getOldSeverity(); + if (oldSeverity != null && !oldSeverity.equals(result.getAlarm().getSeverity())) { + AlarmComment alarmComment = AlarmComment.builder() + .alarmId(alarm.getId()) + .type(AlarmCommentType.SYSTEM) + .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm severity was updated from %s to %s", oldSeverity, result.getAlarm().getSeverity()))) + .build(); + alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment); + } } if (result.isCreated()) { apiUsageClient.report(alarm.getTenantId(), null, ApiUsageRecordKey.CREATED_ALARMS_COUNT); diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java deleted file mode 100644 index 1c4c2e700b..0000000000 --- a/application/src/main/java/org/thingsboard/server/service/ttl/AlarmCommentsCleanUpService.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * 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. - */ -package org.thingsboard.server.service.ttl; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.thingsboard.server.dao.alarm.AlarmCommentDao; -import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; -import org.thingsboard.server.queue.discovery.PartitionService; - -import java.util.concurrent.TimeUnit; - -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COLUMN_FAMILY_NAME; -import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_COLUMN_FAMILY_NAME; - -@Service -@ConditionalOnExpression("${sql.ttl.alarm_comments.enabled:true} && ${sql.ttl.alarm_comments.ttl:0} > 0") -@Slf4j -public class AlarmCommentsCleanUpService extends AbstractCleanUpService { - - private final AlarmCommentDao alarmCommentDao; - private final SqlPartitioningRepository partitioningRepository; - - @Value("${sql.ttl.alarm_comments.ttl:0}") - private long ttlInSec; - @Value("${sql.alarm_comments.partition_size:168}") - private int partitionSizeInHours; - - public AlarmCommentsCleanUpService(PartitionService partitionService, AlarmCommentDao alarmCommentDao, SqlPartitioningRepository partitioningRepository) { - super(partitionService); - this.alarmCommentDao = alarmCommentDao; - this.partitioningRepository = partitioningRepository; - } - - @Scheduled(initialDelayString = "#{T(org.apache.commons.lang3.RandomUtils).nextLong(0, ${sql.ttl.alarm_comments.checking_interval_ms})}", - fixedDelayString = "${sql.ttl.alarm_comments.checking_interval_ms}") - public void cleanUp() { - long commentsExpTime = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(ttlInSec); - if (isSystemTenantPartitionMine()) { - alarmCommentDao.cleanUpAlarmComments(commentsExpTime); - } else { - partitioningRepository.cleanupPartitionsCache(ALARM_COMMENT_COLUMN_FAMILY_NAME, commentsExpTime, TimeUnit.HOURS.toMillis(partitionSizeInHours)); - } - } - -} diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 9fdd263a74..fb3f2d6e06 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -314,10 +314,6 @@ sql: alarms: checking_interval: "${SQL_ALARMS_TTL_CHECKING_INTERVAL:7200000}" # Number of milliseconds. The current value corresponds to two hours removal_batch_size: "${SQL_ALARMS_TTL_REMOVAL_BATCH_SIZE:3000}" # To delete outdated alarms not all at once but in batches - alarms_comments: - enabled: "${SQL_TTL_ALARM_COMMENTS_ENABLED:true}" - ttl: "${SQL_TTL_ALARM_COMMENTS_SECS:0}" # Disabled by default. Accuracy of the cleanup depends on the sql.alarm_comments.partition_size - checking_interval_ms: "${SQL_TTL_ALARM_COMMENTS_CHECKING_INTERVAL_MS:86400000}" # Default value - 1 day rpc: enabled: "${SQL_TTL_RPC_ENABLED:true}" checking_interval: "${SQL_RPC_TTL_CHECKING_INTERVAL:7200000}" # Number of milliseconds. The current value corresponds to two hours diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java index 087c77b391..4986eacb52 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; +import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.audit.ActionType; @@ -115,7 +116,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT Mockito.reset(tbClusterService, auditLogService); AlarmComment createdComment = createAlarmComment(alarm.getId()); - Assert.assertEquals("OTHER", createdComment.getType()); + Assert.assertEquals(AlarmCommentType.OTHER, createdComment.getType()); testLogEntityAction(createdComment, createdComment.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ADDED, 1); testPushMsgToRuleEngineTime(createdComment.getId(), tenantId, createdComment, 1); diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java index 808af7d2a1..dfc070110f 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; -import org.thingsboard.server.dao.alarm.AlarmCommentOperationResult; import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.customer.CustomerService; @@ -44,6 +43,7 @@ import java.util.UUID; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -77,7 +77,7 @@ public class DefaultTbAlarmCommentServiceTest { public void testSave() throws ThingsboardException { var alarm = new Alarm(); var alarmComment = new AlarmComment(); - when(alarmCommentService.createOrUpdateAlarmComment(Mockito.any(), eq(alarmComment))).thenReturn(new AlarmCommentOperationResult(alarmComment, true)); + when(alarmCommentService.createOrUpdateAlarmComment(Mockito.any(), eq(alarmComment))).thenReturn(alarmComment); service.saveAlarmComment(alarm, alarmComment, new User()); verify(notificationEntityService, times(1)).notifyCreateOrUpdateAlarmComment(any(), any(), any(), any()); @@ -88,7 +88,7 @@ public class DefaultTbAlarmCommentServiceTest { var alarmId = new AlarmId(UUID.randomUUID()); var alarmCommentId = new AlarmCommentId(UUID.randomUUID()); - when(alarmCommentService.deleteAlarmComment(Mockito.any(), eq(alarmCommentId))).thenReturn(new AlarmCommentOperationResult(new AlarmComment(), true)); + doNothing().when(alarmCommentService).deleteAlarmComment(Mockito.any(), eq(alarmCommentId)); service.deleteAlarmComment(new Alarm(alarmId), new AlarmComment(alarmCommentId), new User()); verify(notificationEntityService, times(1)).notifyDeleteAlarmComment(any(), any(), any()); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java deleted file mode 100644 index 3dc25e02ab..0000000000 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentOperationResult.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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. - */ -package org.thingsboard.server.dao.alarm; - -import lombok.Data; -import org.thingsboard.server.common.data.alarm.AlarmComment; - -@Data -public class AlarmCommentOperationResult { - private final AlarmComment alarmComment; - private final boolean successful; - private final boolean created; - - public AlarmCommentOperationResult(AlarmComment alarmComment, boolean successful) { - this(alarmComment, successful, false); - } - - public AlarmCommentOperationResult(AlarmComment alarmComment, boolean successful, boolean created) { - this.alarmComment = alarmComment; - this.successful = successful; - this.created = created; - } -} diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java index f9274f9a87..a60bcbf81d 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -23,11 +23,12 @@ import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.dao.entity.EntityDaoService; -public interface AlarmCommentService { - AlarmCommentOperationResult createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment); +public interface AlarmCommentService extends EntityDaoService { + AlarmComment createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment); - AlarmCommentOperationResult deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); + void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); PageData findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java index 4940c74191..f8eefafac6 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm; import lombok.Data; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.id.EntityId; import java.util.Collections; @@ -27,6 +28,7 @@ public class AlarmOperationResult { private final Alarm alarm; private final boolean successful; private final boolean created; + private final AlarmSeverity oldSeverity; private final List propagatedEntitiesList; public AlarmOperationResult(Alarm alarm, boolean successful) { @@ -34,13 +36,14 @@ public class AlarmOperationResult { } public AlarmOperationResult(Alarm alarm, boolean successful, List propagatedEntitiesList) { - this(alarm, successful, false, propagatedEntitiesList); + this(alarm, successful, false, null, propagatedEntitiesList); } - public AlarmOperationResult(Alarm alarm, boolean successful, boolean created, List propagatedEntitiesList) { + public AlarmOperationResult(Alarm alarm, boolean successful, boolean created, AlarmSeverity oldSeverity, List propagatedEntitiesList) { this.alarm = alarm; this.successful = successful; this.created = created; + this.oldSeverity = oldSeverity; this.propagatedEntitiesList = propagatedEntitiesList; } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index dae96eb0c2..0393c630a9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -39,11 +39,11 @@ public class AlarmComment extends BaseData implements HasName { private EntityId alarmId; @ApiModelProperty(position = 4, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private UserId userId; - @ApiModelProperty(position = 5, value = "Defines origination of comment", example = "System/Other", accessMode = ApiModelProperty.AccessMode.READ_ONLY) - @NoXss - @Length(fieldName = "type") - private String type; + @ApiModelProperty(position = 5, value = "Defines origination of comment. System type means comment was created by TB. OTHER type means comment was created by user.", example = "SYSTEM/OTHER", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private AlarmCommentType type; @ApiModelProperty(position = 6, value = "JSON object with text of comment.", dataType = "com.fasterxml.jackson.databind.JsonNode") + @NoXss + @Length(fieldName = "comment", max = 10000) private transient JsonNode comment; @ApiModelProperty(position = 1, value = "JSON object with the alarm comment Id. " + diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentType.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentType.java new file mode 100644 index 0000000000..e9d4c34105 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentType.java @@ -0,0 +1,22 @@ +/** + * 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. + */ +package org.thingsboard.server.common.data.alarm; + +public enum AlarmCommentType { + + SYSTEM, OTHER; + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java index aa1d3913cb..8db3fbf71f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentDao.java @@ -38,6 +38,4 @@ public interface AlarmCommentDao extends Dao { PageData findAlarmComments(TenantId tenantId, AlarmId id, PageLink pageLink); ListenableFuture findAlarmCommentByIdAsync(TenantId tenantId, UUID key); - - void cleanUpAlarmComments(long auditLogsExpTime); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 96ecf8cf96..c7beaf216e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -18,26 +18,25 @@ package org.thingsboard.server.dao.alarm; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; +import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.service.DataValidator; -import org.thingsboard.server.dao.user.UserService; -import java.util.ArrayList; -import java.util.List; +import java.util.Optional; import java.util.UUID; import static org.thingsboard.server.dao.service.Validator.validateId; @@ -49,15 +48,12 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al @Autowired private AlarmCommentDao alarmCommentDao; - @Autowired - private UserService userService; - @Autowired private DataValidator alarmCommentDataValidator; @Override - public AlarmCommentOperationResult createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment) { - alarmCommentDataValidator.validate(alarmComment, tenantId); + public AlarmComment createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment) { + alarmCommentDataValidator.validate(alarmComment, c -> tenantId); if (alarmComment.getId() == null) { return createAlarmComment(tenantId, alarmComment); } else { @@ -66,11 +62,9 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al } @Override - public AlarmCommentOperationResult deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId) { + public void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId) { log.debug("Deleting Alarm Comment with id: {}", alarmCommentId); - AlarmCommentOperationResult result = new AlarmCommentOperationResult(new AlarmComment(), true); alarmCommentDao.deleteAlarmComment(tenantId, alarmCommentId); - return result; } @Override @@ -93,21 +87,20 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al return alarmCommentDao.findById(tenantId, alarmCommentId.getId()); } - private AlarmCommentOperationResult createAlarmComment(TenantId tenantId, AlarmComment alarmComment) { + private AlarmComment createAlarmComment(TenantId tenantId, AlarmComment alarmComment) { log.debug("New Alarm comment : {}", alarmComment); if (alarmComment.getType() == null) { - alarmComment.setType("OTHER"); + alarmComment.setType(AlarmCommentType.OTHER); } if (alarmComment.getId() == null) { UUID uuid = Uuids.timeBased(); alarmComment.setId(new AlarmCommentId(uuid)); alarmComment.setCreatedTime(Uuids.unixTimestamp(uuid)); } - AlarmComment saved = alarmCommentDao.createAlarmComment(tenantId, alarmComment); - return new AlarmCommentOperationResult(saved, true, true); + return alarmCommentDao.createAlarmComment(tenantId, alarmComment); } - private AlarmCommentOperationResult updateAlarmComment(TenantId tenantId, AlarmComment newAlarmComment) { + private AlarmComment updateAlarmComment(TenantId tenantId, AlarmComment newAlarmComment) { log.debug("Update Alarm comment : {}", newAlarmComment); AlarmComment existing = alarmCommentDao.findAlarmCommentById(tenantId, newAlarmComment.getId().getId()); @@ -119,9 +112,18 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al ((ObjectNode) comment).put("editedOn", Uuids.unixTimestamp(uuid)); existing.setComment(comment); } - AlarmComment result = alarmCommentDao.save(tenantId, existing); - return new AlarmCommentOperationResult(result, true, true); + return alarmCommentDao.save(tenantId, existing); } return null; } + + @Override + public Optional> findEntity(TenantId tenantId, EntityId entityId) { + return Optional.ofNullable(findAlarmCommentById(tenantId, new AlarmCommentId(entityId.getId()))); + } + + @Override + public EntityType getEntityType() { + return EntityType.ALARM_COMMENT; + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java index c76be82956..798a4c08dc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java @@ -165,7 +165,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ log.debug("New Alarm : {}", alarm); Alarm saved = alarmDao.save(alarm.getTenantId(), alarm); List propagatedEntitiesList = createEntityAlarmRecords(saved); - return new AlarmOperationResult(saved, true, true, propagatedEntitiesList); + return new AlarmOperationResult(saved, true, true, null, propagatedEntitiesList); } private List createEntityAlarmRecords(Alarm alarm) throws InterruptedException, ExecutionException { @@ -208,6 +208,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ boolean propagationEnabled = !oldAlarm.isPropagate() && newAlarm.isPropagate(); boolean propagationToOwnerEnabled = !oldAlarm.isPropagateToOwner() && newAlarm.isPropagateToOwner(); boolean propagationToTenantEnabled = !oldAlarm.isPropagateToTenant() && newAlarm.isPropagateToTenant(); + AlarmSeverity oldAlarmSeverity = oldAlarm.getSeverity(); Alarm result = alarmDao.save(newAlarm.getTenantId(), merge(oldAlarm, newAlarm)); List propagatedEntitiesList; if (propagationEnabled || propagationToOwnerEnabled || propagationToTenantEnabled) { @@ -220,7 +221,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ } else { propagatedEntitiesList = new ArrayList<>(getPropagationEntityIds(result)); } - return new AlarmOperationResult(result, true, propagatedEntitiesList); + return new AlarmOperationResult(result, true, false, oldAlarmSeverity, propagatedEntitiesList); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java index c8651b86c8..e81558cac5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java @@ -21,6 +21,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.UserId; @@ -50,7 +51,7 @@ public abstract class AbstractAlarmCommentEntity extends private UUID userId; @Column(name = ALARM_COMMENT_TYPE) - private String type; + private AlarmCommentType type; @Type(type = "json") @Column(name = ALARM_COMMENT_COMMENT) @@ -65,9 +66,7 @@ public abstract class AbstractAlarmCommentEntity extends this.setUuid(alarmComment.getUuidId()); } this.setCreatedTime(alarmComment.getCreatedTime()); - if (alarmComment.getAlarmId() != null) { - this.alarmId = alarmComment.getAlarmId().getId(); - } + this.alarmId = alarmComment.getAlarmId().getId(); if (alarmComment.getUserId() != null) { this.userId = alarmComment.getUserId().getId(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java index 6efe89df4f..beb4a7ebc1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/DataValidator.java @@ -67,29 +67,6 @@ public abstract class DataValidator> { } } - public D validate(D data, TenantId tenantId) { - try { - if (data == null) { - throw new DataValidationException("Data object can't be null!"); - } - - ConstraintValidator.validateFields(data); - - validateDataImpl(tenantId, data); - D old; - if (data.getId() == null) { - validateCreate(tenantId, data); - old = null; - } else { - old = validateUpdate(tenantId, data); - } - return old; - } catch (DataValidationException e) { - log.error("{} object is invalid: [{}]", data == null ? "Data" : data.getClass().getSimpleName(), e.getMessage()); - throw e; - } - } - protected void validateDataImpl(TenantId tenantId, D data) { } diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java index 6c12c0cebd..a90fba0ead 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.service; +import com.fasterxml.jackson.databind.JsonNode; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.validation.Length; @@ -23,15 +24,21 @@ import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; @Slf4j -public class StringLengthValidator implements ConstraintValidator { +public class StringLengthValidator implements ConstraintValidator { private int max; @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - if (StringUtils.isEmpty(value)) { + public boolean isValid(Object value, ConstraintValidatorContext context) { + String stringValue; + if (value instanceof CharSequence || value instanceof JsonNode) { + stringValue = value.toString(); + } else { return true; } - return value.length() <= max; + if (StringUtils.isEmpty(stringValue)) { + return true; + } + return stringValue.length() <= max; } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java index 5691f7a861..ef43fd4df5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDao.java @@ -54,8 +54,6 @@ public class JpaAlarmCommentDao extends JpaAbstractDao getEntityClass() { return AlarmCommentEntity.class; diff --git a/dao/src/main/resources/sql/schema-entities-idx.sql b/dao/src/main/resources/sql/schema-entities-idx.sql index b135e60b8e..dc72e4cdc3 100644 --- a/dao/src/main/resources/sql/schema-entities-idx.sql +++ b/dao/src/main/resources/sql/schema-entities-idx.sql @@ -80,4 +80,4 @@ CREATE INDEX IF NOT EXISTS idx_rule_node_type ON rule_node(type); CREATE INDEX IF NOT EXISTS idx_api_usage_state_entity_id ON api_usage_state(entity_id); -CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id ASC); +CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java index 7d9b258ba6..914c360d86 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmCommentServiceTest.java @@ -39,6 +39,8 @@ import org.thingsboard.server.common.data.security.Authority; import java.util.UUID; import java.util.concurrent.ExecutionException; +import static org.thingsboard.server.common.data.alarm.AlarmCommentType.OTHER; + public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { public static final String TEST_ALARM = "TEST_ALARM"; @@ -80,18 +82,18 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { public void testSaveAndFetchAlarmComment() throws ExecutionException, InterruptedException { AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId()) .userId(user.getId()) - .type("OTHER") + .type(OTHER) .comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))) .build(); - AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment(); + AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment); Assert.assertNotNull(createdComment); Assert.assertNotNull(createdComment.getId()); Assert.assertEquals(alarm.getId(), createdComment.getAlarmId()); Assert.assertEquals(user.getId(), createdComment.getUserId()); - Assert.assertEquals("OTHER", createdComment.getType()); + Assert.assertEquals(OTHER, createdComment.getType()); Assert.assertTrue(createdComment.getCreatedTime() > 0); AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get(); @@ -108,11 +110,11 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { UserId userId = new UserId(UUID.randomUUID()); AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId()) .userId(userId) - .type("OTHER") + .type(OTHER) .comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))) .build(); - AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment(); + AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment); Assert.assertNotNull(createdComment); Assert.assertNotNull(createdComment.getId()); @@ -120,11 +122,11 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { //update comment String newComment = "new comment"; createdComment.setComment(JacksonUtil.newObjectNode().put("text", newComment)); - AlarmComment updatedComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, createdComment).getAlarmComment(); + AlarmComment updatedComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, createdComment); Assert.assertEquals(alarm.getId(), updatedComment.getAlarmId()); Assert.assertEquals(userId, updatedComment.getUserId()); - Assert.assertEquals("OTHER", updatedComment.getType()); + Assert.assertEquals(OTHER, updatedComment.getType()); Assert.assertTrue(updatedComment.getCreatedTime() > 0); Assert.assertEquals(newComment, updatedComment.getComment().get("text").asText()); Assert.assertEquals("true", updatedComment.getComment().get("edited").asText()); @@ -144,16 +146,16 @@ public abstract class BaseAlarmCommentServiceTest extends AbstractServiceTest { UserId userId = new UserId(UUID.randomUUID()); AlarmComment alarmComment = AlarmComment.builder().alarmId(alarm.getId()) .userId(userId) - .type("OTHER") + .type(OTHER) .comment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))) .build(); - AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment).getAlarmComment(); + AlarmComment createdComment = alarmCommentService.createOrUpdateAlarmComment(tenantId, alarmComment); Assert.assertNotNull(createdComment); Assert.assertNotNull(createdComment.getId()); - Assert.assertTrue("Alarm comment was not deleted when expected", alarmCommentService.deleteAlarmComment(tenantId, createdComment.getId()).isSuccessful()); + alarmCommentService.deleteAlarmComment(tenantId, createdComment.getId()); AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get(); diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java index 8530525a63..1a37e3af4b 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java @@ -22,6 +22,7 @@ import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; @@ -58,9 +59,9 @@ public class JpaAlarmCommentDaoTest extends AbstractJpaDaoTest { saveAlarm(alarmId1, UUID.randomUUID(), UUID.randomUUID(), "TEST_ALARM"); saveAlarm(alarmId2, UUID.randomUUID(), UUID.randomUUID(), "TEST_ALARM"); - saveAlarmComment(commentId1, alarmId1, userId, "OTHER"); - saveAlarmComment(commentId2, alarmId1, userId, "OTHER"); - saveAlarmComment(commentId3, alarmId2, userId, "OTHER"); + saveAlarmComment(commentId1, alarmId1, userId, AlarmCommentType.OTHER); + saveAlarmComment(commentId2, alarmId1, userId, AlarmCommentType.OTHER); + saveAlarmComment(commentId3, alarmId2, userId, AlarmCommentType.OTHER); int count = alarmCommentDao.findAlarmComments(TenantId.fromUUID(tenantId), new AlarmId(alarmId1), new PageLink(10, 0)).getData().size(); assertEquals(2, count); @@ -78,7 +79,7 @@ public class JpaAlarmCommentDaoTest extends AbstractJpaDaoTest { alarm.setStatus(AlarmStatus.ACTIVE_UNACK); alarmDao.save(TenantId.fromUUID(tenantId), alarm); } - private void saveAlarmComment(UUID id, UUID alarmId, UUID userId, String type) { + private void saveAlarmComment(UUID id, UUID alarmId, UUID userId, AlarmCommentType type) { AlarmComment alarmComment = new AlarmComment(); alarmComment.setId(new AlarmCommentId(id)); alarmComment.setAlarmId(TenantId.fromUUID(alarmId)); From 36b0e80a23b0f7c76c8067f6f704f8a3618e4f71 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 11 Jan 2023 17:43:08 +0200 Subject: [PATCH 34/43] updated comment length --- .../main/data/upgrade/3.4.3/schema_update.sql | 2 +- .../main/resources/sql/schema-entities.sql | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/application/src/main/data/upgrade/3.4.3/schema_update.sql b/application/src/main/data/upgrade/3.4.3/schema_update.sql index bdc9d1b4fc..e465364339 100644 --- a/application/src/main/data/upgrade/3.4.3/schema_update.sql +++ b/application/src/main/data/upgrade/3.4.3/schema_update.sql @@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS alarm_comment ( alarm_id uuid NOT NULL, user_id uuid, type varchar(255) NOT NULL, - comment varchar(1000000), + comment varchar(10000), CONSTRAINT fk_alarm_comment_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE ) PARTITION BY RANGE (created_time); CREATE INDEX IF NOT EXISTS idx_alarm_comment_alarm_id ON alarm_comment(alarm_id); \ No newline at end of file diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 290e330630..8cea8e5550 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -61,6 +61,16 @@ CREATE TABLE IF NOT EXISTS alarm ( propagate_to_tenant boolean ); +CREATE TABLE IF NOT EXISTS alarm_comment ( + id uuid NOT NULL, + created_time bigint NOT NULL, + alarm_id uuid NOT NULL, + user_id uuid, + type varchar(255) NOT NULL, + comment varchar(10000), + CONSTRAINT fk_alarm_comment_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE + ) PARTITION BY RANGE (created_time); + CREATE TABLE IF NOT EXISTS entity_alarm ( tenant_id uuid NOT NULL, entity_type varchar(32), @@ -775,14 +785,4 @@ CREATE TABLE IF NOT EXISTS user_auth_settings ( created_time bigint NOT NULL, user_id uuid UNIQUE NOT NULL CONSTRAINT fk_user_auth_settings_user_id REFERENCES tb_user(id), two_fa_settings varchar -); - -CREATE TABLE IF NOT EXISTS alarm_comment ( - id uuid NOT NULL, - created_time bigint NOT NULL, - alarm_id uuid NOT NULL, - user_id uuid, - type varchar(255) NOT NULL, - comment varchar(1000000), - CONSTRAINT fk_alarm_comment_alarm_id FOREIGN KEY (alarm_id) REFERENCES alarm(id) ON DELETE CASCADE -) PARTITION BY RANGE (created_time); \ No newline at end of file +); \ No newline at end of file From e0dd0d9369f5437fee5c00c137761aef7573ee3c Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 12 Jan 2023 13:16:26 +0200 Subject: [PATCH 35/43] updated ThingsboardInstallService --- .../thingsboard/server/install/ThingsboardInstallService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java index 9facea6dde..a3d69451ce 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -236,6 +236,10 @@ public class ThingsboardInstallService { log.info("Updating system data..."); systemDataLoaderService.updateSystemWidgets(); break; + case "3.4.3": + log.info("Upgrading ThingsBoard from version 3.4.3 to 3.5 ..."); + databaseEntitiesUpgradeService.upgradeDatabase("3.4.3"); + break; //TODO update CacheCleanupService on the next version upgrade From 071b68e938db20ab3c951a24800b6d8c71e15a86 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 12 Jan 2023 16:35:10 +0200 Subject: [PATCH 36/43] Alarm comment is not entity any more --- .../server/install/ThingsboardInstallService.java | 4 ++-- .../entitiy/DefaultTbNotificationEntityService.java | 4 ++-- .../entitiy/alarm/DefaultTbAlarmCommentService.java | 4 ++-- .../service/entitiy/alarm/DefaultTbAlarmService.java | 3 ++- application/src/main/resources/thingsboard.yml | 1 - .../server/dao/alarm/AlarmCommentService.java | 2 +- .../org/thingsboard/server/common/data/EntityType.java | 2 +- .../thingsboard/server/common/data/audit/ActionType.java | 5 ++++- .../server/common/data/id/AlarmCommentId.java | 8 +------- .../server/common/data/id/EntityIdFactory.java | 2 -- .../server/dao/alarm/BaseAlarmCommentService.java | 9 --------- .../rule/engine/util/EntitiesFieldsAsyncLoader.java | 3 --- .../org/thingsboard/rule/engine/util/TenantIdLoader.java | 4 ---- 13 files changed, 15 insertions(+), 36 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java index a3d69451ce..61cdcd1bbf 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -233,12 +233,12 @@ public class ThingsboardInstallService { log.info("Upgrading ThingsBoard from version 3.4.1 to 3.4.2 ..."); databaseEntitiesUpgradeService.upgradeDatabase("3.4.1"); dataUpdateService.updateData("3.4.1"); - log.info("Updating system data..."); - systemDataLoaderService.updateSystemWidgets(); break; case "3.4.3": log.info("Upgrading ThingsBoard from version 3.4.3 to 3.5 ..."); databaseEntitiesUpgradeService.upgradeDatabase("3.4.3"); + log.info("Updating system data..."); + systemDataLoaderService.updateSystemWidgets(); break; //TODO update CacheCleanupService on the next version upgrade diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java index c06d6e8d04..e0ba7e6567 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java @@ -232,12 +232,12 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS @Override public void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user) { - logEntityAction(alarm.getTenantId(), alarmComment.getId(), alarmComment, alarm.getCustomerId(), actionType, user); + logEntityAction(alarm.getTenantId(), alarm.getId(), alarm, alarm.getCustomerId(), actionType, user, alarmComment); } @Override public void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { - logEntityAction(alarm.getTenantId(), alarmComment.getId(), alarmComment, alarm.getCustomerId(), ActionType.DELETED, user); + logEntityAction(alarm.getTenantId(), alarm.getId(), alarm, alarm.getCustomerId(), ActionType.DELETED_COMMENT, user, alarmComment); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java index af8fa287a4..258431b0f6 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java @@ -31,7 +31,7 @@ import org.thingsboard.server.service.entitiy.AbstractTbEntityService; public class DefaultTbAlarmCommentService extends AbstractTbEntityService implements TbAlarmCommentService{ @Override public AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException { - ActionType actionType = alarmComment.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + ActionType actionType = alarmComment.getId() == null ? ActionType.ADDED_COMMENT : ActionType.UPDATED_COMMENT; UserId userId = user.getId(); alarmComment.setUserId(userId); try { @@ -39,7 +39,7 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem notificationEntityService.notifyCreateOrUpdateAlarmComment(alarm, savedAlarmComment, actionType, user); return savedAlarmComment; } catch (Exception e) { - notificationEntityService.logEntityAction(alarm.getTenantId(), emptyId(EntityType.ALARM_COMMENT), alarmComment, actionType, user, e); + notificationEntityService.logEntityAction(alarm.getTenantId(), emptyId(EntityType.ALARM), alarm, actionType, user, e, alarmComment); throw e; } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java index 6a0d00e992..5552669e32 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -61,7 +61,8 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb AlarmComment alarmComment = AlarmComment.builder() .alarmId(alarm.getId()) .type(AlarmCommentType.SYSTEM) - .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was acknowledged by user %s", user.getName()))) + .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was acknowledged by user %s", user.getName())) + .put("userId", user.getId().toString())) .build(); alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment); alarm.setAckTs(ackTs); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index fb3f2d6e06..c17d03b312 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -584,7 +584,6 @@ audit-log: "user": "${AUDIT_LOG_MASK_USER:W}" "rule_chain": "${AUDIT_LOG_MASK_RULE_CHAIN:W}" "alarm": "${AUDIT_LOG_MASK_ALARM:W}" - "alarm_comment": "${AUDIT_LOG_MASK_ALARM_COMMENT:W}" "entity_view": "${AUDIT_LOG_MASK_ENTITY_VIEW:W}" "device_profile": "${AUDIT_LOG_MASK_DEVICE_PROFILE:W}" "asset_profile": "${AUDIT_LOG_MASK_ASSET_PROFILE:W}" diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java index a60bcbf81d..fbc2b29b6b 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.EntityDaoService; -public interface AlarmCommentService extends EntityDaoService { +public interface AlarmCommentService { AlarmComment createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment); void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index 44b175c20d..0798647903 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -19,5 +19,5 @@ package org.thingsboard.server.common.data; * @author Andrew Shvayka */ public enum EntityType { - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, ALARM_COMMENT, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE; + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java b/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java index 41f6f30dbe..507903a5fd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java @@ -48,7 +48,10 @@ public enum ActionType { PROVISION_SUCCESS(false), PROVISION_FAILURE(false), ASSIGNED_TO_EDGE(false), // log edge name - UNASSIGNED_FROM_EDGE(false); + UNASSIGNED_FROM_EDGE(false), + ADDED_COMMENT(false), + UPDATED_COMMENT(false), + DELETED_COMMENT(false); private final boolean isRead; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java index 3e0c415b0f..1ceeab2f4d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @ApiModel -public class AlarmCommentId extends UUIDBased implements EntityId{ +public class AlarmCommentId extends UUIDBased { private static final long serialVersionUID = 1L; @@ -36,10 +36,4 @@ public class AlarmCommentId extends UUIDBased implements EntityId{ public static AlarmCommentId fromString(String commentId) { return new AlarmCommentId(UUID.fromString(commentId)); } - - @ApiModelProperty(position = 2, required = true, value = "string", example = "ALARM_COMMENT", allowableValues = "ALARM_COMMENT") - @Override - public EntityType getEntityType() { - return EntityType.ALARM_COMMENT; - } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java index ae647825cd..c6a19e0040 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java @@ -53,8 +53,6 @@ public class EntityIdFactory { return new AssetId(uuid); case ALARM: return new AlarmId(uuid); - case ALARM_COMMENT: - return new AlarmCommentId(uuid); case RULE_CHAIN: return new RuleChainId(uuid); case RULE_NODE: diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index c7beaf216e..581d9ab814 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -117,13 +117,4 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al return null; } - @Override - public Optional> findEntity(TenantId tenantId, EntityId entityId) { - return Optional.ofNullable(findAlarmCommentById(tenantId, new AlarmCommentId(entityId.getId()))); - } - - @Override - public EntityType getEntityType() { - return EntityType.ALARM_COMMENT; - } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java index 558e197064..4c7647a321 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java @@ -57,9 +57,6 @@ public class EntitiesFieldsAsyncLoader { case ALARM: return getAsync(ctx.getAlarmService().findAlarmByIdAsync(ctx.getTenantId(), (AlarmId) original), EntityFieldsData::new); - case ALARM_COMMENT: - return getAsync(ctx.getAlarmCommentService().findAlarmCommentByIdAsync(ctx.getTenantId(), (AlarmCommentId) original), - EntityFieldsData::new); case RULE_CHAIN: return getAsync(ctx.getRuleChainService().findRuleChainByIdAsync(ctx.getTenantId(), (RuleChainId) original), EntityFieldsData::new); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java index 344e35084d..f8eb5bc848 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java @@ -71,10 +71,6 @@ public class TenantIdLoader { case ALARM: tenantEntity = ctx.getAlarmService().findAlarmById(ctxTenantId, new AlarmId(id)); break; - case ALARM_COMMENT: - AlarmComment alarmComment = ctx.getAlarmCommentService().findAlarmCommentById(ctxTenantId, new AlarmCommentId(id)); - tenantEntity = ctx.getAlarmService().findAlarmById(ctxTenantId, new AlarmId(alarmComment.getAlarmId().getId())); - break; case RULE_CHAIN: tenantEntity = ctx.getRuleChainService().findRuleChainById(ctxTenantId, new RuleChainId(id)); break; From 715704d76a37428b1cf7bb75721a9c1141545525 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 12 Jan 2023 16:56:21 +0200 Subject: [PATCH 37/43] Refactoring --- .../service/entitiy/alarm/DefaultTbAlarmService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java index 5552669e32..7e778fd840 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -61,7 +61,8 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb AlarmComment alarmComment = AlarmComment.builder() .alarmId(alarm.getId()) .type(AlarmCommentType.SYSTEM) - .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was acknowledged by user %s", user.getName())) + .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was acknowledged by user %s", + (user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName())) .put("userId", user.getId().toString())) .build(); alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment); @@ -80,7 +81,9 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb AlarmComment alarmComment = AlarmComment.builder() .alarmId(alarm.getId()) .type(AlarmCommentType.SYSTEM) - .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was cleared by user %s", user.getName()))) + .comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was cleared by user %s", + (user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName())) + .put("userId", user.getId().toString())) .build(); alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment); alarm.setClearTs(clearTs); From e8d651a108b2f2f0490f25c8e4bd891aecc22d88 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 12 Jan 2023 18:42:47 +0200 Subject: [PATCH 38/43] fixed audit logs --- .../entitiy/DefaultTbNotificationEntityService.java | 7 +------ .../service/entitiy/TbNotificationEntityService.java | 3 +-- .../entitiy/alarm/DefaultTbAlarmCommentService.java | 4 ++-- .../alarmComment/DefaultTbAlarmCommentServiceTest.java | 4 ++-- .../thingsboard/server/dao/audit/AuditLogServiceImpl.java | 7 +++++++ .../thingsboard/rule/engine/util/TenantIdLoaderTest.java | 8 -------- ui-ngx/src/app/shared/models/audit-log.models.ts | 6 ++++++ ui-ngx/src/assets/locale/locale.constant-en_US.json | 3 +++ 8 files changed, 22 insertions(+), 20 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java index e0ba7e6567..fe00715303 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java @@ -231,15 +231,10 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS } @Override - public void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user) { + public void notifyAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user) { logEntityAction(alarm.getTenantId(), alarm.getId(), alarm, alarm.getCustomerId(), actionType, user, alarmComment); } - @Override - public void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { - logEntityAction(alarm.getTenantId(), alarm.getId(), alarm, alarm.getCustomerId(), ActionType.DELETED_COMMENT, user, alarmComment); - } - @Override public void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, I entityId, E entity, User user, diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java index 6ef53fd7f6..baf63738e2 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java @@ -103,9 +103,8 @@ public interface TbNotificationEntityService { void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, User user, Object... additionalInfo); - void notifyCreateOrUpdateAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user); + void notifyAlarmComment(Alarm alarm, AlarmComment alarmComment, ActionType actionType, User user); - void notifyDeleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user); void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, I entityId, E entity, User user, diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java index 258431b0f6..ee98af5f0f 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmCommentService.java @@ -36,7 +36,7 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem alarmComment.setUserId(userId); try { AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment)); - notificationEntityService.notifyCreateOrUpdateAlarmComment(alarm, savedAlarmComment, actionType, user); + notificationEntityService.notifyAlarmComment(alarm, savedAlarmComment, actionType, user); return savedAlarmComment; } catch (Exception e) { notificationEntityService.logEntityAction(alarm.getTenantId(), emptyId(EntityType.ALARM), alarm, actionType, user, e, alarmComment); @@ -47,6 +47,6 @@ public class DefaultTbAlarmCommentService extends AbstractTbEntityService implem @Override public void deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { alarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment.getId()); - notificationEntityService.notifyDeleteAlarmComment(alarm, alarmComment, user); + notificationEntityService.notifyAlarmComment(alarm, alarmComment, ActionType.DELETED_COMMENT, user); } } diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java index dfc070110f..174d78c7ef 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java @@ -80,7 +80,7 @@ public class DefaultTbAlarmCommentServiceTest { when(alarmCommentService.createOrUpdateAlarmComment(Mockito.any(), eq(alarmComment))).thenReturn(alarmComment); service.saveAlarmComment(alarm, alarmComment, new User()); - verify(notificationEntityService, times(1)).notifyCreateOrUpdateAlarmComment(any(), any(), any(), any()); + verify(notificationEntityService, times(1)).notifyAlarmComment(any(), any(), any(), any()); } @Test @@ -91,6 +91,6 @@ public class DefaultTbAlarmCommentServiceTest { doNothing().when(alarmCommentService).deleteAlarmComment(Mockito.any(), eq(alarmCommentId)); service.deleteAlarmComment(new Alarm(alarmId), new AlarmComment(alarmCommentId), new User()); - verify(notificationEntityService, times(1)).notifyDeleteAlarmComment(any(), any(), any()); + verify(notificationEntityService, times(1)).notifyAlarmComment(any(), any(), any(), any()); } } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 3df41be1e3..6c612b7e6e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -30,6 +30,7 @@ import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.audit.ActionStatus; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.AuditLog; @@ -45,6 +46,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.audit.sink.AuditLogSink; import org.thingsboard.server.dao.device.provision.ProvisionRequest; import org.thingsboard.server.dao.entity.EntityService; @@ -182,6 +184,11 @@ public class AuditLogServiceImpl implements AuditLogService { } } break; + case ADDED_COMMENT: + case DELETED_COMMENT: + AlarmComment comment = extractParameter(AlarmComment.class, additionalInfo); + actionData.set("comment", comment.getComment()); + break; case DELETED: case ACTIVATED: case SUSPENDED: diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java index 4990439e60..6ac3f58925 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java @@ -195,14 +195,6 @@ public class TenantIdLoaderTest { when(ctx.getAlarmService()).thenReturn(alarmService); doReturn(alarm).when(alarmService).findAlarmById(eq(tenantId), any()); - break; - case ALARM_COMMENT: - AlarmComment alarmComment = new AlarmComment(); - alarmComment.setAlarmId(new AlarmId(UUID.randomUUID())); - - when(ctx.getAlarmCommentService()).thenReturn(alarmCommentService); - doReturn(alarmComment).when(alarmCommentService).findAlarmCommentById(eq(tenantId), any()); - break; case RULE_CHAIN: RuleChain ruleChain = new RuleChain(); diff --git a/ui-ngx/src/app/shared/models/audit-log.models.ts b/ui-ngx/src/app/shared/models/audit-log.models.ts index 056c6aa569..e1f11ceee7 100644 --- a/ui-ngx/src/app/shared/models/audit-log.models.ts +++ b/ui-ngx/src/app/shared/models/audit-log.models.ts @@ -47,6 +47,9 @@ export enum ActionType { RELATIONS_DELETED = 'RELATIONS_DELETED', ALARM_ACK = 'ALARM_ACK', ALARM_CLEAR = 'ALARM_CLEAR', + ADDED_COMMENT = 'ADDED_COMMENT', + UPDATED_COMMENT = 'UPDATED_COMMENT', + DELETED_COMMENT = 'DELETED_COMMENT', LOGIN = 'LOGIN', LOGOUT = 'LOGOUT', LOCKOUT = 'LOCKOUT', @@ -85,6 +88,9 @@ export const actionTypeTranslations = new Map( [ActionType.RELATIONS_DELETED, 'audit-log.type-relations-delete'], [ActionType.ALARM_ACK, 'audit-log.type-alarm-ack'], [ActionType.ALARM_CLEAR, 'audit-log.type-alarm-clear'], + [ActionType.ADDED_COMMENT, 'audit-log.type-added-comment'], + [ActionType.UPDATED_COMMENT, 'audit-log.type-updated-comment'], + [ActionType.DELETED_COMMENT, 'audit-log.type-deleted-comment'], [ActionType.LOGIN, 'audit-log.type-login'], [ActionType.LOGOUT, 'audit-log.type-logout'], [ActionType.LOCKOUT, 'audit-log.type-lockout'], diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index dd28154103..f86743e21d 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -728,6 +728,9 @@ "type-relations-delete": "All relation deleted", "type-alarm-ack": "Acknowledged", "type-alarm-clear": "Cleared", + "type-added-comment": "Added comment", + "type-updated-comment": "Updated comment", + "type-deleted-comment": "Deleted comment", "type-login": "Login", "type-logout": "Logout", "type-lockout": "Lockout", From b80069500bc2bcaf51842da4d22c20aebdf57dd5 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 13 Jan 2023 11:57:47 +0200 Subject: [PATCH 39/43] fixed unit tests --- .../controller/AbstractNotifyEntityTest.java | 6 ----- .../BaseAlarmCommentControllerTest.java | 24 +++++++------------ 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java index 9653fdba33..672e55825b 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java @@ -340,12 +340,6 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { Mockito.argThat(matcherOriginatorId), Mockito.any(TbMsg.class), Mockito.isNull()); } - protected void testPushMsgToRuleEngineTime(EntityId matcherOriginatorId, TenantId tenantId, HasName entity, int cntTime) { - tenantId = tenantId.isNullUid() && ((HasTenantId) entity).getTenantId() != null ? ((HasTenantId) entity).getTenantId() : tenantId; - Mockito.verify(tbClusterService, times(cntTime)).pushMsgToRuleEngine(Mockito.eq(tenantId), - Mockito.eq(matcherOriginatorId), Mockito.any(TbMsg.class), Mockito.isNull()); - } - private void testNotificationMsgToEdgeServiceTime(EntityId entityId, TenantId tenantId, ActionType actionType, int cntTime) { EdgeEventActionType edgeEventActionType = ActionType.CREDENTIALS_UPDATED.equals(actionType) ? EdgeEventActionType.CREDENTIALS_UPDATED : edgeTypeByActionType(actionType); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java index 4986eacb52..8aba871651 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java @@ -105,8 +105,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT AlarmComment createdComment = createAlarmComment(alarm.getId()); - testLogEntityAction(createdComment, createdComment.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ADDED, 1); - testPushMsgToRuleEngineTime(createdComment.getId(), tenantId, createdComment, 1); + testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ADDED_COMMENT, 1, createdComment); } @Test @@ -118,8 +117,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT AlarmComment createdComment = createAlarmComment(alarm.getId()); Assert.assertEquals(AlarmCommentType.OTHER, createdComment.getType()); - testLogEntityAction(createdComment, createdComment.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ADDED, 1); - testPushMsgToRuleEngineTime(createdComment.getId(), tenantId, createdComment, 1); + testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ADDED_COMMENT, 1, createdComment); } @Test @@ -138,8 +136,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText()); Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn")); - testLogEntityAction(updatedAlarmComment, updatedAlarmComment.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.UPDATED, 1); - testPushMsgToRuleEngineTime(updatedAlarmComment.getId(), tenantId, updatedAlarmComment, 1); + testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.UPDATED_COMMENT, 1, savedComment); } @Test @@ -158,8 +155,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT Assert.assertEquals("true", updatedAlarmComment.getComment().get("edited").asText()); Assert.assertNotNull(updatedAlarmComment.getComment().get("editedOn")); - testLogEntityAction(updatedAlarmComment, updatedAlarmComment.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.UPDATED, 1); - testPushMsgToRuleEngineTime(updatedAlarmComment.getId(), tenantId, updatedAlarmComment, 1); + testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.UPDATED_COMMENT, 1, updatedAlarmComment); } @Test @@ -177,7 +173,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT .andExpect(status().isForbidden()) .andExpect(statusReason(containsString(msgErrorPermission))); - testNotifyEntityNever(savedComment.getId(), savedComment); + testNotifyEntityNever(alarm.getId(), savedComment); } @Test @@ -195,11 +191,11 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT .andExpect(status().isForbidden()) .andExpect(statusReason(containsString(msgErrorPermission))); - testNotifyEntityNever(savedComment.getId(), savedComment); + testNotifyEntityNever(alarm.getId(), savedComment); } @Test - public void testDeleteAlarmViaCustomer() throws Exception { + public void testDeleteAlarmСommentViaCustomer() throws Exception { loginCustomerUser(); AlarmComment alarmComment = createAlarmComment(alarm.getId()); @@ -208,8 +204,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId()) .andExpect(status().isOk()); - testNotifyEntityOneTimeMsgToEdgeServiceNever(alarmComment, alarmComment.getId(), alarmComment.getId(), - tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.DELETED); + testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.DELETED_COMMENT, 1, alarmComment); } @Test @@ -222,8 +217,7 @@ public abstract class BaseAlarmCommentControllerTest extends AbstractControllerT doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId()) .andExpect(status().isOk()); - testNotifyEntityOneTimeMsgToEdgeServiceNever(alarmComment, alarmComment.getId(), alarmComment.getId(), - tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.DELETED); + testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.DELETED_COMMENT, 1, alarmComment); } @Test From 55d4f22e4650e6335705a251fc452a8c96a13123 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 13 Jan 2023 13:06:52 +0200 Subject: [PATCH 40/43] fixed unit tests --- .../entitiy/alarm/DefaultTbAlarmServiceTest.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java index 0314788065..32a270acb4 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java @@ -27,8 +27,10 @@ import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.customer.CustomerService; @@ -38,6 +40,8 @@ import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; +import java.util.UUID; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; @@ -91,8 +95,9 @@ public class DefaultTbAlarmServiceTest { var alarm = new Alarm(); alarm.setStatus(AlarmStatus.ACTIVE_UNACK); when(alarmSubscriptionService.ackAlarm(any(), any(), anyLong())).thenReturn(Futures.immediateFuture(true)); - service.ack(alarm, new User()); + service.ack(alarm, new User(new UserId(UUID.randomUUID()))); + verify(alarmCommentService, times(1)).createOrUpdateAlarmComment(any(), any()); verify(notificationEntityService, times(1)).notifyCreateOrUpdateAlarm(any(), any(), any()); verify(alarmSubscriptionService, times(1)).ackAlarm(any(), any(), anyLong()); } @@ -102,8 +107,9 @@ public class DefaultTbAlarmServiceTest { var alarm = new Alarm(); alarm.setStatus(AlarmStatus.ACTIVE_ACK); when(alarmSubscriptionService.clearAlarm(any(), any(), any(), anyLong())).thenReturn(Futures.immediateFuture(true)); - service.clear(alarm, new User()); + service.clear(alarm, new User(new UserId(UUID.randomUUID()))); + verify(alarmCommentService, times(1)).createOrUpdateAlarmComment(any(), any()); verify(notificationEntityService, times(1)).notifyCreateOrUpdateAlarm(any(), any(), any()); verify(alarmSubscriptionService, times(1)).clearAlarm(any(), any(), any(), anyLong()); } From 22539332505e14c37894bd7f9e4505c1cefe2743 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 13 Jan 2023 14:20:10 +0200 Subject: [PATCH 41/43] fixed audit logs --- .../org/thingsboard/server/dao/audit/AuditLogServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 6c612b7e6e..1d42dc5a26 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -185,6 +185,7 @@ public class AuditLogServiceImpl implements AuditLogService { } break; case ADDED_COMMENT: + case UPDATED_COMMENT: case DELETED_COMMENT: AlarmComment comment = extractParameter(AlarmComment.class, additionalInfo); actionData.set("comment", comment.getComment()); From 0a6d227364ca2833d5f09b0cf9ac5a2ec93a5ad7 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 13 Jan 2023 16:37:13 +0200 Subject: [PATCH 42/43] refactoring --- .../server/dao/alarm/AlarmOperationResult.java | 10 ++-------- .../server/dao/alarm/BaseAlarmCommentService.java | 3 +-- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java index f8eefafac6..c91fb9d789 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmOperationResult.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.alarm; +import lombok.AllArgsConstructor; import lombok.Data; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmSeverity; @@ -24,6 +25,7 @@ import java.util.Collections; import java.util.List; @Data +@AllArgsConstructor public class AlarmOperationResult { private final Alarm alarm; private final boolean successful; @@ -38,12 +40,4 @@ public class AlarmOperationResult { public AlarmOperationResult(Alarm alarm, boolean successful, List propagatedEntitiesList) { this(alarm, successful, false, null, propagatedEntitiesList); } - - public AlarmOperationResult(Alarm alarm, boolean successful, boolean created, AlarmSeverity oldSeverity, List propagatedEntitiesList) { - this.alarm = alarm; - this.successful = successful; - this.created = created; - this.oldSeverity = oldSeverity; - this.propagatedEntitiesList = propagatedEntitiesList; - } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 581d9ab814..3984efeca0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -107,9 +107,8 @@ public class BaseAlarmCommentService extends AbstractEntityService implements Al if (existing != null) { if (newAlarmComment.getComment() != null) { JsonNode comment = newAlarmComment.getComment(); - UUID uuid = Uuids.timeBased(); ((ObjectNode) comment).put("edited", "true"); - ((ObjectNode) comment).put("editedOn", Uuids.unixTimestamp(uuid)); + ((ObjectNode) comment).put("editedOn", System.currentTimeMillis()); existing.setComment(comment); } return alarmCommentDao.save(tenantId, existing); From 7792fe7293e66bd70b383d45308e30ff66553e3f Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 13 Jan 2023 17:55:01 +0200 Subject: [PATCH 43/43] deleted unused imports --- .../thingsboard/server/controller/AlarmCommentController.java | 2 -- .../server/service/entitiy/alarm/TbAlarmCommentService.java | 1 - .../server/controller/BaseAlarmCommentControllerTest.java | 1 - .../service/entitiy/alarm/DefaultTbAlarmServiceTest.java | 1 - .../org/thingsboard/server/dao/alarm/AlarmCommentService.java | 1 - .../thingsboard/server/dao/alarm/BaseAlarmCommentService.java | 4 ---- .../org/thingsboard/server/dao/audit/AuditLogServiceImpl.java | 1 - .../server/dao/model/sql/AlarmCommentInfoEntity.java | 3 --- .../rule/engine/util/EntitiesFieldsAsyncLoader.java | 1 - .../java/org/thingsboard/rule/engine/util/TenantIdLoader.java | 2 -- .../org/thingsboard/rule/engine/util/TenantIdLoaderTest.java | 2 -- 11 files changed, 19 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index b86becd132..1af3c8c8bf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -38,12 +38,10 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService; import org.thingsboard.server.service.security.permission.Operation; -import org.thingsboard.server.service.security.permission.Resource; import static org.thingsboard.server.controller.ControllerConstants.ALARM_COMMENT_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_COMMENT_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.ALARM_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java index 74f207138e..d8bb798d49 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmCommentService.java @@ -19,7 +19,6 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.exception.ThingsboardException; -import org.thingsboard.server.common.data.id.TenantId; public interface TbAlarmCommentService { AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException; diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java index 8aba871651..337abee74f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmCommentControllerTest.java @@ -25,7 +25,6 @@ import org.junit.Before; import org.junit.Test; import org.mockito.AdditionalAnswers; import org.mockito.Mockito; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java index 32a270acb4..bea64f12af 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java @@ -27,7 +27,6 @@ import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.UserId; diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java index fbc2b29b6b..d4ffee4169 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/alarm/AlarmCommentService.java @@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.dao.entity.EntityDaoService; public interface AlarmCommentService { AlarmComment createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment); diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java index 3984efeca0..7cc547536a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmCommentService.java @@ -22,21 +22,17 @@ import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; -import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.service.DataValidator; -import java.util.Optional; import java.util.UUID; import static org.thingsboard.server.dao.service.Validator.validateId; diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 1d42dc5a26..e7f57b0eb0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -46,7 +46,6 @@ import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.rule.RuleChainMetaData; import org.thingsboard.server.common.data.security.DeviceCredentials; -import org.thingsboard.server.dao.alarm.AlarmCommentService; import org.thingsboard.server.dao.audit.sink.AuditLogSink; import org.thingsboard.server.dao.device.provision.ProvisionRequest; import org.thingsboard.server.dao.entity.EntityService; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java index bc9c5841c5..1d19ec9388 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentInfoEntity.java @@ -19,9 +19,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; -import java.util.HashMap; -import java.util.Map; - @Data @EqualsAndHashCode(callSuper = true) public class AlarmCommentInfoEntity extends AbstractAlarmCommentEntity { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java index 4c7647a321..245b671cf5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoader.java @@ -22,7 +22,6 @@ import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.EntityFieldsData; -import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java index f8eb5bc848..b687246789 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java @@ -18,8 +18,6 @@ package org.thingsboard.rule.engine.util; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.HasTenantId; -import org.thingsboard.server.common.data.alarm.AlarmComment; -import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.ApiUsageStateId; import org.thingsboard.server.common.data.id.AssetId; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java index 6ac3f58925..08081ff961 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java @@ -41,11 +41,9 @@ import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; -import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.EntityId;