115 changed files with 2131 additions and 162 deletions
@ -0,0 +1,127 @@ |
|||||
|
/** |
||||
|
* 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.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; |
||||
|
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 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.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; |
||||
|
|
||||
|
@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. " + |
||||
|
"\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')") |
||||
|
@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); |
||||
|
AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); |
||||
|
Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); |
||||
|
alarmComment.setAlarmId(alarmId); |
||||
|
return tbAlarmCommentService.saveAlarmComment(alarm, 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 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, alarmId); |
||||
|
tbAlarmCommentService.deleteAlarmComment(alarm, alarmComment, getCurrentUser()); |
||||
|
} |
||||
|
|
||||
|
@ApiOperation(value = "Get Alarm comments (getAlarmComments)", |
||||
|
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) |
||||
|
@ResponseBody |
||||
|
public PageData<AlarmCommentInfo> getAlarmComments( |
||||
|
@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) |
||||
|
@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, |
||||
|
@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 |
||||
|
) throws Exception { |
||||
|
checkParameter(ALARM_ID, strAlarmId); |
||||
|
AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); |
||||
|
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)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
/** |
||||
|
* 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.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.UserId; |
||||
|
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
||||
|
|
||||
|
@Service |
||||
|
@AllArgsConstructor |
||||
|
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_COMMENT : ActionType.UPDATED_COMMENT; |
||||
|
UserId userId = user.getId(); |
||||
|
alarmComment.setUserId(userId); |
||||
|
try { |
||||
|
AlarmComment savedAlarmComment = checkNotNull(alarmCommentService.createOrUpdateAlarmComment(alarm.getTenantId(), alarmComment)); |
||||
|
notificationEntityService.notifyAlarmComment(alarm, savedAlarmComment, actionType, user); |
||||
|
return savedAlarmComment; |
||||
|
} catch (Exception e) { |
||||
|
notificationEntityService.logEntityAction(alarm.getTenantId(), emptyId(EntityType.ALARM), alarm, actionType, user, e, alarmComment); |
||||
|
throw e; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) { |
||||
|
alarmCommentService.deleteAlarmComment(alarm.getTenantId(), alarmComment.getId()); |
||||
|
notificationEntityService.notifyAlarmComment(alarm, alarmComment, ActionType.DELETED_COMMENT, user); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
/** |
||||
|
* 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.Alarm; |
||||
|
import org.thingsboard.server.common.data.alarm.AlarmComment; |
||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException; |
||||
|
|
||||
|
public interface TbAlarmCommentService { |
||||
|
AlarmComment saveAlarmComment(Alarm alarm, AlarmComment alarmComment, User user) throws ThingsboardException; |
||||
|
|
||||
|
void deleteAlarmComment(Alarm alarm, AlarmComment alarmComment, User user); |
||||
|
} |
||||
@ -0,0 +1,363 @@ |
|||||
|
/** |
||||
|
* 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.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.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; |
||||
|
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(alarm, alarm.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ADDED_COMMENT, 1, createdComment); |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void testCreateAlarmCommentViaTenant() throws Exception { |
||||
|
loginTenantAdmin(); |
||||
|
|
||||
|
Mockito.reset(tbClusterService, auditLogService); |
||||
|
|
||||
|
AlarmComment createdComment = createAlarmComment(alarm.getId()); |
||||
|
Assert.assertEquals(AlarmCommentType.OTHER, createdComment.getType()); |
||||
|
|
||||
|
testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ADDED_COMMENT, 1, createdComment); |
||||
|
} |
||||
|
|
||||
|
@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")); |
||||
|
|
||||
|
testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.UPDATED_COMMENT, 1, savedComment); |
||||
|
} |
||||
|
|
||||
|
@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")); |
||||
|
|
||||
|
testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.UPDATED_COMMENT, 1, updatedAlarmComment); |
||||
|
} |
||||
|
|
||||
|
@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(alarm.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(alarm.getId(), savedComment); |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void testDeleteAlarmСommentViaCustomer() throws Exception { |
||||
|
loginCustomerUser(); |
||||
|
AlarmComment alarmComment = createAlarmComment(alarm.getId()); |
||||
|
|
||||
|
Mockito.reset(tbClusterService, auditLogService); |
||||
|
|
||||
|
doDelete("/api/alarm/" + alarm.getId() + "/comment/" + alarmComment.getId()) |
||||
|
.andExpect(status().isOk()); |
||||
|
|
||||
|
testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.DELETED_COMMENT, 1, alarmComment); |
||||
|
} |
||||
|
|
||||
|
@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()); |
||||
|
|
||||
|
testLogEntityAction(alarm, alarm.getId(), tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.DELETED_COMMENT, 1, alarmComment); |
||||
|
} |
||||
|
|
||||
|
@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 testFindAlarmCommentsViaCustomerUser() throws Exception { |
||||
|
loginCustomerUser(); |
||||
|
|
||||
|
List<AlarmComment> 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<PageData<AlarmCommentInfo>>() {} |
||||
|
); |
||||
|
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<AlarmComment> 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<AlarmCommentInfo> pageData = doGetTyped( |
||||
|
"/api/alarm/" + alarm.getId() + "/comment" + "?page=0&pageSize=1", new TypeReference<PageData<AlarmCommentInfo>>() {} |
||||
|
); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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 { |
||||
|
} |
||||
@ -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.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.doNothing; |
||||
|
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(alarmComment); |
||||
|
service.saveAlarmComment(alarm, alarmComment, new User()); |
||||
|
|
||||
|
verify(notificationEntityService, times(1)).notifyAlarmComment(any(), any(), any(), any()); |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
public void testDelete() { |
||||
|
var alarmId = new AlarmId(UUID.randomUUID()); |
||||
|
var alarmCommentId = new AlarmCommentId(UUID.randomUUID()); |
||||
|
|
||||
|
doNothing().when(alarmCommentService).deleteAlarmComment(Mockito.any(), eq(alarmCommentId)); |
||||
|
service.deleteAlarmComment(new Alarm(alarmId), new AlarmComment(alarmCommentId), new User()); |
||||
|
|
||||
|
verify(notificationEntityService, times(1)).notifyAlarmComment(any(), any(), any(), any()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
/** |
||||
|
* 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.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; |
||||
|
import org.thingsboard.server.common.data.page.PageData; |
||||
|
import org.thingsboard.server.common.data.page.PageLink; |
||||
|
|
||||
|
public interface AlarmCommentService { |
||||
|
AlarmComment createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment); |
||||
|
|
||||
|
void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); |
||||
|
|
||||
|
PageData<AlarmCommentInfo> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink); |
||||
|
|
||||
|
ListenableFuture<AlarmComment> findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId); |
||||
|
|
||||
|
AlarmComment findAlarmCommentById(TenantId tenantId, AlarmCommentId alarmCommentId); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,87 @@ |
|||||
|
/** |
||||
|
* 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.annotation.JsonProperty; |
||||
|
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.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 |
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
public class AlarmComment extends BaseData<AlarmCommentId> implements HasName { |
||||
|
@ApiModelProperty(position = 3, value = "JSON object with Alarm id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) |
||||
|
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. 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. " + |
||||
|
"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 |
||||
|
@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(); |
||||
|
} |
||||
|
|
||||
|
public AlarmComment(AlarmComment alarmComment) { |
||||
|
super(alarmComment.getId()); |
||||
|
this.createdTime = alarmComment.getCreatedTime(); |
||||
|
this.alarmId = alarmComment.getAlarmId(); |
||||
|
this.type = alarmComment.getType(); |
||||
|
this.comment = alarmComment.getComment(); |
||||
|
this.userId = alarmComment.getUserId(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
/** |
||||
|
* 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; |
||||
|
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 first name", example = "John") |
||||
|
private String firstName; |
||||
|
|
||||
|
@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(); |
||||
|
} |
||||
|
|
||||
|
public AlarmCommentInfo(AlarmComment alarmComment) { |
||||
|
super(alarmComment); |
||||
|
} |
||||
|
|
||||
|
public AlarmCommentInfo(AlarmComment alarmComment, String firstName, String lastName, String email) { |
||||
|
super(alarmComment); |
||||
|
this.firstName = firstName; |
||||
|
this.lastName = lastName; |
||||
|
this.email = email; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
|
||||
|
} |
||||
@ -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.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 { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
@JsonCreator |
||||
|
public AlarmCommentId(@JsonProperty("id") UUID id) { |
||||
|
super(id); |
||||
|
} |
||||
|
|
||||
|
public static AlarmCommentId fromString(String commentId) { |
||||
|
return new AlarmCommentId(UUID.fromString(commentId)); |
||||
|
} |
||||
|
} |
||||
@ -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.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; |
||||
|
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> { |
||||
|
|
||||
|
AlarmComment createAlarmComment(TenantId tenantId, AlarmComment alarmComment); |
||||
|
|
||||
|
void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId); |
||||
|
|
||||
|
AlarmComment findAlarmCommentById(TenantId tenantId, UUID key); |
||||
|
|
||||
|
PageData<AlarmCommentInfo> findAlarmComments(TenantId tenantId, AlarmId id, PageLink pageLink); |
||||
|
|
||||
|
ListenableFuture<AlarmComment> findAlarmCommentByIdAsync(TenantId tenantId, UUID key); |
||||
|
} |
||||
@ -0,0 +1,115 @@ |
|||||
|
/** |
||||
|
* 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.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.ListenableFuture; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
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.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.UUID; |
||||
|
|
||||
|
import static org.thingsboard.server.dao.service.Validator.validateId; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
public class BaseAlarmCommentService extends AbstractEntityService implements AlarmCommentService{ |
||||
|
|
||||
|
@Autowired |
||||
|
private AlarmCommentDao alarmCommentDao; |
||||
|
|
||||
|
@Autowired |
||||
|
private DataValidator<AlarmComment> alarmCommentDataValidator; |
||||
|
|
||||
|
@Override |
||||
|
public AlarmComment createOrUpdateAlarmComment(TenantId tenantId, AlarmComment alarmComment) { |
||||
|
alarmCommentDataValidator.validate(alarmComment, c -> tenantId); |
||||
|
if (alarmComment.getId() == null) { |
||||
|
return createAlarmComment(tenantId, alarmComment); |
||||
|
} else { |
||||
|
return updateAlarmComment(tenantId, alarmComment); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void deleteAlarmComment(TenantId tenantId, AlarmCommentId alarmCommentId) { |
||||
|
log.debug("Deleting Alarm Comment with id: {}", alarmCommentId); |
||||
|
alarmCommentDao.deleteAlarmComment(tenantId, alarmCommentId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageData<AlarmCommentInfo> findAlarmComments(TenantId tenantId, AlarmId alarmId, PageLink pageLink) { |
||||
|
log.trace("Executing findAlarmComments by alarmId [{}]", alarmId); |
||||
|
return alarmCommentDao.findAlarmComments(tenantId, alarmId, pageLink); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ListenableFuture<AlarmComment> findAlarmCommentByIdAsync(TenantId tenantId, AlarmCommentId alarmCommentId) { |
||||
|
log.trace("Executing findAlarmCommentByIdAsync by alarmCommentId [{}]", alarmCommentId); |
||||
|
validateId(alarmCommentId, "Incorrect alarmCommentId " + alarmCommentId); |
||||
|
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 AlarmComment createAlarmComment(TenantId tenantId, AlarmComment alarmComment) { |
||||
|
log.debug("New Alarm comment : {}", alarmComment); |
||||
|
if (alarmComment.getType() == null) { |
||||
|
alarmComment.setType(AlarmCommentType.OTHER); |
||||
|
} |
||||
|
if (alarmComment.getId() == null) { |
||||
|
UUID uuid = Uuids.timeBased(); |
||||
|
alarmComment.setId(new AlarmCommentId(uuid)); |
||||
|
alarmComment.setCreatedTime(Uuids.unixTimestamp(uuid)); |
||||
|
} |
||||
|
return alarmCommentDao.createAlarmComment(tenantId, alarmComment); |
||||
|
} |
||||
|
|
||||
|
private AlarmComment updateAlarmComment(TenantId tenantId, AlarmComment newAlarmComment) { |
||||
|
log.debug("Update Alarm comment : {}", newAlarmComment); |
||||
|
|
||||
|
AlarmComment existing = alarmCommentDao.findAlarmCommentById(tenantId, newAlarmComment.getId().getId()); |
||||
|
if (existing != null) { |
||||
|
if (newAlarmComment.getComment() != null) { |
||||
|
JsonNode comment = newAlarmComment.getComment(); |
||||
|
((ObjectNode) comment).put("edited", "true"); |
||||
|
((ObjectNode) comment).put("editedOn", System.currentTimeMillis()); |
||||
|
existing.setComment(comment); |
||||
|
} |
||||
|
return alarmCommentDao.save(tenantId, existing); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,98 @@ |
|||||
|
/** |
||||
|
* 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.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; |
||||
|
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<T extends AlarmComment> extends BaseSqlEntity<T> implements BaseEntity<T> { |
||||
|
|
||||
|
@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 AlarmCommentType 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()); |
||||
|
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)); |
||||
|
if (userId != null) { |
||||
|
alarmComment.setUserId(new UserId(userId)); |
||||
|
} |
||||
|
alarmComment.setType(type); |
||||
|
alarmComment.setComment(comment); |
||||
|
return alarmComment; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
/** |
||||
|
* 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.hibernate.annotations.TypeDef; |
||||
|
import org.thingsboard.server.common.data.alarm.AlarmComment; |
||||
|
import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; |
||||
|
import org.thingsboard.server.dao.util.mapping.JsonStringType; |
||||
|
|
||||
|
import javax.persistence.Entity; |
||||
|
import javax.persistence.Table; |
||||
|
|
||||
|
import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_COLUMN_FAMILY_NAME; |
||||
|
|
||||
|
@Data |
||||
|
@EqualsAndHashCode(callSuper = true) |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
@Table(name = ALARM_COMMENT_COLUMN_FAMILY_NAME) |
||||
|
|
||||
|
public class AlarmCommentEntity extends AbstractAlarmCommentEntity<AlarmComment> { |
||||
|
|
||||
|
public AlarmCommentEntity() { |
||||
|
super(); |
||||
|
} |
||||
|
|
||||
|
public AlarmCommentEntity(AlarmCommentInfo alarmCommentInfo) { |
||||
|
super(alarmCommentInfo); |
||||
|
} |
||||
|
|
||||
|
public AlarmCommentEntity(AlarmComment alarmComment) { |
||||
|
super(alarmComment); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public AlarmComment toData() { |
||||
|
return super.toAlarmComment(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -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.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<AlarmCommentInfo> { |
||||
|
|
||||
|
private String firstName; |
||||
|
private String lastName; |
||||
|
|
||||
|
private String email; |
||||
|
|
||||
|
public AlarmCommentInfoEntity() { |
||||
|
super(); |
||||
|
} |
||||
|
|
||||
|
public AlarmCommentInfoEntity(AlarmCommentEntity alarmCommentEntity) { |
||||
|
super(alarmCommentEntity); |
||||
|
} |
||||
|
|
||||
|
public AlarmCommentInfoEntity(AlarmCommentEntity alarmCommentEntity, String firstName, String lastName, String email) { |
||||
|
super(alarmCommentEntity); |
||||
|
this.firstName = firstName; |
||||
|
this.lastName = lastName; |
||||
|
this.email = email; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public AlarmCommentInfo toData() { |
||||
|
return new AlarmCommentInfo(super.toAlarmComment(), this.firstName, this.lastName, this.email); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
/** |
||||
|
* 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.alarm.AlarmComment; |
||||
|
import org.thingsboard.server.common.data.id.TenantId; |
||||
|
import org.thingsboard.server.dao.exception.DataValidationException; |
||||
|
import org.thingsboard.server.dao.service.DataValidator; |
||||
|
|
||||
|
@Component |
||||
|
@AllArgsConstructor |
||||
|
public class AlarmCommentDataValidator extends DataValidator<AlarmComment> { |
||||
|
|
||||
|
@Override |
||||
|
protected void validateDataImpl(TenantId tenantId, AlarmComment alarmComment) { |
||||
|
if (alarmComment.getComment() == null) { |
||||
|
throw new DataValidationException("Alarm comment should be specified!"); |
||||
|
} |
||||
|
if (alarmComment.getAlarmId() == null) { |
||||
|
throw new DataValidationException("Alarm id should be specified!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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.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<AlarmCommentEntity, UUID> { |
||||
|
|
||||
|
@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 = "" + |
||||
|
"SELECT count(a) " + |
||||
|
"FROM AlarmCommentEntity a " + |
||||
|
"WHERE a.alarmId = :alarmId ") |
||||
|
Page<AlarmCommentInfoEntity> findAllByAlarmId(@Param("alarmId") UUID alarmId, |
||||
|
Pageable pageable); |
||||
|
} |
||||
@ -0,0 +1,99 @@ |
|||||
|
/** |
||||
|
* 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.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.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; |
||||
|
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; |
||||
|
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<AlarmCommentEntity, AlarmComment> implements AlarmCommentDao { |
||||
|
private final SqlPartitioningRepository partitioningRepository; |
||||
|
@Value("${sql.alarm_comments.partition_size:168}") |
||||
|
private int partitionSizeInHours; |
||||
|
|
||||
|
@Autowired |
||||
|
private AlarmCommentRepository alarmCommentRepository; |
||||
|
|
||||
|
@Override |
||||
|
public AlarmComment createAlarmComment(TenantId tenantId, AlarmComment alarmComment){ |
||||
|
log.trace("Saving entity {}", alarmComment); |
||||
|
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(TenantId tenantId, AlarmCommentId alarmCommentId){ |
||||
|
log.trace("Try to delete entity alarm comment by id using [{}]", alarmCommentId); |
||||
|
alarmCommentRepository.deleteById(alarmCommentId.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageData<AlarmCommentInfo> findAlarmComments(TenantId tenantId, AlarmId id, PageLink pageLink){ |
||||
|
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<AlarmComment> findAlarmCommentByIdAsync(TenantId tenantId, UUID key) { |
||||
|
log.trace("Try to find alarm comment by id using [{}]", key); |
||||
|
return findByIdAsync(tenantId, key); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected Class<AlarmCommentEntity> getEntityClass() { |
||||
|
return AlarmCommentEntity.class; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected JpaRepository<AlarmCommentEntity, UUID> getRepository() { |
||||
|
return alarmCommentRepository; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,164 @@ |
|||||
|
/** |
||||
|
* 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; |
||||
|
|
||||
|
import static org.thingsboard.server.common.data.alarm.AlarmCommentType.OTHER; |
||||
|
|
||||
|
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.setFirstName("John"); |
||||
|
user.setLastName("Brown"); |
||||
|
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); |
||||
|
|
||||
|
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<AlarmCommentInfo> alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)); |
||||
|
Assert.assertNotNull(alarmComments.getData()); |
||||
|
Assert.assertEquals(1, alarmComments.getData().size()); |
||||
|
Assert.assertEquals(createdComment, new AlarmComment(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); |
||||
|
|
||||
|
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); |
||||
|
|
||||
|
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<AlarmCommentInfo> alarmComments = alarmCommentService.findAlarmComments(tenantId, alarm.getId(), new PageLink(10, 0)); |
||||
|
Assert.assertNotNull(alarmComments.getData()); |
||||
|
Assert.assertEquals(1, alarmComments.getData().size()); |
||||
|
Assert.assertEquals(updatedComment, new AlarmComment(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); |
||||
|
|
||||
|
Assert.assertNotNull(createdComment); |
||||
|
Assert.assertNotNull(createdComment.getId()); |
||||
|
|
||||
|
alarmCommentService.deleteAlarmComment(tenantId, createdComment.getId()); |
||||
|
|
||||
|
AlarmComment fetched = alarmCommentService.findAlarmCommentByIdAsync(tenantId, createdComment.getId()).get(); |
||||
|
|
||||
|
Assert.assertNull("Alarm comment was returned when it was expected to be null", fetched); |
||||
|
} |
||||
|
} |
||||
@ -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 { |
||||
|
} |
||||
@ -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.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.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; |
||||
|
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, 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); |
||||
|
} |
||||
|
|
||||
|
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, AlarmCommentType 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); |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue