Commit ac007bea24ef4244190690a173c6ef323cb0258e
Committed by
Andrew Shvayka
1 parent
a400bdb9
device swap feature init
Showing
21 changed files
with
272 additions
and
24 deletions
@@ -15,6 +15,7 @@ | @@ -15,6 +15,7 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.controller; | 16 | package org.thingsboard.server.controller; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.core.JsonProcessingException; | ||
18 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
19 | import com.fasterxml.jackson.databind.node.ArrayNode; | 20 | import com.fasterxml.jackson.databind.node.ArrayNode; |
20 | import com.fasterxml.jackson.databind.node.ObjectNode; | 21 | import com.fasterxml.jackson.databind.node.ObjectNode; |
@@ -26,7 +27,6 @@ import org.springframework.beans.factory.annotation.Value; | @@ -26,7 +27,6 @@ import org.springframework.beans.factory.annotation.Value; | ||
26 | import org.springframework.security.core.Authentication; | 27 | import org.springframework.security.core.Authentication; |
27 | import org.springframework.security.core.context.SecurityContextHolder; | 28 | import org.springframework.security.core.context.SecurityContextHolder; |
28 | import org.springframework.web.bind.annotation.ExceptionHandler; | 29 | import org.springframework.web.bind.annotation.ExceptionHandler; |
29 | -import org.thingsboard.server.common.data.BaseData; | ||
30 | import org.thingsboard.server.common.data.Customer; | 30 | import org.thingsboard.server.common.data.Customer; |
31 | import org.thingsboard.server.common.data.Dashboard; | 31 | import org.thingsboard.server.common.data.Dashboard; |
32 | import org.thingsboard.server.common.data.DashboardInfo; | 32 | import org.thingsboard.server.common.data.DashboardInfo; |
@@ -39,12 +39,12 @@ import org.thingsboard.server.common.data.HasTenantId; | @@ -39,12 +39,12 @@ import org.thingsboard.server.common.data.HasTenantId; | ||
39 | import org.thingsboard.server.common.data.Tenant; | 39 | import org.thingsboard.server.common.data.Tenant; |
40 | import org.thingsboard.server.common.data.User; | 40 | import org.thingsboard.server.common.data.User; |
41 | import org.thingsboard.server.common.data.alarm.Alarm; | 41 | import org.thingsboard.server.common.data.alarm.Alarm; |
42 | -import org.thingsboard.server.common.data.id.AlarmId; | ||
43 | import org.thingsboard.server.common.data.alarm.AlarmInfo; | 42 | import org.thingsboard.server.common.data.alarm.AlarmInfo; |
44 | import org.thingsboard.server.common.data.asset.Asset; | 43 | import org.thingsboard.server.common.data.asset.Asset; |
45 | import org.thingsboard.server.common.data.audit.ActionType; | 44 | import org.thingsboard.server.common.data.audit.ActionType; |
46 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 45 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
47 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 46 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
47 | +import org.thingsboard.server.common.data.id.AlarmId; | ||
48 | import org.thingsboard.server.common.data.id.AssetId; | 48 | import org.thingsboard.server.common.data.id.AssetId; |
49 | import org.thingsboard.server.common.data.id.CustomerId; | 49 | import org.thingsboard.server.common.data.id.CustomerId; |
50 | import org.thingsboard.server.common.data.id.DashboardId; | 50 | import org.thingsboard.server.common.data.id.DashboardId; |
@@ -595,6 +595,12 @@ public abstract class BaseController { | @@ -595,6 +595,12 @@ public abstract class BaseController { | ||
595 | case ALARM_CLEAR: | 595 | case ALARM_CLEAR: |
596 | msgType = DataConstants.ALARM_CLEAR; | 596 | msgType = DataConstants.ALARM_CLEAR; |
597 | break; | 597 | break; |
598 | + case SWAPPED_FROM_TENANT: | ||
599 | + msgType = DataConstants.ENTITY_SWAPPED_FROM; | ||
600 | + break; | ||
601 | + case SWAPPED_TO_TENANT: | ||
602 | + msgType = DataConstants.ENTITY_SWAPPED_TO; | ||
603 | + break; | ||
598 | } | 604 | } |
599 | if (!StringUtils.isEmpty(msgType)) { | 605 | if (!StringUtils.isEmpty(msgType)) { |
600 | try { | 606 | try { |
@@ -614,6 +620,16 @@ public abstract class BaseController { | @@ -614,6 +620,16 @@ public abstract class BaseController { | ||
614 | String strCustomerName = extractParameter(String.class, 2, additionalInfo); | 620 | String strCustomerName = extractParameter(String.class, 2, additionalInfo); |
615 | metaData.putValue("unassignedCustomerId", strCustomerId); | 621 | metaData.putValue("unassignedCustomerId", strCustomerId); |
616 | metaData.putValue("unassignedCustomerName", strCustomerName); | 622 | metaData.putValue("unassignedCustomerName", strCustomerName); |
623 | + } else if (actionType == ActionType.SWAPPED_FROM_TENANT) { | ||
624 | + String strTenantId = extractParameter(String.class, 0, additionalInfo); | ||
625 | + String strTenantName = extractParameter(String.class, 1, additionalInfo); | ||
626 | + metaData.putValue("swappedFromTenantId", strTenantId); | ||
627 | + metaData.putValue("swappedFromTenantName", strTenantName); | ||
628 | + } else if (actionType == ActionType.SWAPPED_TO_TENANT) { | ||
629 | + String strTenantId = extractParameter(String.class, 0, additionalInfo); | ||
630 | + String strTenantName = extractParameter(String.class, 1, additionalInfo); | ||
631 | + metaData.putValue("swappedToTenantId", strTenantId); | ||
632 | + metaData.putValue("swappedToTenantName", strTenantName); | ||
617 | } | 633 | } |
618 | ObjectNode entityNode; | 634 | ObjectNode entityNode; |
619 | if (entity != null) { | 635 | if (entity != null) { |
@@ -677,5 +693,13 @@ public abstract class BaseController { | @@ -677,5 +693,13 @@ public abstract class BaseController { | ||
677 | return result; | 693 | return result; |
678 | } | 694 | } |
679 | 695 | ||
696 | + protected <E extends HasName> String entityToStr(E entity) { | ||
697 | + try { | ||
698 | + return json.writeValueAsString(json.valueToTree(entity)); | ||
699 | + } catch (JsonProcessingException e) { | ||
700 | + log.warn("[{}] Failed to convert entity to string!", entity, e); | ||
701 | + } | ||
702 | + return null; | ||
703 | + } | ||
680 | 704 | ||
681 | } | 705 | } |
@@ -39,8 +39,10 @@ import org.thingsboard.server.common.data.DataConstants; | @@ -39,8 +39,10 @@ import org.thingsboard.server.common.data.DataConstants; | ||
39 | import org.thingsboard.server.common.data.Device; | 39 | import org.thingsboard.server.common.data.Device; |
40 | import org.thingsboard.server.common.data.EntitySubtype; | 40 | import org.thingsboard.server.common.data.EntitySubtype; |
41 | import org.thingsboard.server.common.data.EntityType; | 41 | import org.thingsboard.server.common.data.EntityType; |
42 | +import org.thingsboard.server.common.data.Tenant; | ||
42 | import org.thingsboard.server.common.data.audit.ActionType; | 43 | import org.thingsboard.server.common.data.audit.ActionType; |
43 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; | 44 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
45 | +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | ||
44 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 46 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
45 | import org.thingsboard.server.common.data.id.CustomerId; | 47 | import org.thingsboard.server.common.data.id.CustomerId; |
46 | import org.thingsboard.server.common.data.id.DeviceId; | 48 | import org.thingsboard.server.common.data.id.DeviceId; |
@@ -48,6 +50,9 @@ import org.thingsboard.server.common.data.id.TenantId; | @@ -48,6 +50,9 @@ import org.thingsboard.server.common.data.id.TenantId; | ||
48 | import org.thingsboard.server.common.data.page.TextPageData; | 50 | import org.thingsboard.server.common.data.page.TextPageData; |
49 | import org.thingsboard.server.common.data.page.TextPageLink; | 51 | import org.thingsboard.server.common.data.page.TextPageLink; |
50 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 52 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
53 | +import org.thingsboard.server.common.msg.TbMsg; | ||
54 | +import org.thingsboard.server.common.msg.TbMsgDataType; | ||
55 | +import org.thingsboard.server.common.msg.TbMsgMetaData; | ||
51 | import org.thingsboard.server.dao.device.claim.ClaimResponse; | 56 | import org.thingsboard.server.dao.device.claim.ClaimResponse; |
52 | import org.thingsboard.server.dao.device.claim.ClaimResult; | 57 | import org.thingsboard.server.dao.device.claim.ClaimResult; |
53 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 58 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
@@ -70,6 +75,7 @@ public class DeviceController extends BaseController { | @@ -70,6 +75,7 @@ public class DeviceController extends BaseController { | ||
70 | 75 | ||
71 | private static final String DEVICE_ID = "deviceId"; | 76 | private static final String DEVICE_ID = "deviceId"; |
72 | private static final String DEVICE_NAME = "deviceName"; | 77 | private static final String DEVICE_NAME = "deviceName"; |
78 | + private static final String TENANT_ID = "tenantId"; | ||
73 | 79 | ||
74 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 80 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
75 | @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET) | 81 | @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET) |
@@ -481,4 +487,54 @@ public class DeviceController extends BaseController { | @@ -481,4 +487,54 @@ public class DeviceController extends BaseController { | ||
481 | } | 487 | } |
482 | return DataConstants.DEFAULT_SECRET_KEY; | 488 | return DataConstants.DEFAULT_SECRET_KEY; |
483 | } | 489 | } |
490 | + | ||
491 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
492 | + @RequestMapping(value = "/tenant/{tenantId}/device/{deviceId}", method = RequestMethod.POST) | ||
493 | + @ResponseBody | ||
494 | + public Device swapDevice(@PathVariable(TENANT_ID) String strTenantId, | ||
495 | + @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { | ||
496 | + checkParameter(TENANT_ID, strTenantId); | ||
497 | + checkParameter(DEVICE_ID, strDeviceId); | ||
498 | + try { | ||
499 | + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); | ||
500 | + Device device = checkDeviceId(deviceId, Operation.WRITE); | ||
501 | + | ||
502 | + TenantId newTenantId = new TenantId(toUUID(strTenantId)); | ||
503 | + Tenant newTenant = tenantService.findTenantById(newTenantId); | ||
504 | + if (newTenant == null) { | ||
505 | + throw new ThingsboardException("Could not find the specified Tenant!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); | ||
506 | + } | ||
507 | + | ||
508 | + Device swappedDevice = deviceService.swapDevice(newTenantId, device); | ||
509 | + | ||
510 | + logEntityAction(getCurrentUser(), deviceId, swappedDevice, | ||
511 | + swappedDevice.getCustomerId(), | ||
512 | + ActionType.SWAPPED_TO_TENANT, null, strTenantId, newTenant.getName()); | ||
513 | + | ||
514 | + Tenant currentTenant = tenantService.findTenantById(getTenantId()); | ||
515 | + pushSwappedFromNotification(currentTenant, newTenantId, swappedDevice); | ||
516 | + | ||
517 | + return swappedDevice; | ||
518 | + } catch (Exception e) { | ||
519 | + logEntityAction(getCurrentUser(), emptyId(EntityType.DEVICE), null, | ||
520 | + null, | ||
521 | + ActionType.SWAPPED_TO_TENANT, e, strTenantId); | ||
522 | + throw handleException(e); | ||
523 | + } | ||
524 | + } | ||
525 | + | ||
526 | + private void pushSwappedFromNotification(Tenant currentTenant, TenantId newTenantId, Device swappedDevice) { | ||
527 | + String data = entityToStr(swappedDevice); | ||
528 | + if (data != null) { | ||
529 | + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_SWAPPED_FROM, swappedDevice.getId(), getMetaDataForSwappedFrom(currentTenant), TbMsgDataType.JSON, data); | ||
530 | + tbClusterService.pushMsgToRuleEngine(newTenantId, swappedDevice.getId(), tbMsg, null); | ||
531 | + } | ||
532 | + } | ||
533 | + | ||
534 | + private TbMsgMetaData getMetaDataForSwappedFrom(Tenant tenant) { | ||
535 | + TbMsgMetaData metaData = new TbMsgMetaData(); | ||
536 | + metaData.putValue("swappedFromTenantId", tenant.getId().getId().toString()); | ||
537 | + metaData.putValue("swappedFromTenantName", tenant.getName()); | ||
538 | + return metaData; | ||
539 | + } | ||
484 | } | 540 | } |
@@ -16,14 +16,12 @@ | @@ -16,14 +16,12 @@ | ||
16 | package org.thingsboard.server.dao.audit; | 16 | package org.thingsboard.server.dao.audit; |
17 | 17 | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | -import org.thingsboard.server.common.data.BaseData; | ||
20 | import org.thingsboard.server.common.data.HasName; | 19 | import org.thingsboard.server.common.data.HasName; |
21 | import org.thingsboard.server.common.data.audit.ActionType; | 20 | import org.thingsboard.server.common.data.audit.ActionType; |
22 | import org.thingsboard.server.common.data.audit.AuditLog; | 21 | import org.thingsboard.server.common.data.audit.AuditLog; |
23 | import org.thingsboard.server.common.data.id.CustomerId; | 22 | import org.thingsboard.server.common.data.id.CustomerId; |
24 | import org.thingsboard.server.common.data.id.EntityId; | 23 | import org.thingsboard.server.common.data.id.EntityId; |
25 | import org.thingsboard.server.common.data.id.TenantId; | 24 | import org.thingsboard.server.common.data.id.TenantId; |
26 | -import org.thingsboard.server.common.data.id.UUIDBased; | ||
27 | import org.thingsboard.server.common.data.id.UserId; | 25 | import org.thingsboard.server.common.data.id.UserId; |
28 | import org.thingsboard.server.common.data.page.TimePageData; | 26 | import org.thingsboard.server.common.data.page.TimePageData; |
29 | import org.thingsboard.server.common.data.page.TimePageLink; | 27 | import org.thingsboard.server.common.data.page.TimePageLink; |
@@ -50,4 +48,5 @@ public interface AuditLogService { | @@ -50,4 +48,5 @@ public interface AuditLogService { | ||
50 | ActionType actionType, | 48 | ActionType actionType, |
51 | Exception e, Object... additionalInfo); | 49 | Exception e, Object... additionalInfo); |
52 | 50 | ||
51 | + void removeAuditLogs(TenantId tenantId, EntityId entityId); | ||
53 | } | 52 | } |
@@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; | @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; | ||
28 | import java.util.List; | 28 | import java.util.List; |
29 | 29 | ||
30 | public interface DeviceService { | 30 | public interface DeviceService { |
31 | - | 31 | + |
32 | Device findDeviceById(TenantId tenantId, DeviceId deviceId); | 32 | Device findDeviceById(TenantId tenantId, DeviceId deviceId); |
33 | 33 | ||
34 | ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId); | 34 | ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId); |
@@ -65,4 +65,6 @@ public interface DeviceService { | @@ -65,4 +65,6 @@ public interface DeviceService { | ||
65 | 65 | ||
66 | ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId); | 66 | ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId); |
67 | 67 | ||
68 | + Device swapDevice(TenantId tenantId, Device device); | ||
69 | + | ||
68 | } | 70 | } |
@@ -41,4 +41,6 @@ public interface EventService { | @@ -41,4 +41,6 @@ public interface EventService { | ||
41 | 41 | ||
42 | List<Event> findLatestEvents(TenantId tenantId, EntityId entityId, String eventType, int limit); | 42 | List<Event> findLatestEvents(TenantId tenantId, EntityId entityId, String eventType, int limit); |
43 | 43 | ||
44 | + void removeEvents(TenantId tenantId, EntityId entityId); | ||
45 | + | ||
44 | } | 46 | } |
@@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; | @@ -24,7 +24,6 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; | ||
24 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 24 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
25 | 25 | ||
26 | import java.util.List; | 26 | import java.util.List; |
27 | -import java.util.concurrent.ExecutionException; | ||
28 | 27 | ||
29 | /** | 28 | /** |
30 | * Created by ashvayka on 27.04.17. | 29 | * Created by ashvayka on 27.04.17. |
@@ -77,6 +76,8 @@ public interface RelationService { | @@ -77,6 +76,8 @@ public interface RelationService { | ||
77 | 76 | ||
78 | ListenableFuture<List<EntityRelationInfo>> findInfoByQuery(TenantId tenantId, EntityRelationsQuery query); | 77 | ListenableFuture<List<EntityRelationInfo>> findInfoByQuery(TenantId tenantId, EntityRelationsQuery query); |
79 | 78 | ||
79 | + void removeRelations(TenantId tenantId, EntityId entityId); | ||
80 | + | ||
80 | // TODO: This method may be useful for some validations in the future | 81 | // TODO: This method may be useful for some validations in the future |
81 | // ListenableFuture<Boolean> checkRecursiveRelation(EntityId from, EntityId to); | 82 | // ListenableFuture<Boolean> checkRecursiveRelation(EntityId from, EntityId to); |
82 | 83 |
@@ -57,6 +57,8 @@ public class DataConstants { | @@ -57,6 +57,8 @@ public class DataConstants { | ||
57 | public static final String ATTRIBUTES_DELETED = "ATTRIBUTES_DELETED"; | 57 | public static final String ATTRIBUTES_DELETED = "ATTRIBUTES_DELETED"; |
58 | public static final String ALARM_ACK = "ALARM_ACK"; | 58 | public static final String ALARM_ACK = "ALARM_ACK"; |
59 | public static final String ALARM_CLEAR = "ALARM_CLEAR"; | 59 | public static final String ALARM_CLEAR = "ALARM_CLEAR"; |
60 | + public static final String ENTITY_SWAPPED_FROM = "ENTITY_SWAPPED_FROM"; | ||
61 | + public static final String ENTITY_SWAPPED_TO = "ENTITY_SWAPPED_TO"; | ||
60 | 62 | ||
61 | public static final String RPC_CALL_FROM_SERVER_TO_DEVICE = "RPC_CALL_FROM_SERVER_TO_DEVICE"; | 63 | public static final String RPC_CALL_FROM_SERVER_TO_DEVICE = "RPC_CALL_FROM_SERVER_TO_DEVICE"; |
62 | 64 |
@@ -40,7 +40,9 @@ public enum ActionType { | @@ -40,7 +40,9 @@ public enum ActionType { | ||
40 | ALARM_CLEAR(false), | 40 | ALARM_CLEAR(false), |
41 | LOGIN(false), | 41 | LOGIN(false), |
42 | LOGOUT(false), | 42 | LOGOUT(false), |
43 | - LOCKOUT(false); | 43 | + LOCKOUT(false), |
44 | + SWAPPED_FROM_TENANT(false), | ||
45 | + SWAPPED_TO_TENANT(false); | ||
44 | 46 | ||
45 | private final boolean isRead; | 47 | private final boolean isRead; |
46 | 48 |
@@ -22,11 +22,12 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -22,11 +22,12 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
22 | import org.thingsboard.server.common.data.id.EntityId; | 22 | import org.thingsboard.server.common.data.id.EntityId; |
23 | import org.thingsboard.server.common.data.id.UserId; | 23 | import org.thingsboard.server.common.data.id.UserId; |
24 | import org.thingsboard.server.common.data.page.TimePageLink; | 24 | import org.thingsboard.server.common.data.page.TimePageLink; |
25 | +import org.thingsboard.server.dao.Dao; | ||
25 | 26 | ||
26 | import java.util.List; | 27 | import java.util.List; |
27 | import java.util.UUID; | 28 | import java.util.UUID; |
28 | 29 | ||
29 | -public interface AuditLogDao { | 30 | +public interface AuditLogDao extends Dao<AuditLog> { |
30 | 31 | ||
31 | ListenableFuture<Void> saveByTenantId(AuditLog auditLog); | 32 | ListenableFuture<Void> saveByTenantId(AuditLog auditLog); |
32 | 33 |
@@ -28,7 +28,6 @@ import org.springframework.beans.factory.annotation.Autowired; | @@ -28,7 +28,6 @@ import org.springframework.beans.factory.annotation.Autowired; | ||
28 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 28 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
29 | import org.springframework.stereotype.Service; | 29 | import org.springframework.stereotype.Service; |
30 | import org.springframework.util.StringUtils; | 30 | import org.springframework.util.StringUtils; |
31 | -import org.thingsboard.server.common.data.BaseData; | ||
32 | import org.thingsboard.server.common.data.EntityType; | 31 | import org.thingsboard.server.common.data.EntityType; |
33 | import org.thingsboard.server.common.data.HasName; | 32 | import org.thingsboard.server.common.data.HasName; |
34 | import org.thingsboard.server.common.data.audit.ActionStatus; | 33 | import org.thingsboard.server.common.data.audit.ActionStatus; |
@@ -38,7 +37,6 @@ import org.thingsboard.server.common.data.id.AuditLogId; | @@ -38,7 +37,6 @@ import org.thingsboard.server.common.data.id.AuditLogId; | ||
38 | import org.thingsboard.server.common.data.id.CustomerId; | 37 | import org.thingsboard.server.common.data.id.CustomerId; |
39 | import org.thingsboard.server.common.data.id.EntityId; | 38 | import org.thingsboard.server.common.data.id.EntityId; |
40 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
41 | -import org.thingsboard.server.common.data.id.UUIDBased; | ||
42 | import org.thingsboard.server.common.data.id.UserId; | 40 | import org.thingsboard.server.common.data.id.UserId; |
43 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 41 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
44 | import org.thingsboard.server.common.data.page.TimePageData; | 42 | import org.thingsboard.server.common.data.page.TimePageData; |
@@ -53,6 +51,8 @@ import org.thingsboard.server.dao.service.DataValidator; | @@ -53,6 +51,8 @@ import org.thingsboard.server.dao.service.DataValidator; | ||
53 | 51 | ||
54 | import java.io.PrintWriter; | 52 | import java.io.PrintWriter; |
55 | import java.io.StringWriter; | 53 | import java.io.StringWriter; |
54 | +import java.util.ArrayList; | ||
55 | +import java.util.Arrays; | ||
56 | import java.util.List; | 56 | import java.util.List; |
57 | 57 | ||
58 | import static org.thingsboard.server.dao.service.Validator.validateEntityId; | 58 | import static org.thingsboard.server.dao.service.Validator.validateEntityId; |
@@ -117,8 +117,8 @@ public class AuditLogServiceImpl implements AuditLogService { | @@ -117,8 +117,8 @@ public class AuditLogServiceImpl implements AuditLogService { | ||
117 | 117 | ||
118 | @Override | 118 | @Override |
119 | public <E extends HasName, I extends EntityId> ListenableFuture<List<Void>> | 119 | public <E extends HasName, I extends EntityId> ListenableFuture<List<Void>> |
120 | - logEntityAction(TenantId tenantId, CustomerId customerId, UserId userId, String userName, I entityId, E entity, | ||
121 | - ActionType actionType, Exception e, Object... additionalInfo) { | 120 | + logEntityAction(TenantId tenantId, CustomerId customerId, UserId userId, String userName, I entityId, E entity, |
121 | + ActionType actionType, Exception e, Object... additionalInfo) { | ||
122 | if (canLog(entityId.getEntityType(), actionType)) { | 122 | if (canLog(entityId.getEntityType(), actionType)) { |
123 | JsonNode actionData = constructActionData(entityId, entity, actionType, additionalInfo); | 123 | JsonNode actionData = constructActionData(entityId, entity, actionType, additionalInfo); |
124 | ActionStatus actionStatus = ActionStatus.SUCCESS; | 124 | ActionStatus actionStatus = ActionStatus.SUCCESS; |
@@ -129,7 +129,8 @@ public class AuditLogServiceImpl implements AuditLogService { | @@ -129,7 +129,8 @@ public class AuditLogServiceImpl implements AuditLogService { | ||
129 | } else { | 129 | } else { |
130 | try { | 130 | try { |
131 | entityName = entityService.fetchEntityNameAsync(tenantId, entityId).get(); | 131 | entityName = entityService.fetchEntityNameAsync(tenantId, entityId).get(); |
132 | - } catch (Exception ex) {} | 132 | + } catch (Exception ex) { |
133 | + } | ||
133 | } | 134 | } |
134 | if (e != null) { | 135 | if (e != null) { |
135 | actionStatus = ActionStatus.FAILURE; | 136 | actionStatus = ActionStatus.FAILURE; |
@@ -157,16 +158,36 @@ public class AuditLogServiceImpl implements AuditLogService { | @@ -157,16 +158,36 @@ public class AuditLogServiceImpl implements AuditLogService { | ||
157 | } | 158 | } |
158 | } | 159 | } |
159 | 160 | ||
161 | + @Override | ||
162 | + public void removeAuditLogs(TenantId tenantId, EntityId entityId) { | ||
163 | + List<AuditLog> auditLogs = new ArrayList<>(); | ||
164 | + TimePageData<AuditLog> auditLogPageData; | ||
165 | + TimePageLink auditLogPageLink = new TimePageLink(1000); | ||
166 | + do { | ||
167 | + auditLogPageData = findAuditLogsByTenantIdAndEntityId(tenantId, entityId, | ||
168 | + new ArrayList<>(Arrays.asList(ActionType.values())), auditLogPageLink); | ||
169 | + auditLogs.addAll(auditLogPageData.getData()); | ||
170 | + if (auditLogPageData.hasNext()) { | ||
171 | + auditLogPageLink = auditLogPageData.getNextPageLink(); | ||
172 | + } | ||
173 | + } while (auditLogPageData.hasNext()); | ||
174 | + | ||
175 | + for (AuditLog auditLog : auditLogs) { | ||
176 | + auditLogDao.removeById(tenantId, auditLog.getUuidId()); | ||
177 | + } | ||
178 | + } | ||
179 | + | ||
160 | private <E extends HasName, I extends EntityId> JsonNode constructActionData(I entityId, E entity, | 180 | private <E extends HasName, I extends EntityId> JsonNode constructActionData(I entityId, E entity, |
161 | - ActionType actionType, | ||
162 | - Object... additionalInfo) { | 181 | + ActionType actionType, |
182 | + Object... additionalInfo) { | ||
163 | ObjectNode actionData = objectMapper.createObjectNode(); | 183 | ObjectNode actionData = objectMapper.createObjectNode(); |
164 | - switch(actionType) { | 184 | + switch (actionType) { |
165 | case ADDED: | 185 | case ADDED: |
166 | case UPDATED: | 186 | case UPDATED: |
167 | case ALARM_ACK: | 187 | case ALARM_ACK: |
168 | case ALARM_CLEAR: | 188 | case ALARM_CLEAR: |
169 | case RELATIONS_DELETED: | 189 | case RELATIONS_DELETED: |
190 | + case SWAPPED_TO_TENANT: | ||
170 | if (entity != null) { | 191 | if (entity != null) { |
171 | ObjectNode entityNode = objectMapper.valueToTree(entity); | 192 | ObjectNode entityNode = objectMapper.valueToTree(entity); |
172 | if (entityId.getEntityType() == EntityType.DASHBOARD) { | 193 | if (entityId.getEntityType() == EntityType.DASHBOARD) { |
@@ -208,7 +229,7 @@ public class AuditLogServiceImpl implements AuditLogService { | @@ -208,7 +229,7 @@ public class AuditLogServiceImpl implements AuditLogService { | ||
208 | scope = extractParameter(String.class, 0, additionalInfo); | 229 | scope = extractParameter(String.class, 0, additionalInfo); |
209 | actionData.put("scope", scope); | 230 | actionData.put("scope", scope); |
210 | List<String> keys = extractParameter(List.class, 1, additionalInfo); | 231 | List<String> keys = extractParameter(List.class, 1, additionalInfo); |
211 | - ArrayNode attrsArrayNode = actionData.putArray("attributes"); | 232 | + ArrayNode attrsArrayNode = actionData.putArray("attributes"); |
212 | if (keys != null) { | 233 | if (keys != null) { |
213 | keys.forEach(attrsArrayNode::add); | 234 | keys.forEach(attrsArrayNode::add); |
214 | } | 235 | } |
@@ -18,14 +18,12 @@ package org.thingsboard.server.dao.audit; | @@ -18,14 +18,12 @@ package org.thingsboard.server.dao.audit; | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
20 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
21 | -import org.thingsboard.server.common.data.BaseData; | ||
22 | import org.thingsboard.server.common.data.HasName; | 21 | import org.thingsboard.server.common.data.HasName; |
23 | import org.thingsboard.server.common.data.audit.ActionType; | 22 | import org.thingsboard.server.common.data.audit.ActionType; |
24 | import org.thingsboard.server.common.data.audit.AuditLog; | 23 | import org.thingsboard.server.common.data.audit.AuditLog; |
25 | import org.thingsboard.server.common.data.id.CustomerId; | 24 | import org.thingsboard.server.common.data.id.CustomerId; |
26 | import org.thingsboard.server.common.data.id.EntityId; | 25 | import org.thingsboard.server.common.data.id.EntityId; |
27 | import org.thingsboard.server.common.data.id.TenantId; | 26 | import org.thingsboard.server.common.data.id.TenantId; |
28 | -import org.thingsboard.server.common.data.id.UUIDBased; | ||
29 | import org.thingsboard.server.common.data.id.UserId; | 27 | import org.thingsboard.server.common.data.id.UserId; |
30 | import org.thingsboard.server.common.data.page.TimePageData; | 28 | import org.thingsboard.server.common.data.page.TimePageData; |
31 | import org.thingsboard.server.common.data.page.TimePageLink; | 29 | import org.thingsboard.server.common.data.page.TimePageLink; |
@@ -61,4 +59,7 @@ public class DummyAuditLogServiceImpl implements AuditLogService { | @@ -61,4 +59,7 @@ public class DummyAuditLogServiceImpl implements AuditLogService { | ||
61 | return null; | 59 | return null; |
62 | } | 60 | } |
63 | 61 | ||
62 | + @Override | ||
63 | + public void removeAuditLogs(TenantId tenantId, EntityId entityId) { | ||
64 | + } | ||
64 | } | 65 | } |
@@ -189,4 +189,14 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt | @@ -189,4 +189,14 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt | ||
189 | }, MoreExecutors.directExecutor()); | 189 | }, MoreExecutors.directExecutor()); |
190 | } | 190 | } |
191 | 191 | ||
192 | + @Override | ||
193 | + public Device findDeviceByTenantIdAndId(TenantId tenantId, UUID id) { | ||
194 | + return findById(tenantId, id); | ||
195 | + } | ||
196 | + | ||
197 | + @Override | ||
198 | + public ListenableFuture<Device> findDeviceByTenantIdAndIdAsync(TenantId tenantId, UUID id) { | ||
199 | + return findByIdAsync(tenantId, id); | ||
200 | + } | ||
201 | + | ||
192 | } | 202 | } |
@@ -115,4 +115,21 @@ public interface DeviceDao extends Dao<Device> { | @@ -115,4 +115,21 @@ public interface DeviceDao extends Dao<Device> { | ||
115 | * @return the list of tenant device type objects | 115 | * @return the list of tenant device type objects |
116 | */ | 116 | */ |
117 | ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId); | 117 | ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId); |
118 | + | ||
119 | + /** | ||
120 | + * Find devices by tenantId and device id. | ||
121 | + * @param tenantId the tenant Id | ||
122 | + * @param id the device Id | ||
123 | + * @return the device object | ||
124 | + */ | ||
125 | + Device findDeviceByTenantIdAndId(TenantId tenantId, UUID id); | ||
126 | + | ||
127 | + /** | ||
128 | + * Find devices by tenantId and device id. | ||
129 | + * @param tenantId tenantId the tenantId | ||
130 | + * @param id the deviceId | ||
131 | + * @return the device object | ||
132 | + */ | ||
133 | + ListenableFuture<Device> findDeviceByTenantIdAndIdAsync(TenantId tenantId, UUID id); | ||
134 | + | ||
118 | } | 135 | } |
@@ -28,6 +28,8 @@ import org.springframework.cache.CacheManager; | @@ -28,6 +28,8 @@ import org.springframework.cache.CacheManager; | ||
28 | import org.springframework.cache.annotation.CacheEvict; | 28 | import org.springframework.cache.annotation.CacheEvict; |
29 | import org.springframework.cache.annotation.Cacheable; | 29 | import org.springframework.cache.annotation.Cacheable; |
30 | import org.springframework.stereotype.Service; | 30 | import org.springframework.stereotype.Service; |
31 | +import org.springframework.transaction.annotation.Transactional; | ||
32 | +import org.springframework.util.CollectionUtils; | ||
31 | import org.springframework.util.StringUtils; | 33 | import org.springframework.util.StringUtils; |
32 | import org.thingsboard.server.common.data.Customer; | 34 | import org.thingsboard.server.common.data.Customer; |
33 | import org.thingsboard.server.common.data.Device; | 35 | import org.thingsboard.server.common.data.Device; |
@@ -46,9 +48,11 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | @@ -46,9 +48,11 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | ||
46 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; | 48 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
47 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 49 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
48 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 50 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
51 | +import org.thingsboard.server.dao.audit.AuditLogService; | ||
49 | import org.thingsboard.server.dao.customer.CustomerDao; | 52 | import org.thingsboard.server.dao.customer.CustomerDao; |
50 | import org.thingsboard.server.dao.entity.AbstractEntityService; | 53 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
51 | import org.thingsboard.server.dao.entityview.EntityViewService; | 54 | import org.thingsboard.server.dao.entityview.EntityViewService; |
55 | +import org.thingsboard.server.dao.event.EventService; | ||
52 | import org.thingsboard.server.dao.exception.DataValidationException; | 56 | import org.thingsboard.server.dao.exception.DataValidationException; |
53 | import org.thingsboard.server.dao.service.DataValidator; | 57 | import org.thingsboard.server.dao.service.DataValidator; |
54 | import org.thingsboard.server.dao.service.PaginatedRemover; | 58 | import org.thingsboard.server.dao.service.PaginatedRemover; |
@@ -97,18 +101,32 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -97,18 +101,32 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
97 | @Autowired | 101 | @Autowired |
98 | private CacheManager cacheManager; | 102 | private CacheManager cacheManager; |
99 | 103 | ||
104 | + @Autowired | ||
105 | + private EventService eventService; | ||
106 | + | ||
107 | + @Autowired | ||
108 | + private AuditLogService auditLogService; | ||
109 | + | ||
100 | @Override | 110 | @Override |
101 | public Device findDeviceById(TenantId tenantId, DeviceId deviceId) { | 111 | public Device findDeviceById(TenantId tenantId, DeviceId deviceId) { |
102 | log.trace("Executing findDeviceById [{}]", deviceId); | 112 | log.trace("Executing findDeviceById [{}]", deviceId); |
103 | validateId(deviceId, INCORRECT_DEVICE_ID + deviceId); | 113 | validateId(deviceId, INCORRECT_DEVICE_ID + deviceId); |
104 | - return deviceDao.findById(tenantId, deviceId.getId()); | 114 | + if (TenantId.SYS_TENANT_ID.equals(tenantId)) { |
115 | + return deviceDao.findById(tenantId, deviceId.getId()); | ||
116 | + } else { | ||
117 | + return deviceDao.findDeviceByTenantIdAndId(tenantId, deviceId.getId()); | ||
118 | + } | ||
105 | } | 119 | } |
106 | 120 | ||
107 | @Override | 121 | @Override |
108 | public ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId) { | 122 | public ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId) { |
109 | log.trace("Executing findDeviceById [{}]", deviceId); | 123 | log.trace("Executing findDeviceById [{}]", deviceId); |
110 | validateId(deviceId, INCORRECT_DEVICE_ID + deviceId); | 124 | validateId(deviceId, INCORRECT_DEVICE_ID + deviceId); |
111 | - return deviceDao.findByIdAsync(tenantId, deviceId.getId()); | 125 | + if (TenantId.SYS_TENANT_ID.equals(tenantId)) { |
126 | + return deviceDao.findByIdAsync(tenantId, deviceId.getId()); | ||
127 | + } else { | ||
128 | + return deviceDao.findDeviceByTenantIdAndIdAsync(tenantId, deviceId.getId()); | ||
129 | + } | ||
112 | } | 130 | } |
113 | 131 | ||
114 | @Cacheable(cacheNames = DEVICE_CACHE, key = "{#tenantId, #name}") | 132 | @Cacheable(cacheNames = DEVICE_CACHE, key = "{#tenantId, #name}") |
@@ -317,6 +335,33 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | @@ -317,6 +335,33 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe | ||
317 | }, MoreExecutors.directExecutor()); | 335 | }, MoreExecutors.directExecutor()); |
318 | } | 336 | } |
319 | 337 | ||
338 | + @Transactional | ||
339 | + @CacheEvict(cacheNames = DEVICE_CACHE, key = "{#device.tenantId, #device.name}") | ||
340 | + @Override | ||
341 | + public Device swapDevice(TenantId tenantId, Device device) { | ||
342 | + log.trace("Executing swapDevice [{}]", device); | ||
343 | + | ||
344 | + try { | ||
345 | + List<EntityView> entityViews = entityViewService.findEntityViewsByTenantIdAndEntityIdAsync(device.getTenantId(), device.getId()).get(); | ||
346 | + if (!CollectionUtils.isEmpty(entityViews)) { | ||
347 | + throw new DataValidationException("Can't swap device that is assigned to entity views!"); | ||
348 | + } | ||
349 | + } catch (ExecutionException | InterruptedException e) { | ||
350 | + log.error("Exception while finding entity views for deviceId [{}]", device.getId(), e); | ||
351 | + throw new RuntimeException("Exception while finding entity views for deviceId [" + device.getId() + "]", e); | ||
352 | + } | ||
353 | + | ||
354 | + eventService.removeEvents(device.getTenantId(), device.getId()); | ||
355 | + | ||
356 | + relationService.removeRelations(device.getTenantId(), device.getId()); | ||
357 | + | ||
358 | + auditLogService.removeAuditLogs(device.getTenantId(), device.getId()); | ||
359 | + | ||
360 | + device.setTenantId(tenantId); | ||
361 | + device.setCustomerId(null); | ||
362 | + return doSaveDevice(device, null); | ||
363 | + } | ||
364 | + | ||
320 | private DataValidator<Device> deviceValidator = | 365 | private DataValidator<Device> deviceValidator = |
321 | new DataValidator<Device>() { | 366 | new DataValidator<Device>() { |
322 | 367 |
@@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; | ||
28 | import org.thingsboard.server.dao.exception.DataValidationException; | 28 | import org.thingsboard.server.dao.exception.DataValidationException; |
29 | import org.thingsboard.server.dao.service.DataValidator; | 29 | import org.thingsboard.server.dao.service.DataValidator; |
30 | 30 | ||
31 | +import java.util.ArrayList; | ||
31 | import java.util.List; | 32 | import java.util.List; |
32 | import java.util.Optional; | 33 | import java.util.Optional; |
33 | 34 | ||
@@ -94,6 +95,24 @@ public class BaseEventService implements EventService { | @@ -94,6 +95,24 @@ public class BaseEventService implements EventService { | ||
94 | return eventDao.findLatestEvents(tenantId.getId(), entityId, eventType, limit); | 95 | return eventDao.findLatestEvents(tenantId.getId(), entityId, eventType, limit); |
95 | } | 96 | } |
96 | 97 | ||
98 | + @Override | ||
99 | + public void removeEvents(TenantId tenantId, EntityId entityId) { | ||
100 | + List<Event> events = new ArrayList<>(); | ||
101 | + TimePageData<Event> eventPageData; | ||
102 | + TimePageLink eventPageLink = new TimePageLink(1000); | ||
103 | + do { | ||
104 | + eventPageData = findEvents(tenantId, entityId, eventPageLink); | ||
105 | + events.addAll(eventPageData.getData()); | ||
106 | + if (eventPageData.hasNext()) { | ||
107 | + eventPageLink = eventPageData.getNextPageLink(); | ||
108 | + } | ||
109 | + } while (eventPageData.hasNext()); | ||
110 | + | ||
111 | + for (Event event : events) { | ||
112 | + eventDao.removeById(tenantId, event.getUuidId()); | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
97 | private DataValidator<Event> eventValidator = | 116 | private DataValidator<Event> eventValidator = |
98 | new DataValidator<Event>() { | 117 | new DataValidator<Event>() { |
99 | @Override | 118 | @Override |
@@ -506,6 +506,22 @@ public class BaseRelationService implements RelationService { | @@ -506,6 +506,22 @@ public class BaseRelationService implements RelationService { | ||
506 | }, MoreExecutors.directExecutor()); | 506 | }, MoreExecutors.directExecutor()); |
507 | } | 507 | } |
508 | 508 | ||
509 | + @Override | ||
510 | + public void removeRelations(TenantId tenantId, EntityId entityId) { | ||
511 | + Cache cache = cacheManager.getCache(RELATIONS_CACHE); | ||
512 | + | ||
513 | + List<EntityRelation> relations = new ArrayList<>(); | ||
514 | + for (RelationTypeGroup relationTypeGroup : RelationTypeGroup.values()) { | ||
515 | + relations.addAll(findByFrom(tenantId, entityId, relationTypeGroup)); | ||
516 | + relations.addAll(findByTo(tenantId, entityId, relationTypeGroup)); | ||
517 | + } | ||
518 | + | ||
519 | + for (EntityRelation relation : relations) { | ||
520 | + cacheEviction(relation, cache); | ||
521 | + deleteRelation(tenantId, relation); | ||
522 | + } | ||
523 | + } | ||
524 | + | ||
509 | protected void validate(EntityRelation relation) { | 525 | protected void validate(EntityRelation relation) { |
510 | if (relation == null) { | 526 | if (relation == null) { |
511 | throw new DataValidationException("Relation type should be specified!"); | 527 | throw new DataValidationException("Relation type should be specified!"); |
@@ -85,4 +85,7 @@ public interface DeviceRepository extends CrudRepository<DeviceEntity, String> { | @@ -85,4 +85,7 @@ public interface DeviceRepository extends CrudRepository<DeviceEntity, String> { | ||
85 | List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndIdIn(String tenantId, String customerId, List<String> deviceIds); | 85 | List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndIdIn(String tenantId, String customerId, List<String> deviceIds); |
86 | 86 | ||
87 | List<DeviceEntity> findDevicesByTenantIdAndIdIn(String tenantId, List<String> deviceIds); | 87 | List<DeviceEntity> findDevicesByTenantIdAndIdIn(String tenantId, List<String> deviceIds); |
88 | + | ||
89 | + DeviceEntity findByTenantIdAndId(String tenantId, String id); | ||
90 | + | ||
88 | } | 91 | } |
@@ -138,6 +138,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | @@ -138,6 +138,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> | ||
138 | return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(fromTimeUUID(tenantId)))); | 138 | return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(fromTimeUUID(tenantId)))); |
139 | } | 139 | } |
140 | 140 | ||
141 | + @Override | ||
142 | + public Device findDeviceByTenantIdAndId(TenantId tenantId, UUID id) { | ||
143 | + return DaoUtil.getData(deviceRepository.findByTenantIdAndId(fromTimeUUID(tenantId.getId()), fromTimeUUID(id))); | ||
144 | + } | ||
145 | + | ||
146 | + @Override | ||
147 | + public ListenableFuture<Device> findDeviceByTenantIdAndIdAsync(TenantId tenantId, UUID id) { | ||
148 | + return service.submit(() -> DaoUtil.getData(deviceRepository.findByTenantIdAndId(fromTimeUUID(tenantId.getId()), fromTimeUUID(id)))); | ||
149 | + } | ||
150 | + | ||
141 | private List<EntitySubtype> convertTenantDeviceTypesToDto(UUID tenantId, List<String> types) { | 151 | private List<EntitySubtype> convertTenantDeviceTypesToDto(UUID tenantId, List<String> types) { |
142 | List<EntitySubtype> list = Collections.emptyList(); | 152 | List<EntitySubtype> list = Collections.emptyList(); |
143 | if (types != null && !types.isEmpty()) { | 153 | if (types != null && !types.isEmpty()) { |
@@ -16,8 +16,13 @@ | @@ -16,8 +16,13 @@ | ||
16 | package org.thingsboard.rule.engine.filter; | 16 | package org.thingsboard.rule.engine.filter; |
17 | 17 | ||
18 | import lombok.extern.slf4j.Slf4j; | 18 | import lombok.extern.slf4j.Slf4j; |
19 | +import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; | ||
20 | +import org.thingsboard.rule.engine.api.RuleNode; | ||
21 | +import org.thingsboard.rule.engine.api.TbContext; | ||
22 | +import org.thingsboard.rule.engine.api.TbNode; | ||
23 | +import org.thingsboard.rule.engine.api.TbNodeConfiguration; | ||
24 | +import org.thingsboard.rule.engine.api.TbNodeException; | ||
19 | import org.thingsboard.rule.engine.api.util.TbNodeUtils; | 25 | import org.thingsboard.rule.engine.api.util.TbNodeUtils; |
20 | -import org.thingsboard.rule.engine.api.*; | ||
21 | import org.thingsboard.server.common.data.DataConstants; | 26 | import org.thingsboard.server.common.data.DataConstants; |
22 | import org.thingsboard.server.common.data.plugin.ComponentType; | 27 | import org.thingsboard.server.common.data.plugin.ComponentType; |
23 | import org.thingsboard.server.common.msg.TbMsg; | 28 | import org.thingsboard.server.common.msg.TbMsg; |
@@ -30,7 +35,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; | @@ -30,7 +35,7 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; | ||
30 | configClazz = EmptyNodeConfiguration.class, | 35 | configClazz = EmptyNodeConfiguration.class, |
31 | relationTypes = {"Post attributes", "Post telemetry", "RPC Request from Device", "RPC Request to Device", "Activity Event", "Inactivity Event", | 36 | relationTypes = {"Post attributes", "Post telemetry", "RPC Request from Device", "RPC Request to Device", "Activity Event", "Inactivity Event", |
32 | "Connect Event", "Disconnect Event", "Entity Created", "Entity Updated", "Entity Deleted", "Entity Assigned", | 37 | "Connect Event", "Disconnect Event", "Entity Created", "Entity Updated", "Entity Deleted", "Entity Assigned", |
33 | - "Entity Unassigned", "Attributes Updated", "Attributes Deleted", "Alarm Acknowledged", "Alarm Cleared", "Other"}, | 38 | + "Entity Unassigned", "Attributes Updated", "Attributes Deleted", "Alarm Acknowledged", "Alarm Cleared", "Other", "Entity Swapped From", "Entity Swapped To"}, |
34 | nodeDescription = "Route incoming messages by Message Type", | 39 | nodeDescription = "Route incoming messages by Message Type", |
35 | nodeDetails = "Sends messages with message types <b>\"Post attributes\", \"Post telemetry\", \"RPC Request\"</b> etc. via corresponding chain, otherwise <b>Other</b> chain is used.", | 40 | nodeDetails = "Sends messages with message types <b>\"Post attributes\", \"Post telemetry\", \"RPC Request\"</b> etc. via corresponding chain, otherwise <b>Other</b> chain is used.", |
36 | uiResources = {"static/rulenode/rulenode-core-config.js"}, | 41 | uiResources = {"static/rulenode/rulenode-core-config.js"}, |
@@ -81,6 +86,10 @@ public class TbMsgTypeSwitchNode implements TbNode { | @@ -81,6 +86,10 @@ public class TbMsgTypeSwitchNode implements TbNode { | ||
81 | relationType = "Alarm Cleared"; | 86 | relationType = "Alarm Cleared"; |
82 | } else if (msg.getType().equals(DataConstants.RPC_CALL_FROM_SERVER_TO_DEVICE)) { | 87 | } else if (msg.getType().equals(DataConstants.RPC_CALL_FROM_SERVER_TO_DEVICE)) { |
83 | relationType = "RPC Request to Device"; | 88 | relationType = "RPC Request to Device"; |
89 | + } else if (msg.getType().equals(DataConstants.ENTITY_SWAPPED_FROM)) { | ||
90 | + relationType = "Entity Swapped From"; | ||
91 | + } else if (msg.getType().equals(DataConstants.ENTITY_SWAPPED_TO)) { | ||
92 | + relationType = "Entity Swapped To"; | ||
84 | } else { | 93 | } else { |
85 | relationType = "Other"; | 94 | relationType = "Other"; |
86 | } | 95 | } |
@@ -222,6 +222,12 @@ export default angular.module('thingsboard.types', []) | @@ -222,6 +222,12 @@ export default angular.module('thingsboard.types', []) | ||
222 | }, | 222 | }, |
223 | "LOCKOUT": { | 223 | "LOCKOUT": { |
224 | name: "audit-log.type-lockout" | 224 | name: "audit-log.type-lockout" |
225 | + }, | ||
226 | + "SWAPPED_FROM_TENANT": { | ||
227 | + name: "audit-log.type-swapped-from-tenant" | ||
228 | + }, | ||
229 | + "SWAPPED_TO_TENANT": { | ||
230 | + name: "audit-log.type-swapped-to-tenant" | ||
225 | } | 231 | } |
226 | }, | 232 | }, |
227 | auditLogActionStatus: { | 233 | auditLogActionStatus: { |
@@ -356,7 +356,9 @@ | @@ -356,7 +356,9 @@ | ||
356 | "action-data": "Action data", | 356 | "action-data": "Action data", |
357 | "failure-details": "Failure details", | 357 | "failure-details": "Failure details", |
358 | "search": "Search audit logs", | 358 | "search": "Search audit logs", |
359 | - "clear-search": "Clear search" | 359 | + "clear-search": "Clear search", |
360 | + "type-swapped-from-tenant": "Swapped from Tenant", | ||
361 | + "type-swapped-to-tenant": "Swapped to Tenant" | ||
360 | }, | 362 | }, |
361 | "confirm-on-exit": { | 363 | "confirm-on-exit": { |
362 | "message": "You have unsaved changes. Are you sure you want to leave this page?", | 364 | "message": "You have unsaved changes. Are you sure you want to leave this page?", |