Merge pull request #9035 from imbeacon/customer-removing-alarm-unassign
Fix for alarm unassign on user or customer removed
This commit is contained in:
commit
db663cb5bc
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.service.entitiy.alarm;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -29,20 +30,20 @@ import org.thingsboard.server.common.data.alarm.AlarmComment;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmCommentType;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmInfo;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmQueryV2;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmUpdateRequest;
|
||||
import org.thingsboard.server.common.data.audit.ActionType;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||
import org.thingsboard.server.common.data.id.AlarmId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.UserId;
|
||||
import org.thingsboard.server.common.data.page.TimePageLink;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.page.SortOrder;
|
||||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@ -104,19 +105,8 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
|
||||
}
|
||||
AlarmInfo alarmInfo = result.getAlarm();
|
||||
if (result.isModified()) {
|
||||
AlarmComment alarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.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())
|
||||
.put("subtype", "ACK"))
|
||||
.build();
|
||||
try {
|
||||
alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
|
||||
} catch (ThingsboardException e) {
|
||||
log.error("Failed to save alarm comment", e);
|
||||
}
|
||||
String systemComment = String.format("Alarm was acknowledged by user %s", user.getTitle());
|
||||
addSystemAlarmComment(alarmInfo, user, "ACK", systemComment);
|
||||
notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
|
||||
alarmInfo.getCustomerId(), ActionType.ALARM_ACK, user);
|
||||
} else {
|
||||
@ -138,19 +128,8 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
|
||||
}
|
||||
AlarmInfo alarmInfo = result.getAlarm();
|
||||
if (result.isCleared()) {
|
||||
AlarmComment alarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.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())
|
||||
.put("subtype", "CLEAR"))
|
||||
.build();
|
||||
try {
|
||||
alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
|
||||
} catch (ThingsboardException e) {
|
||||
log.error("Failed to save alarm comment", e);
|
||||
}
|
||||
String systemComment = String.format("Alarm was cleared by user %s", user.getTitle());
|
||||
addSystemAlarmComment(alarmInfo, user, "CLEAR", systemComment);
|
||||
notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
|
||||
alarmInfo.getCustomerId(), ActionType.ALARM_CLEAR, user);
|
||||
} else {
|
||||
@ -168,21 +147,8 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
|
||||
AlarmInfo alarmInfo = result.getAlarm();
|
||||
if (result.isModified()) {
|
||||
AlarmAssignee assignee = alarmInfo.getAssignee();
|
||||
AlarmComment alarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was assigned by user %s to user %s",
|
||||
(user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName(),
|
||||
(assignee.getFirstName() == null || assignee.getLastName() == null) ? assignee.getEmail() : assignee.getFirstName() + " " + assignee.getLastName()))
|
||||
.put("userId", user.getId().toString())
|
||||
.put("assigneeId", assignee.getId().toString())
|
||||
.put("subtype", "ASSIGN"))
|
||||
.build();
|
||||
try {
|
||||
alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
|
||||
} catch (ThingsboardException e) {
|
||||
log.error("Failed to save alarm comment", e);
|
||||
}
|
||||
String systemComment = String.format("Alarm was assigned by user %s to user %s", user.getTitle(), assignee.getTitle());
|
||||
addSystemAlarmComment(alarmInfo, user, "ASSIGN", systemComment, assignee.getId());
|
||||
notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
|
||||
alarmInfo.getCustomerId(), ActionType.ALARM_ASSIGNED, user);
|
||||
} else {
|
||||
@ -199,19 +165,8 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
|
||||
}
|
||||
AlarmInfo alarmInfo = result.getAlarm();
|
||||
if (result.isModified()) {
|
||||
AlarmComment alarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was unassigned by user %s",
|
||||
(user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName()))
|
||||
.put("userId", user.getId().toString())
|
||||
.put("subtype", "ASSIGN"))
|
||||
.build();
|
||||
try {
|
||||
alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
|
||||
} catch (ThingsboardException e) {
|
||||
log.error("Failed to save alarm comment", e);
|
||||
}
|
||||
String systemComment = String.format("Alarm was unassigned by user %s", user.getTitle());
|
||||
addSystemAlarmComment(alarmInfo, user, "ASSIGN", systemComment);
|
||||
notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarmInfo,
|
||||
alarmInfo.getCustomerId(), ActionType.ALARM_UNASSIGNED, user);
|
||||
} else {
|
||||
@ -221,37 +176,20 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unassignUserAlarms(TenantId tenantId, User user, long unassignTs) {
|
||||
AlarmQueryV2 alarmQuery = AlarmQueryV2.builder().assigneeId(user.getId()).pageLink(new TimePageLink(Integer.MAX_VALUE)).build();
|
||||
try {
|
||||
List<AlarmInfo> alarms = alarmService.findAlarmsV2(tenantId, alarmQuery).get(30, TimeUnit.SECONDS).getData();
|
||||
for (AlarmInfo alarm : alarms) {
|
||||
AlarmApiCallResult result = alarmSubscriptionService.unassignAlarm(tenantId, alarm.getId(), getOrDefault(unassignTs));
|
||||
if (!result.isSuccessful()) {
|
||||
continue;
|
||||
public List<AlarmId> unassignDeletedUserAlarms(TenantId tenantId, User user, long unassignTs) {
|
||||
List<AlarmId> totalAlarmIds = new ArrayList<>();
|
||||
PageLink pageLink = new PageLink(100, 0, null, new SortOrder("id", SortOrder.Direction.ASC));
|
||||
while (true) {
|
||||
PageData<AlarmId> pageData = alarmService.findAlarmIdsByAssigneeId(user.getTenantId(), user.getId(), pageLink);
|
||||
List<AlarmId> alarmIds = pageData.getData();
|
||||
if (alarmIds.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
if (result.isModified()) {
|
||||
AlarmComment alarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was unassigned because user %s - was deleted",
|
||||
(user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName()))
|
||||
.put("userId", user.getId().toString())
|
||||
.put("subtype", "ASSIGN"))
|
||||
.build();
|
||||
try {
|
||||
alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
|
||||
} catch (ThingsboardException e) {
|
||||
log.error("Failed to save alarm comment", e);
|
||||
}
|
||||
notificationEntityService.logEntityAction(alarm.getTenantId(), alarm.getOriginator(), result.getAlarm(),
|
||||
alarm.getCustomerId(), ActionType.ALARM_UNASSIGNED, user);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
throw new RuntimeException(e);
|
||||
processAlarmsUnassignment(tenantId, user, alarmIds, unassignTs);
|
||||
totalAlarmIds.addAll(alarmIds);
|
||||
pageLink = pageLink.nextPageLink();
|
||||
}
|
||||
return totalAlarmIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -265,4 +203,46 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
|
||||
private static long getOrDefault(long ts) {
|
||||
return ts > 0 ? ts : System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void processAlarmsUnassignment(TenantId tenantId, User user, List<AlarmId> alarmIds, long unassignTs) {
|
||||
for (AlarmId alarmId : alarmIds) {
|
||||
log.trace("[{}] Unassigning alarm {} userId {}", tenantId, alarmId, user.getId());
|
||||
AlarmApiCallResult result = alarmSubscriptionService.unassignAlarm(user.getTenantId(), alarmId, unassignTs);
|
||||
if (!result.isSuccessful()) {
|
||||
log.error("[{}] Cannot unassign alarm {} userId {}", tenantId, alarmId, user.getId());
|
||||
continue;
|
||||
}
|
||||
if (result.isModified()) {
|
||||
String comment = String.format("Alarm was unassigned because user %s - was deleted", user.getTitle());
|
||||
addSystemAlarmComment(result.getAlarm(), null, "ASSIGN", comment);
|
||||
notificationEntityService.logEntityAction(result.getAlarm().getTenantId(), result.getAlarm().getOriginator(), result.getAlarm(), result.getAlarm().getCustomerId(), ActionType.ALARM_UNASSIGNED, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addSystemAlarmComment(Alarm alarm, User user, String subType, String commentText) {
|
||||
addSystemAlarmComment(alarm, user, subType, commentText, null);
|
||||
}
|
||||
|
||||
private void addSystemAlarmComment(Alarm alarm, User user, String subType, String commentText, UserId assigneeId) {
|
||||
ObjectNode commentNode = JacksonUtil.newObjectNode();
|
||||
commentNode.put("text", commentText)
|
||||
.put("subtype", subType);
|
||||
if (user != null) {
|
||||
commentNode.put("userId", user.getId().getId().toString());
|
||||
}
|
||||
if (assigneeId != null) {
|
||||
commentNode.put("assigneeId", assigneeId.getId().toString());
|
||||
}
|
||||
AlarmComment alarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.comment(commentNode)
|
||||
.build();
|
||||
try {
|
||||
alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
|
||||
} catch (ThingsboardException e) {
|
||||
log.error("Failed to save alarm comment", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,9 +19,12 @@ import org.thingsboard.server.common.data.User;
|
||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmInfo;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||
import org.thingsboard.server.common.data.id.AlarmId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.UserId;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TbAlarmService {
|
||||
|
||||
Alarm save(Alarm entity, User user) throws ThingsboardException;
|
||||
@ -38,7 +41,7 @@ public interface TbAlarmService {
|
||||
|
||||
AlarmInfo unassign(Alarm alarm, long unassignTs, User user) throws ThingsboardException;
|
||||
|
||||
void unassignUserAlarms(TenantId tenantId, User user, long unassignTs);
|
||||
List<AlarmId> unassignDeletedUserAlarms(TenantId tenantId, User user, long unassignTs);
|
||||
|
||||
Boolean delete(Alarm alarm, User user);
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ import org.thingsboard.server.common.data.security.UserCredentials;
|
||||
import org.thingsboard.server.dao.user.UserService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
|
||||
import org.thingsboard.server.service.entitiy.alarm.TbAlarmService;
|
||||
import org.thingsboard.server.service.security.system.SystemSecurityService;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -44,7 +43,6 @@ import static org.thingsboard.server.controller.UserController.ACTIVATE_URL_PATT
|
||||
public class DefaultUserService extends AbstractTbEntityService implements TbUserService {
|
||||
|
||||
private final UserService userService;
|
||||
private final TbAlarmService tbAlarmService;
|
||||
private final MailService mailService;
|
||||
private final SystemSecurityService systemSecurityService;
|
||||
|
||||
@ -64,7 +62,7 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse
|
||||
try {
|
||||
mailService.sendActivationEmail(activateUrl, email);
|
||||
} catch (ThingsboardException e) {
|
||||
userService.deleteUser(tenantId, savedUser.getId());
|
||||
userService.deleteUser(tenantId, savedUser);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -77,17 +75,16 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(TenantId tenantId, CustomerId customerId, User tbUser, User user) throws ThingsboardException {
|
||||
public void delete(TenantId tenantId, CustomerId customerId, User user, User responsibleUser) throws ThingsboardException {
|
||||
ActionType actionType = ActionType.DELETED;
|
||||
UserId userId = tbUser.getId();
|
||||
UserId userId = user.getId();
|
||||
|
||||
try {
|
||||
tbAlarmService.unassignUserAlarms(tbUser.getTenantId(), tbUser, System.currentTimeMillis());
|
||||
userService.deleteUser(tenantId, userId);
|
||||
notificationEntityService.logEntityAction(tenantId, userId, tbUser, customerId, actionType, user, customerId.toString());
|
||||
userService.deleteUser(tenantId, user);
|
||||
notificationEntityService.logEntityAction(tenantId, userId, user, customerId, actionType, responsibleUser, customerId.toString());
|
||||
} catch (Exception e) {
|
||||
notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.USER),
|
||||
actionType, user, e, userId.toString());
|
||||
actionType, responsibleUser, e, userId.toString());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,5 +25,5 @@ import javax.servlet.http.HttpServletRequest;
|
||||
public interface TbUserService {
|
||||
User save(TenantId tenantId, CustomerId customerId, User tbUser, boolean sendActivationMail, HttpServletRequest request, User user) throws ThingsboardException;
|
||||
|
||||
void delete(TenantId tenantId, CustomerId customerId, User tbUser, User user) throws ThingsboardException;
|
||||
void delete(TenantId tenantId, CustomerId customerId, User user, User responsibleUser) throws ThingsboardException;
|
||||
}
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright © 2016-2023 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.housekeeper;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
import org.thingsboard.common.util.ThingsBoardThreadFactory;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.User;
|
||||
import org.thingsboard.server.common.data.id.AlarmId;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
|
||||
import org.thingsboard.server.dao.housekeeper.HouseKeeperService;
|
||||
import org.thingsboard.server.service.entitiy.alarm.TbAlarmService;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class InMemoryHouseKeeperServiceService implements HouseKeeperService {
|
||||
|
||||
final TbAlarmService alarmService;
|
||||
|
||||
ListeningExecutorService executor;
|
||||
|
||||
AtomicInteger queueSize = new AtomicInteger();
|
||||
AtomicInteger totalProcessedCounter = new AtomicInteger();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
log.debug("Starting HouseKeeper service");
|
||||
executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("housekeeper")));
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
if (executor != null) {
|
||||
log.debug("Stopping HouseKeeper service");
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@TransactionalEventListener(fallbackExecution = true)
|
||||
public void handleEvent(DeleteEntityEvent<?> event) {
|
||||
log.trace("[{}] DeleteEntityEvent handler: {}", event.getTenantId(), event);
|
||||
EntityId entityId = event.getEntityId();
|
||||
if (EntityType.USER.equals(entityId.getEntityType())) {
|
||||
unassignDeletedUserAlarms(event.getTenantId(), (User) event.getEntity(), event.getTs());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<List<AlarmId>> unassignDeletedUserAlarms(TenantId tenantId, User user, long unassignTs) {
|
||||
log.debug("[{}][{}] unassignDeletedUserAlarms submitting, pending queue size: {} ", tenantId, user.getId().getId(), queueSize.get());
|
||||
queueSize.incrementAndGet();
|
||||
ListenableFuture<List<AlarmId>> future = executor.submit(() -> alarmService.unassignDeletedUserAlarms(tenantId, user, unassignTs));
|
||||
Futures.addCallback(future, new FutureCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(List<AlarmId> alarmIds) {
|
||||
queueSize.decrementAndGet();
|
||||
totalProcessedCounter.incrementAndGet();
|
||||
log.debug("[{}][{}] unassignDeletedUserAlarms finished, pending queue size: {}, total processed count: {} ",
|
||||
tenantId, user.getId().getId(), queueSize.get(), totalProcessedCounter.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable throwable) {
|
||||
queueSize.decrementAndGet();
|
||||
totalProcessedCounter.incrementAndGet();
|
||||
log.error("[{}][{}] unassignDeletedUserAlarms failed, pending queue size: {}, total processed count: {}",
|
||||
tenantId, user.getId().getId(), queueSize.get(), totalProcessedCounter.get(), throwable);
|
||||
}
|
||||
}, MoreExecutors.directExecutor());
|
||||
return future;
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,6 +18,7 @@ package org.thingsboard.server.controller;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -46,6 +47,8 @@ import org.thingsboard.server.dao.service.DaoSqlTest;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
@ -563,27 +566,28 @@ public class AlarmControllerTest extends AbstractControllerTest {
|
||||
|
||||
alarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
|
||||
Assert.assertNotNull(alarm);
|
||||
AlarmId alarmId = alarm.getId();
|
||||
|
||||
Mockito.reset(tbClusterService, auditLogService);
|
||||
long beforeAssignmentTs = System.currentTimeMillis();
|
||||
|
||||
doPost("/api/alarm/" + alarm.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
|
||||
doPost("/api/alarm/" + alarmId.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
Alarm foundAlarm = doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class);
|
||||
|
||||
Assert.assertNotNull(foundAlarm);
|
||||
Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId());
|
||||
Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
|
||||
|
||||
beforeAssignmentTs = System.currentTimeMillis();
|
||||
|
||||
Mockito.reset(tbClusterService, auditLogService);
|
||||
|
||||
loginSysAdmin();
|
||||
|
||||
doDelete("/api/user/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
|
||||
loginDifferentTenant();
|
||||
|
||||
foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
|
||||
foundAlarm = Awaitility.await().atMost(TIMEOUT, TimeUnit.SECONDS)
|
||||
.until(() -> doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class), Objects::nonNull);
|
||||
|
||||
Assert.assertNotNull(foundAlarm);
|
||||
Assert.assertNull(foundAlarm.getAssigneeId());
|
||||
Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
|
||||
@ -609,15 +613,66 @@ public class AlarmControllerTest extends AbstractControllerTest {
|
||||
.build();
|
||||
alarm = doPost("/api/alarm", alarm, Alarm.class);
|
||||
Assert.assertNotNull(alarm);
|
||||
AlarmId alarmId = alarm.getId();
|
||||
alarm = doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class);
|
||||
Assert.assertNotNull(alarm);
|
||||
long beforeAssignmentTs = System.currentTimeMillis();
|
||||
|
||||
alarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
|
||||
doPost("/api/alarm/" + alarmId.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class);
|
||||
Assert.assertNotNull(foundAlarm);
|
||||
Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId());
|
||||
Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
|
||||
|
||||
beforeAssignmentTs = System.currentTimeMillis();
|
||||
|
||||
doDelete("/api/user/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
|
||||
foundAlarm = Awaitility.await().atMost(TIMEOUT, TimeUnit.SECONDS)
|
||||
.until(() -> doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class), Objects::nonNull);
|
||||
|
||||
Assert.assertNotNull(foundAlarm);
|
||||
Assert.assertNull(foundAlarm.getAssigneeId());
|
||||
Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnassignAlarmOnCustomerRemoving() throws Exception {
|
||||
createDifferentTenantCustomer();
|
||||
loginDifferentTenant();
|
||||
|
||||
User user = new User();
|
||||
user.setAuthority(Authority.CUSTOMER_USER);
|
||||
user.setTenantId(tenantId);
|
||||
user.setCustomerId(differentTenantCustomerId);
|
||||
user.setEmail("customerForAssign@thingsboard.org");
|
||||
User savedUser = createUser(user, "password");
|
||||
|
||||
Device device = createDevice("Different customer device", "default", "differentTenantTest");
|
||||
|
||||
Device assignedDevice = doPost("/api/customer/" + differentTenantCustomerId.getId()
|
||||
+ "/device/" + device.getId().getId(), Device.class);
|
||||
Assert.assertEquals(differentTenantCustomerId, assignedDevice.getCustomerId());
|
||||
|
||||
Alarm alarm = Alarm.builder()
|
||||
.type(TEST_ALARM_TYPE)
|
||||
.tenantId(savedDifferentTenant.getId())
|
||||
.customerId(differentTenantCustomerId)
|
||||
.originator(device.getId())
|
||||
.severity(AlarmSeverity.MAJOR)
|
||||
.build();
|
||||
alarm = doPost("/api/alarm", alarm, Alarm.class);
|
||||
Assert.assertNotNull(alarm);
|
||||
AlarmId alarmId = alarm.getId();
|
||||
|
||||
alarm = doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class);
|
||||
Assert.assertNotNull(alarm);
|
||||
|
||||
Mockito.reset(tbClusterService, auditLogService);
|
||||
long beforeAssignmentTs = System.currentTimeMillis();
|
||||
|
||||
doPost("/api/alarm/" + alarm.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
|
||||
doPost("/api/alarm/" + alarmId.getId() + "/assign/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
AlarmInfo foundAlarm = doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class);
|
||||
Assert.assertNotNull(foundAlarm);
|
||||
Assert.assertEquals(savedUser.getId(), foundAlarm.getAssigneeId());
|
||||
Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
|
||||
@ -626,9 +681,11 @@ public class AlarmControllerTest extends AbstractControllerTest {
|
||||
|
||||
Mockito.reset(tbClusterService, auditLogService);
|
||||
|
||||
doDelete("/api/user/" + savedUser.getId().getId()).andExpect(status().isOk());
|
||||
doDelete("/api/customer/" + differentTenantCustomerId.getId()).andExpect(status().isOk());
|
||||
|
||||
foundAlarm = Awaitility.await().atMost(TIMEOUT, TimeUnit.SECONDS)
|
||||
.until(() -> doGet("/api/alarm/info/" + alarmId.getId(), AlarmInfo.class), Objects::nonNull);
|
||||
|
||||
foundAlarm = doGet("/api/alarm/info/" + alarm.getId(), AlarmInfo.class);
|
||||
Assert.assertNotNull(foundAlarm);
|
||||
Assert.assertNull(foundAlarm.getAssigneeId());
|
||||
Assert.assertTrue(foundAlarm.getAssignTs() >= beforeAssignmentTs);
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.service.entitiy.alarm;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -23,14 +24,20 @@ 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.common.util.JacksonUtil;
|
||||
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.AlarmApiCallResult;
|
||||
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.audit.ActionType;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||
import org.thingsboard.server.common.data.id.AlarmId;
|
||||
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.dao.alarm.AlarmService;
|
||||
import org.thingsboard.server.dao.customer.CustomerService;
|
||||
import org.thingsboard.server.dao.edge.EdgeService;
|
||||
@ -39,6 +46,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.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@ -74,7 +83,6 @@ public class DefaultTbAlarmServiceTest {
|
||||
protected TbClusterService tbClusterService;
|
||||
@MockBean
|
||||
private EntitiesVersionControlService vcService;
|
||||
|
||||
@SpyBean
|
||||
DefaultTbAlarmService service;
|
||||
|
||||
@ -124,4 +132,61 @@ public class DefaultTbAlarmServiceTest {
|
||||
verify(notificationEntityService, times(1)).logEntityAction(any(), any(), any(), any(), eq(ActionType.DELETED), any());
|
||||
verify(alarmSubscriptionService, times(1)).deleteAlarm(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnassignAlarm() throws ThingsboardException {
|
||||
AlarmInfo alarm = new AlarmInfo();
|
||||
alarm.setId(new AlarmId(UUID.randomUUID()));
|
||||
when(alarmSubscriptionService.unassignAlarm(any(), any(), anyLong()))
|
||||
.thenReturn(AlarmApiCallResult.builder().successful(true).modified(true).alarm(alarm).build());
|
||||
|
||||
User user = new User();
|
||||
user.setEmail("testEmail@gmail.com");
|
||||
user.setId(new UserId(UUID.randomUUID()));
|
||||
service.unassign(new Alarm(), 0L, user);
|
||||
|
||||
ObjectNode commentNode = JacksonUtil.newObjectNode();
|
||||
commentNode.put("subtype", "ASSIGN");
|
||||
commentNode.put("text", "Alarm was unassigned by user " + user.getTitle());
|
||||
commentNode.put("userId", user.getId().getId().toString());
|
||||
AlarmComment expectedAlarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.comment(commentNode)
|
||||
.build();
|
||||
|
||||
verify(alarmCommentService, times(1))
|
||||
.saveAlarmComment(eq(alarm), eq(expectedAlarmComment), eq(user));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnassignDeletedUserAlarms() throws ThingsboardException {
|
||||
AlarmInfo alarm = new AlarmInfo();
|
||||
alarm.setId(new AlarmId(UUID.randomUUID()));
|
||||
|
||||
when(alarmService.findAlarmIdsByAssigneeId(any(), any(), any()))
|
||||
.thenReturn(new PageData<>(List.of(alarm.getId()), 0, 1, false))
|
||||
.thenReturn(new PageData<>(Collections.EMPTY_LIST, 0, 0, false));
|
||||
when(alarmSubscriptionService.unassignAlarm(any(), any(), anyLong()))
|
||||
.thenReturn(AlarmApiCallResult.builder().successful(true).modified(true).alarm(alarm).build());
|
||||
|
||||
User user = new User();
|
||||
user.setEmail("testEmail@gmail.com");
|
||||
user.setId(new UserId(UUID.randomUUID()));
|
||||
service.unassignDeletedUserAlarms(new TenantId(UUID.randomUUID()), user, System.currentTimeMillis());
|
||||
|
||||
ObjectNode commentNode = JacksonUtil.newObjectNode();
|
||||
commentNode.put("subtype", "ASSIGN");
|
||||
commentNode.put("text", String.format("Alarm was unassigned because user %s - was deleted", user.getTitle()));
|
||||
AlarmComment expectedAlarmComment = AlarmComment.builder()
|
||||
.alarmId(alarm.getId())
|
||||
.type(AlarmCommentType.SYSTEM)
|
||||
.comment(commentNode)
|
||||
.build();
|
||||
|
||||
verify(alarmCommentService, times(1))
|
||||
.saveAlarmComment(eq(alarm), eq(expectedAlarmComment), eq(null));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.id.EntityId;
|
||||
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.query.AlarmCountQuery;
|
||||
import org.thingsboard.server.common.data.query.AlarmData;
|
||||
import org.thingsboard.server.common.data.query.AlarmDataQuery;
|
||||
@ -118,6 +119,8 @@ public interface AlarmService extends EntityDaoService {
|
||||
PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId,
|
||||
AlarmDataQuery query, Collection<EntityId> orderedEntityIds);
|
||||
|
||||
PageData<AlarmId> findAlarmIdsByAssigneeId(TenantId tenantId, UserId userId, PageLink pageLink);
|
||||
|
||||
void deleteEntityAlarmRelations(TenantId tenantId, EntityId entityId);
|
||||
|
||||
long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query);
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright © 2016-2023 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.housekeeper;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import org.thingsboard.server.common.data.User;
|
||||
import org.thingsboard.server.common.data.id.AlarmId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface HouseKeeperService {
|
||||
|
||||
ListenableFuture<List<AlarmId>> unassignDeletedUserAlarms(TenantId tenantId, User user, long unassignTs);
|
||||
|
||||
}
|
||||
@ -57,7 +57,7 @@ public interface UserService extends EntityDaoService {
|
||||
|
||||
UserCredentials replaceUserCredentials(TenantId tenantId, UserCredentials userCredentials);
|
||||
|
||||
void deleteUser(TenantId tenantId, UserId userId);
|
||||
void deleteUser(TenantId tenantId, User user);
|
||||
|
||||
PageData<User> findUsersByTenantId(TenantId tenantId, PageLink pageLink);
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.common.data.alarm;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -22,6 +23,8 @@ import org.thingsboard.server.common.data.id.UserId;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
|
||||
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
@ -34,4 +37,22 @@ public class AlarmAssignee implements Serializable {
|
||||
private final String lastName;
|
||||
private final String email;
|
||||
|
||||
@JsonIgnore
|
||||
public String getTitle() {
|
||||
String title = "";
|
||||
if (isNotEmpty(firstName)) {
|
||||
title += firstName;
|
||||
}
|
||||
if (isNotEmpty(lastName)) {
|
||||
if (!title.isEmpty()) {
|
||||
title += " ";
|
||||
}
|
||||
title += lastName;
|
||||
}
|
||||
if (title.isEmpty()) {
|
||||
title = email;
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.thingsboard.server.common.data.BaseData;
|
||||
import org.thingsboard.server.common.data.HasName;
|
||||
import org.thingsboard.server.common.data.id.AlarmCommentId;
|
||||
@ -44,6 +45,7 @@ public class AlarmComment extends BaseData<AlarmCommentId> implements HasName {
|
||||
@ApiModelProperty(position = 6, value = "JSON object with text of comment.", dataType = "com.fasterxml.jackson.databind.JsonNode")
|
||||
@NoXss
|
||||
@Length(fieldName = "comment", max = 10000)
|
||||
@EqualsAndHashCode.Include
|
||||
private transient JsonNode comment;
|
||||
|
||||
@ApiModelProperty(position = 1, value = "JSON object with the alarm comment Id. " +
|
||||
|
||||
@ -33,6 +33,7 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class DaoUtil {
|
||||
|
||||
@ -109,6 +110,10 @@ public abstract class DaoUtil {
|
||||
return ids;
|
||||
}
|
||||
|
||||
public static <I> List<I> fromUUIDs(List<UUID> uuids, Function<UUID, I> mapper) {
|
||||
return uuids.stream().map(mapper).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static <I> I toEntityId(UUID uuid, Function<UUID, I> creator) {
|
||||
if (uuid != null) {
|
||||
return creator.apply(uuid);
|
||||
|
||||
@ -77,6 +77,8 @@ public interface AlarmDao extends Dao<Alarm> {
|
||||
|
||||
PageData<AlarmId> findAlarmsIdsByEndTsBeforeAndTenantId(Long time, TenantId tenantId, PageLink pageLink);
|
||||
|
||||
PageData<AlarmId> findAlarmIdsByAssigneeId(TenantId tenantId, UUID userId, PageLink pageLink);
|
||||
|
||||
void createEntityAlarmRecord(EntityAlarm entityAlarm);
|
||||
|
||||
List<EntityAlarm> findEntityAlarmRecords(TenantId tenantId, AlarmId id);
|
||||
|
||||
@ -48,6 +48,7 @@ import org.thingsboard.server.common.data.id.HasId;
|
||||
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.query.AlarmCountQuery;
|
||||
import org.thingsboard.server.common.data.query.AlarmData;
|
||||
import org.thingsboard.server.common.data.query.AlarmDataQuery;
|
||||
@ -384,6 +385,13 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
|
||||
return Futures.immediateFuture(alarmDao.findCustomerAlarmsV2(tenantId, customerId, query));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<AlarmId> findAlarmIdsByAssigneeId(TenantId tenantId, UserId userId, PageLink pageLink) {
|
||||
log.trace("[{}] Executing findAlarmIdsByAssigneeId [{}]", tenantId, userId);
|
||||
validateId(userId, "Incorrect userId " + userId);
|
||||
return alarmDao.findAlarmIdsByAssigneeId(tenantId, userId.getId(), pageLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus,
|
||||
AlarmStatus alarmStatus, String assigneeId) {
|
||||
@ -522,5 +530,4 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
|
||||
request.setEndTs(request.getStartTs());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -28,4 +28,7 @@ public class DeleteEntityEvent<T> {
|
||||
private final EntityId entityId;
|
||||
private final EdgeId edgeId;
|
||||
private final T entity;
|
||||
|
||||
@Builder.Default
|
||||
private final long ts = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ 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.common.data.alarm.AlarmSeverity;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.model.sql.AlarmEntity;
|
||||
import org.thingsboard.server.dao.model.sql.AlarmInfoEntity;
|
||||
|
||||
@ -315,6 +316,9 @@ public interface AlarmRepository extends JpaRepository<AlarmEntity, UUID> {
|
||||
@Query(value = "SELECT a FROM AlarmInfoEntity a WHERE a.tenantId = :tenantId AND a.id = :alarmId")
|
||||
AlarmInfoEntity findAlarmInfoById(@Param("tenantId") UUID tenantId, @Param("alarmId") UUID alarmId);
|
||||
|
||||
@Query("SELECT a.id FROM AlarmEntity a WHERE a.tenantId = :tenantId AND a.assigneeId = :assigneeId")
|
||||
Page<UUID> findAlarmIdsByAssigneeId(@Param("tenantId") UUID tenantId, @Param("assigneeId") UUID assigneeId, Pageable pageable);
|
||||
|
||||
@Query(value = "SELECT create_or_update_active_alarm(:t_id, :c_id, :a_id, :a_created_ts, :a_o_id, :a_o_type, :a_type, :a_severity, " +
|
||||
":a_start_ts, :a_end_ts, :a_details, :a_propagate, :a_propagate_to_owner, " +
|
||||
":a_propagate_to_tenant, :a_propagation_types, :a_creation_enabled)", nativeQuery = true)
|
||||
|
||||
@ -285,6 +285,12 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
|
||||
.mapData(AlarmId::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<AlarmId> findAlarmIdsByAssigneeId(TenantId tenantId, UUID userId, PageLink pageLink) {
|
||||
return DaoUtil.pageToPageData(alarmRepository.findAlarmIdsByAssigneeId(tenantId.getId(), userId, DaoUtil.toPageable(pageLink)))
|
||||
.mapData(AlarmId::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createEntityAlarmRecord(EntityAlarm entityAlarm) {
|
||||
log.debug("Saving entity {}", entityAlarm);
|
||||
|
||||
@ -55,6 +55,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.thingsboard.server.common.data.StringUtils.generateSafeToken;
|
||||
@ -246,8 +247,10 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteUser(TenantId tenantId, UserId userId) {
|
||||
log.trace("Executing deleteUser [{}]", userId);
|
||||
public void deleteUser(TenantId tenantId, User user) {
|
||||
Objects.requireNonNull(user, "User is null");
|
||||
UserId userId = user.getId();
|
||||
log.trace("[{}] Executing deleteUser [{}]", tenantId, userId);
|
||||
validateId(userId, INCORRECT_USER_ID + userId);
|
||||
UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, userId.getId());
|
||||
userCredentialsDao.removeById(tenantId, userCredentials.getUuidId());
|
||||
@ -258,7 +261,8 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
|
||||
countService.publishCountEntityEvictEvent(tenantId, EntityType.USER);
|
||||
eventPublisher.publishEvent(DeleteEntityEvent.builder()
|
||||
.tenantId(tenantId)
|
||||
.entityId(userId).build());
|
||||
.entityId(userId)
|
||||
.entity(user).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -443,7 +447,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
|
||||
|
||||
@Override
|
||||
protected void removeEntity(TenantId tenantId, User entity) {
|
||||
deleteUser(tenantId, new UserId(entity.getUuidId()));
|
||||
deleteUser(tenantId, entity);
|
||||
}
|
||||
};
|
||||
|
||||
@ -456,7 +460,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
|
||||
|
||||
@Override
|
||||
protected void removeEntity(TenantId tenantId, User entity) {
|
||||
deleteUser(tenantId, new UserId(entity.getUuidId()));
|
||||
deleteUser(tenantId, entity);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright © 2016-2023 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.eventsourcing;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.BDDAssertions.byLessThan;
|
||||
|
||||
class DeleteEntityEventTest {
|
||||
|
||||
@Test
|
||||
void testBuilderDefaultTs() {
|
||||
assertThat(DeleteEntityEvent.builder().build().getTs())
|
||||
.isCloseTo(System.currentTimeMillis(), byLessThan(TimeUnit.MINUTES.toMillis(1)));
|
||||
|
||||
assertThat(DeleteEntityEvent.builder().ts(Long.MIN_VALUE).build().getTs())
|
||||
.isEqualTo(Long.MIN_VALUE);
|
||||
assertThat(DeleteEntityEvent.builder().ts(Long.MAX_VALUE).build().getTs())
|
||||
.isEqualTo(Long.MAX_VALUE);
|
||||
assertThat(DeleteEntityEvent.builder().ts(-1L).build().getTs())
|
||||
.isEqualTo(-1L);
|
||||
assertThat(DeleteEntityEvent.builder().ts(0L).build().getTs())
|
||||
.isEqualTo(0L);
|
||||
|
||||
assertThat(DeleteEntityEvent.builder().ts(1692175215000L).build().getTs())
|
||||
.isEqualTo(1692175215000L);
|
||||
}
|
||||
|
||||
}
|
||||
@ -135,7 +135,7 @@ public class UserServiceTest extends AbstractServiceTest {
|
||||
Assert.assertEquals("Joe", savedUser.getFirstName());
|
||||
Assert.assertEquals("Downs", savedUser.getLastName());
|
||||
|
||||
userService.deleteUser(tenantId, savedUser.getId());
|
||||
userService.deleteUser(tenantId, savedUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -188,7 +188,7 @@ public class UserServiceTest extends AbstractServiceTest {
|
||||
Assert.assertNotNull(foundUser);
|
||||
UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, foundUser.getId());
|
||||
Assert.assertNotNull(userCredentials);
|
||||
userService.deleteUser(tenantId, foundUser.getId());
|
||||
userService.deleteUser(tenantId, foundUser);
|
||||
userCredentials = userService.findUserCredentialsByUserId(tenantId, foundUser.getId());
|
||||
foundUser = userService.findUserById(tenantId, foundUser.getId());
|
||||
Assert.assertNull(foundUser);
|
||||
@ -301,7 +301,7 @@ public class UserServiceTest extends AbstractServiceTest {
|
||||
Assert.assertEquals(tenantAdminsEmail2, loadedTenantAdminsEmail2);
|
||||
|
||||
for (User user : loadedTenantAdminsEmail1) {
|
||||
userService.deleteUser(tenantId, user.getId());
|
||||
userService.deleteUser(tenantId, user);
|
||||
}
|
||||
|
||||
pageLink = new PageLink(4, 0, email1);
|
||||
@ -310,7 +310,7 @@ public class UserServiceTest extends AbstractServiceTest {
|
||||
Assert.assertEquals(0, pageData.getData().size());
|
||||
|
||||
for (User user : loadedTenantAdminsEmail2) {
|
||||
userService.deleteUser(tenantId, user.getId());
|
||||
userService.deleteUser(tenantId, user);
|
||||
}
|
||||
|
||||
pageLink = new PageLink(4, 0, email2);
|
||||
@ -440,7 +440,7 @@ public class UserServiceTest extends AbstractServiceTest {
|
||||
Assert.assertEquals(customerUsersEmail2, loadedCustomerUsersEmail2);
|
||||
|
||||
for (User user : loadedCustomerUsersEmail1) {
|
||||
userService.deleteUser(tenantId, user.getId());
|
||||
userService.deleteUser(tenantId, user);
|
||||
}
|
||||
|
||||
pageLink = new PageLink(4, 0, email1);
|
||||
@ -449,7 +449,7 @@ public class UserServiceTest extends AbstractServiceTest {
|
||||
Assert.assertEquals(0, pageData.getData().size());
|
||||
|
||||
for (User user : loadedCustomerUsersEmail2) {
|
||||
userService.deleteUser(tenantId, user.getId());
|
||||
userService.deleteUser(tenantId, user);
|
||||
}
|
||||
|
||||
pageLink = new PageLink(4, 0, email2);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user