diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index bdeec8d0ae..939e9da8a0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -29,29 +30,24 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmStatus; -import org.thingsboard.server.common.data.audit.ActionType; -import org.thingsboard.server.common.data.edge.EdgeEventActionType; 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.EdgeId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.alarm.TbAlarmService; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import java.util.List; - import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_INFO_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_SORT_PROPERTY_ALLOWABLE_VALUES; @@ -70,9 +66,12 @@ import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LI @RestController @TbCoreComponent +@RequiredArgsConstructor @RequestMapping("/api") public class AlarmController extends BaseController { + private final TbAlarmService tbAlarmService; + public static final String ALARM_ID = "alarmId"; private static final String ALARM_SECURITY_CHECK = "If the user has the authority of 'Tenant Administrator', the server checks that the originator of alarm is owned by the same tenant. " + "If the user has the authority of 'Customer User', the server checks that the originator of alarm belongs to the customer. "; @@ -133,24 +132,9 @@ public class AlarmController extends BaseController { @RequestMapping(value = "/alarm", method = RequestMethod.POST) @ResponseBody public Alarm saveAlarm(@ApiParam(value = "A JSON value representing the alarm.") @RequestBody Alarm alarm) throws ThingsboardException { - try { - alarm.setTenantId(getCurrentUser().getTenantId()); - - checkEntity(alarm.getId(), alarm, Resource.ALARM); - - Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm)); - logEntityAction(savedAlarm.getOriginator(), savedAlarm, - getCurrentUser().getCustomerId(), - alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - - sendEntityNotificationMsg(getTenantId(), savedAlarm.getId(), alarm.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED); - - return savedAlarm; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.ALARM), alarm, - null, alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); - throw handleException(e); - } + alarm.setTenantId(getCurrentUser().getTenantId()); + checkEntity(alarm.getId(), alarm, Resource.ALARM); + return tbAlarmService.save(alarm, getCurrentUser()); } @ApiOperation(value = "Delete Alarm (deleteAlarm)", @@ -163,16 +147,7 @@ public class AlarmController extends BaseController { try { AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); - - List relatedEdgeIds = findRelatedEdgeIds(getTenantId(), alarm.getOriginator()); - - logEntityAction(alarm.getOriginator(), alarm, - getCurrentUser().getCustomerId(), - ActionType.ALARM_DELETE, null); - - sendAlarmDeleteNotificationMsg(getTenantId(), alarmId, relatedEdgeIds, alarm); - - return alarmService.deleteAlarm(getTenantId(), alarmId); + return tbAlarmService.delete(alarm, getCurrentUser()); } catch (Exception e) { throw handleException(e); } @@ -187,19 +162,9 @@ public class AlarmController extends BaseController { @ResponseStatus(value = HttpStatus.OK) public void ackAlarm(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); - try { - AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); - long ackTs = System.currentTimeMillis(); - alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, ackTs).get(); - alarm.setAckTs(ackTs); - alarm.setStatus(alarm.getStatus().isCleared() ? AlarmStatus.CLEARED_ACK : AlarmStatus.ACTIVE_ACK); - logEntityAction(alarm.getOriginator(), alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null); - - sendEntityNotificationMsg(getTenantId(), alarmId, EdgeEventActionType.ALARM_ACK); - } catch (Exception e) { - throw handleException(e); - } + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); + tbAlarmService.ack(alarm, getCurrentUser()); } @ApiOperation(value = "Clear Alarm (clearAlarm)", @@ -211,19 +176,9 @@ public class AlarmController extends BaseController { @ResponseStatus(value = HttpStatus.OK) public void clearAlarm(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); - try { - AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); - Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); - long clearTs = System.currentTimeMillis(); - alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, clearTs).get(); - alarm.setClearTs(clearTs); - alarm.setStatus(alarm.getStatus().isAck() ? AlarmStatus.CLEARED_ACK : AlarmStatus.CLEARED_UNACK); - logEntityAction(alarm.getOriginator(), alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null); - - sendEntityNotificationMsg(getTenantId(), alarmId, EdgeEventActionType.ALARM_CLEAR); - } catch (Exception e) { - throw handleException(e); - } + AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); + Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); + tbAlarmService.clear(alarm, getCurrentUser()); } @ApiOperation(value = "Get Alarms (getAlarms)", @@ -276,6 +231,7 @@ public class AlarmController extends BaseController { throw handleException(e); } } + @ApiOperation(value = "Get All Alarms (getAllAlarms)", notes = "Returns a page of alarms that belongs to the current user owner. " + "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 7bd9cb065d..4718feb774 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -34,13 +34,10 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntitySubtype; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetInfo; import org.thingsboard.server.common.data.asset.AssetSearchQuery; -import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AssetId; @@ -54,6 +51,7 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.asset.AssetBulkImportService; +import org.thingsboard.server.service.entitiy.asset.TbAssetService; import org.thingsboard.server.service.importing.BulkImportRequest; import org.thingsboard.server.service.importing.BulkImportResult; import org.thingsboard.server.service.security.model.SecurityUser; @@ -95,6 +93,7 @@ import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE @Slf4j public class AssetController extends BaseController { private final AssetBulkImportService assetBulkImportService; + private final TbAssetService tbAssetService; public static final String ASSET_ID = "assetId"; @@ -145,39 +144,12 @@ public class AssetController extends BaseController { @RequestMapping(value = "/asset", method = RequestMethod.POST) @ResponseBody public Asset saveAsset(@ApiParam(value = "A JSON value representing the asset.") @RequestBody Asset asset) throws ThingsboardException { - try { - if (TB_SERVICE_QUEUE.equals(asset.getType())) { - throw new ThingsboardException("Unable to save asset with type " + TB_SERVICE_QUEUE, ThingsboardErrorCode.BAD_REQUEST_PARAMS); - } - - asset.setTenantId(getCurrentUser().getTenantId()); - - checkEntity(asset.getId(), asset, Resource.ASSET); - - Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); - - onAssetCreatedOrUpdated(savedAsset, asset.getId() != null, getCurrentUser()); - - return savedAsset; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.ASSET), asset, - null, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); - throw handleException(e); - } - } - - private void onAssetCreatedOrUpdated(Asset asset, boolean updated, SecurityUser user) { - try { - logEntityAction(user, asset.getId(), asset, - asset.getCustomerId(), - updated ? ActionType.UPDATED : ActionType.ADDED, null); - } catch (ThingsboardException e) { - log.error("Failed to log entity action", e); - } - - if (updated) { - sendEntityNotificationMsg(asset.getTenantId(), asset.getId(), EdgeEventActionType.UPDATED); + if (TB_SERVICE_QUEUE.equals(asset.getType())) { + throw new ThingsboardException("Unable to save asset with type " + TB_SERVICE_QUEUE, ThingsboardErrorCode.BAD_REQUEST_PARAMS); } + asset.setTenantId(getCurrentUser().getTenantId()); + checkEntity(asset.getId(), asset, Resource.ASSET); + return tbAssetService.save(asset, getCurrentUser()); } @ApiOperation(value = "Delete asset (deleteAsset)", @@ -190,21 +162,8 @@ public class AssetController extends BaseController { try { AssetId assetId = new AssetId(toUUID(strAssetId)); Asset asset = checkAssetId(assetId, Operation.DELETE); - - List relatedEdgeIds = findRelatedEdgeIds(getTenantId(), assetId); - - assetService.deleteAsset(getTenantId(), assetId); - - logEntityAction(assetId, asset, - asset.getCustomerId(), - ActionType.DELETED, null, strAssetId); - - sendDeleteNotificationMsg(getTenantId(), assetId, relatedEdgeIds); + tbAssetService.delete(asset, getCurrentUser()).get(); } catch (Exception e) { - logEntityAction(emptyId(EntityType.ASSET), - null, - null, - ActionType.DELETED, e, strAssetId); throw handleException(e); } } @@ -218,31 +177,11 @@ public class AssetController extends BaseController { @ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(ASSET_ID, strAssetId); - try { - CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId, Operation.READ); - - AssetId assetId = new AssetId(toUUID(strAssetId)); - checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER); - - Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(getTenantId(), assetId, customerId)); - - logEntityAction(assetId, savedAsset, - savedAsset.getCustomerId(), - ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, strCustomerId, customer.getName()); - - sendEntityAssignToCustomerNotificationMsg(savedAsset.getTenantId(), savedAsset.getId(), - customerId, EdgeEventActionType.ASSIGNED_TO_CUSTOMER); - - return savedAsset; - } catch (Exception e) { - - logEntityAction(emptyId(EntityType.ASSET), null, - null, - ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId, strCustomerId); - - throw handleException(e); - } + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); + Customer customer = checkCustomerId(customerId, Operation.READ); + AssetId assetId = new AssetId(toUUID(strAssetId)); + checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER); + return tbAssetService.assignAssetToCustomer(getTenantId(), assetId, customer, getCurrentUser()); } @ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)", @@ -252,33 +191,13 @@ public class AssetController extends BaseController { @ResponseBody public Asset unassignAssetFromCustomer(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(ASSET_ID, strAssetId); - try { - AssetId assetId = new AssetId(toUUID(strAssetId)); - Asset asset = checkAssetId(assetId, Operation.UNASSIGN_FROM_CUSTOMER); - if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { - throw new IncorrectParameterException("Asset isn't assigned to any customer!"); - } - - Customer customer = checkCustomerId(asset.getCustomerId(), Operation.READ); - - Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(getTenantId(), assetId)); - - logEntityAction(assetId, asset, - asset.getCustomerId(), - ActionType.UNASSIGNED_FROM_CUSTOMER, null, strAssetId, customer.getId().toString(), customer.getName()); - - sendEntityAssignToCustomerNotificationMsg(savedAsset.getTenantId(), savedAsset.getId(), - customer.getId(), EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER); - - return savedAsset; - } catch (Exception e) { - - logEntityAction(emptyId(EntityType.ASSET), null, - null, - ActionType.UNASSIGNED_FROM_CUSTOMER, e, strAssetId); - - throw handleException(e); + AssetId assetId = new AssetId(toUUID(strAssetId)); + Asset asset = checkAssetId(assetId, Operation.UNASSIGN_FROM_CUSTOMER); + if (asset.getCustomerId() == null || asset.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { + throw new IncorrectParameterException("Asset isn't assigned to any customer!"); } + Customer customer = checkCustomerId(asset.getCustomerId(), Operation.READ); + return tbAssetService.unassignAssetToCustomer(getTenantId(), assetId, customer, getCurrentUser()); } @ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)", @@ -290,25 +209,9 @@ public class AssetController extends BaseController { @ResponseBody public Asset assignAssetToPublicCustomer(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(ASSET_ID, strAssetId); - try { - AssetId assetId = new AssetId(toUUID(strAssetId)); - Asset asset = checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER); - Customer publicCustomer = customerService.findOrCreatePublicCustomer(asset.getTenantId()); - Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(getTenantId(), assetId, publicCustomer.getId())); - - logEntityAction(assetId, savedAsset, - savedAsset.getCustomerId(), - ActionType.ASSIGNED_TO_CUSTOMER, null, strAssetId, publicCustomer.getId().toString(), publicCustomer.getName()); - - return savedAsset; - } catch (Exception e) { - - logEntityAction(emptyId(EntityType.ASSET), null, - null, - ActionType.ASSIGNED_TO_CUSTOMER, e, strAssetId); - - throw handleException(e); - } + AssetId assetId = new AssetId(toUUID(strAssetId)); + checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER); + return tbAssetService.assignAssetToPublicCustomer(getTenantId(), assetId, getCurrentUser()); } @ApiOperation(value = "Get Tenant Assets (getTenantAssets)", @@ -553,30 +456,14 @@ public class AssetController extends BaseController { @ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(ASSET_ID, strAssetId); - try { - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.READ); - AssetId assetId = new AssetId(toUUID(strAssetId)); - checkAssetId(assetId, Operation.READ); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + Edge edge = checkEdgeId(edgeId, Operation.READ); - Asset savedAsset = checkNotNull(assetService.assignAssetToEdge(getTenantId(), assetId, edgeId)); + AssetId assetId = new AssetId(toUUID(strAssetId)); + checkAssetId(assetId, Operation.READ); - logEntityAction(assetId, savedAsset, - savedAsset.getCustomerId(), - ActionType.ASSIGNED_TO_EDGE, null, strAssetId, strEdgeId, edge.getName()); - - sendEntityAssignToEdgeNotificationMsg(getTenantId(), edgeId, savedAsset.getId(), EdgeEventActionType.ASSIGNED_TO_EDGE); - - return savedAsset; - } catch (Exception e) { - - logEntityAction(emptyId(EntityType.ASSET), null, - null, - ActionType.ASSIGNED_TO_EDGE, e, strAssetId, strEdgeId); - - throw handleException(e); - } + return tbAssetService.assignAssetToEdge(getTenantId(), assetId, edge, getCurrentUser()); } @ApiOperation(value = "Unassign asset from edge (unassignAssetFromEdge)", @@ -593,30 +480,13 @@ public class AssetController extends BaseController { @ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(ASSET_ID, strAssetId); - try { - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.READ); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + Edge edge = checkEdgeId(edgeId, Operation.READ); - AssetId assetId = new AssetId(toUUID(strAssetId)); - Asset asset = checkAssetId(assetId, Operation.READ); - - Asset savedAsset = checkNotNull(assetService.unassignAssetFromEdge(getTenantId(), assetId, edgeId)); - - logEntityAction(assetId, asset, - asset.getCustomerId(), - ActionType.UNASSIGNED_FROM_EDGE, null, strAssetId, strEdgeId, edge.getName()); + AssetId assetId = new AssetId(toUUID(strAssetId)); + Asset asset = checkAssetId(assetId, Operation.READ); - sendEntityAssignToEdgeNotificationMsg(getTenantId(), edgeId, savedAsset.getId(), EdgeEventActionType.UNASSIGNED_FROM_EDGE); - - return savedAsset; - } catch (Exception e) { - - logEntityAction(emptyId(EntityType.ASSET), null, - null, - ActionType.UNASSIGNED_FROM_EDGE, e, strAssetId, strEdgeId); - - throw handleException(e); - } + return tbAssetService.unassignAssetFromEdge(getTenantId(), asset, edge, getCurrentUser()); } @ApiOperation(value = "Get assets assigned to edge (getEdgeAssets)", @@ -680,9 +550,7 @@ public class AssetController extends BaseController { @PostMapping("/asset/bulk_import") public BulkImportResult processAssetsBulkImport(@RequestBody BulkImportRequest request) throws Exception { SecurityUser user = getCurrentUser(); - return assetBulkImportService.processBulkImport(request, user, importedAssetInfo -> { - onAssetCreatedOrUpdated(importedAssetInfo.getEntity(), importedAssetInfo.isUpdated(), user); - }); + return assetBulkImportService.processBulkImport(request, user); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index f945cc30b7..1daefb7a39 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -349,8 +349,12 @@ public abstract class BaseController { } } - UUID toUUID(String id) { - return UUID.fromString(id); + UUID toUUID(String id) throws ThingsboardException { + try { + return UUID.fromString(id); + } catch (IllegalArgumentException e) { + throw handleException(e, false); + } } PageLink createPageLink(int pageSize, int page, String textSearch, String sortProperty, String sortOrder) throws ThingsboardException { diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 85a21e912c..f7b3908010 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -37,20 +37,16 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; -import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; import org.thingsboard.server.common.data.ClaimRequest; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceInfo; import org.thingsboard.server.common.data.EntitySubtype; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest; import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.device.DeviceSearchQuery; import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; @@ -63,9 +59,6 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.security.DeviceCredentials; -import org.thingsboard.server.common.msg.TbMsg; -import org.thingsboard.server.common.msg.TbMsgDataType; -import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.dao.device.claim.ClaimResponse; import org.thingsboard.server.dao.device.claim.ClaimResult; import org.thingsboard.server.dao.device.claim.ReclaimResult; @@ -73,7 +66,7 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.device.DeviceBulkImportService; -import org.thingsboard.server.service.gateway_device.GatewayNotificationsService; +import org.thingsboard.server.service.entitiy.device.TbDeviceService; import org.thingsboard.server.service.importing.BulkImportRequest; import org.thingsboard.server.service.importing.BulkImportResult; import org.thingsboard.server.service.security.model.SecurityUser; @@ -81,7 +74,6 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import javax.annotation.Nullable; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -90,6 +82,7 @@ import java.util.stream.Collectors; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_INFO_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_NAME_DESCRIPTION; @@ -110,6 +103,7 @@ import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_A import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; +import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID; import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; @@ -122,13 +116,11 @@ import static org.thingsboard.server.controller.EdgeController.EDGE_ID; @Slf4j public class DeviceController extends BaseController { - protected static final String DEVICE_ID = "deviceId"; protected static final String DEVICE_NAME = "deviceName"; - protected static final String TENANT_ID = "tenantId"; private final DeviceBulkImportService deviceBulkImportService; - private final GatewayNotificationsService gatewayNotificationsService; + private final TbDeviceService tbDeviceService; @ApiOperation(value = "Get Device (getDeviceById)", notes = "Fetch the Device object based on the provided Device Id. " + @@ -141,12 +133,8 @@ public class DeviceController extends BaseController { public Device getDeviceById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); - try { - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - return checkDeviceId(deviceId, Operation.READ); - } catch (Exception e) { - throw handleException(e); - } + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + return checkDeviceId(deviceId, Operation.READ); } @ApiOperation(value = "Get Device Info (getDeviceInfoById)", @@ -160,12 +148,8 @@ public class DeviceController extends BaseController { public DeviceInfo getDeviceInfoById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); - try { - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - return checkDeviceInfoId(deviceId, Operation.READ); - } catch (Exception e) { - throw handleException(e); - } + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + return checkDeviceInfoId(deviceId, Operation.READ); } @ApiOperation(value = "Create Or Update Device (saveDevice)", @@ -182,27 +166,14 @@ public class DeviceController extends BaseController { public Device saveDevice(@ApiParam(value = "A JSON value representing the device.") @RequestBody Device device, @ApiParam(value = "Optional value of the device credentials to be used during device creation. " + "If omitted, access token will be auto-generated.") @RequestParam(name = "accessToken", required = false) String accessToken) throws ThingsboardException { - boolean created = device.getId() == null; - try { - device.setTenantId(getCurrentUser().getTenantId()); - - Device oldDevice = null; - if (!created) { - oldDevice = checkDeviceId(device.getId(), Operation.WRITE); - } else { - checkEntity(null, device, Resource.DEVICE); - } - - Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); - - onDeviceCreatedOrUpdated(savedDevice, oldDevice, !created, getCurrentUser()); - - return savedDevice; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), device, - null, created ? ActionType.ADDED : ActionType.UPDATED, e); - throw handleException(e); + device.setTenantId(getCurrentUser().getTenantId()); + Device oldDevice = null; + if (device.getId() != null) { + oldDevice = checkDeviceId(device.getId(), Operation.WRITE); + } else { + checkEntity(null, device, Resource.DEVICE); } + return tbDeviceService.save(getTenantId(), device, oldDevice, accessToken, getCurrentUser()); } @ApiOperation(value = "Create Device (saveDevice) with credentials ", @@ -218,36 +189,11 @@ public class DeviceController extends BaseController { @RequestBody SaveDeviceWithCredentialsRequest deviceAndCredentials) throws ThingsboardException { Device device = checkNotNull(deviceAndCredentials.getDevice()); DeviceCredentials credentials = checkNotNull(deviceAndCredentials.getCredentials()); - boolean created = device.getId() == null; - try { - device.setTenantId(getCurrentUser().getTenantId()); - checkEntity(device.getId(), device, Resource.DEVICE); - Device savedDevice = deviceService.saveDeviceWithCredentials(device, credentials); - checkNotNull(savedDevice); - tbClusterService.onDeviceUpdated(savedDevice, device); - logEntityAction(savedDevice.getId(), savedDevice, - savedDevice.getCustomerId(), - device.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - - return savedDevice; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), device, - null, created ? ActionType.ADDED : ActionType.UPDATED, e); - throw handleException(e); - } + device.setTenantId(getCurrentUser().getTenantId()); + checkEntity(device.getId(), device, Resource.DEVICE); + return tbDeviceService.saveDeviceWithCredentials(getTenantId(), device, credentials, getCurrentUser()); } - private void onDeviceCreatedOrUpdated(Device savedDevice, Device oldDevice, boolean updated, SecurityUser user) { - tbClusterService.onDeviceUpdated(savedDevice, oldDevice); - - try { - logEntityAction(user, savedDevice.getId(), savedDevice, - savedDevice.getCustomerId(), - updated ? ActionType.UPDATED : ActionType.ADDED, null); - } catch (ThingsboardException e) { - log.error("Failed to log entity action", e); - } - } @ApiOperation(value = "Delete device (deleteDevice)", notes = "Deletes the device, it's credentials and all the relations (from and to the device). Referencing non-existing device Id will cause an error." + TENANT_AUTHORITY_PARAGRAPH) @@ -257,27 +203,11 @@ public class DeviceController extends BaseController { public void deleteDevice(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + Device device = checkDeviceId(deviceId, Operation.DELETE); try { - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId, Operation.DELETE); - - List relatedEdgeIds = findRelatedEdgeIds(getTenantId(), deviceId); - - deviceService.deleteDevice(getCurrentUser().getTenantId(), deviceId); - - gatewayNotificationsService.onDeviceDeleted(device); - tbClusterService.onDeviceDeleted(device, null); - - logEntityAction(deviceId, device, - device.getCustomerId(), - ActionType.DELETED, null, strDeviceId); - - sendDeleteNotificationMsg(getTenantId(), deviceId, relatedEdgeIds); + tbDeviceService.deleteDevice(device, getCurrentUser()).get(); } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), - null, - null, - ActionType.DELETED, e, strDeviceId); throw handleException(e); } } @@ -293,29 +223,11 @@ public class DeviceController extends BaseController { @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(DEVICE_ID, strDeviceId); - try { - CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId, Operation.READ); - - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER); - - Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(getCurrentUser().getTenantId(), deviceId, customerId)); - - logEntityAction(deviceId, savedDevice, - savedDevice.getCustomerId(), - ActionType.ASSIGNED_TO_CUSTOMER, null, strDeviceId, strCustomerId, customer.getName()); - - sendEntityAssignToCustomerNotificationMsg(savedDevice.getTenantId(), savedDevice.getId(), - customerId, EdgeEventActionType.ASSIGNED_TO_CUSTOMER); - - return savedDevice; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), null, - null, - ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId, strCustomerId); - throw handleException(e); - } + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); + Customer customer = checkCustomerId(customerId, Operation.READ); + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER); + return tbDeviceService.assignDeviceToCustomer(getTenantId(), deviceId, customer, getCurrentUser()); } @ApiOperation(value = "Unassign device from customer (unassignDeviceFromCustomer)", @@ -332,22 +244,11 @@ public class DeviceController extends BaseController { if (device.getCustomerId() == null || device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { throw new IncorrectParameterException("Device isn't assigned to any customer!"); } - Customer customer = checkCustomerId(device.getCustomerId(), Operation.READ); - - Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(getCurrentUser().getTenantId(), deviceId)); - - logEntityAction(deviceId, device, - device.getCustomerId(), - ActionType.UNASSIGNED_FROM_CUSTOMER, null, strDeviceId, customer.getId().toString(), customer.getName()); - sendEntityAssignToCustomerNotificationMsg(savedDevice.getTenantId(), savedDevice.getId(), - customer.getId(), EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER); + Customer customer = checkCustomerId(device.getCustomerId(), Operation.READ); - return savedDevice; + return tbDeviceService.unassignDeviceFromCustomer(device, customer, getCurrentUser()); } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), null, - null, - ActionType.UNASSIGNED_FROM_CUSTOMER, e, strDeviceId); throw handleException(e); } } @@ -362,23 +263,9 @@ public class DeviceController extends BaseController { public Device assignDeviceToPublicCustomer(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); - try { - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER); - Customer publicCustomer = customerService.findOrCreatePublicCustomer(device.getTenantId()); - Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(getCurrentUser().getTenantId(), deviceId, publicCustomer.getId())); - - logEntityAction(deviceId, savedDevice, - savedDevice.getCustomerId(), - ActionType.ASSIGNED_TO_CUSTOMER, null, strDeviceId, publicCustomer.getId().toString(), publicCustomer.getName()); - - return savedDevice; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), null, - null, - ActionType.ASSIGNED_TO_CUSTOMER, e, strDeviceId); - throw handleException(e); - } + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + checkDeviceId(deviceId, Operation.ASSIGN_TO_CUSTOMER); + return tbDeviceService.assignDeviceToPublicCustomer(getTenantId(), deviceId, getCurrentUser()); } @ApiOperation(value = "Get Device Credentials (getDeviceCredentialsByDeviceId)", @@ -389,20 +276,9 @@ public class DeviceController extends BaseController { public DeviceCredentials getDeviceCredentialsByDeviceId(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); - try { - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId, Operation.READ_CREDENTIALS); - DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(getCurrentUser().getTenantId(), deviceId)); - logEntityAction(deviceId, device, - device.getCustomerId(), - ActionType.CREDENTIALS_READ, null, strDeviceId); - return deviceCredentials; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), null, - null, - ActionType.CREDENTIALS_READ, e, strDeviceId); - throw handleException(e); - } + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + Device device = checkDeviceId(deviceId, Operation.READ_CREDENTIALS); + return tbDeviceService.getDeviceCredentialsByDeviceId(device, getCurrentUser()); } @ApiOperation(value = "Update device credentials (updateDeviceCredentials)", notes = "During device creation, platform generates random 'ACCESS_TOKEN' credentials. " + @@ -416,23 +292,8 @@ public class DeviceController extends BaseController { @ApiParam(value = "A JSON value representing the device credentials.") @RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException { checkNotNull(deviceCredentials); - try { - Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); - DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(getCurrentUser().getTenantId(), deviceCredentials)); - tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId(), result), null); - - sendEntityNotificationMsg(getTenantId(), device.getId(), EdgeEventActionType.CREDENTIALS_UPDATED); - - logEntityAction(device.getId(), device, - device.getCustomerId(), - ActionType.CREDENTIALS_UPDATED, null, deviceCredentials); - return result; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), null, - null, - ActionType.CREDENTIALS_UPDATED, e, deviceCredentials); - throw handleException(e); - } + Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); + return tbDeviceService.updateDeviceCredentials(device, deviceCredentials, getCurrentUser()); } @ApiOperation(value = "Get Tenant Devices (getTenantDevices)", @@ -692,52 +553,42 @@ public class DeviceController extends BaseController { @ApiParam(value = "Claiming request which can optionally contain secret key") @RequestBody(required = false) ClaimRequest claimRequest) throws ThingsboardException { checkParameter(DEVICE_NAME, deviceName); - try { - final DeferredResult deferredResult = new DeferredResult<>(); - - SecurityUser user = getCurrentUser(); - TenantId tenantId = user.getTenantId(); - CustomerId customerId = user.getCustomerId(); - - Device device = checkNotNull(deviceService.findDeviceByTenantIdAndName(tenantId, deviceName)); - accessControlService.checkPermission(user, Resource.DEVICE, Operation.CLAIM_DEVICES, - device.getId(), device); - String secretKey = getSecretKey(claimRequest); + final DeferredResult deferredResult = new DeferredResult<>(); - ListenableFuture future = claimDevicesService.claimDevice(device, customerId, secretKey); - Futures.addCallback(future, new FutureCallback() { - @Override - public void onSuccess(@Nullable ClaimResult result) { - HttpStatus status; - if (result != null) { - if (result.getResponse().equals(ClaimResponse.SUCCESS)) { - status = HttpStatus.OK; - deferredResult.setResult(new ResponseEntity<>(result, status)); - - try { - logEntityAction(user, device.getId(), result.getDevice(), customerId, ActionType.ASSIGNED_TO_CUSTOMER, null, - device.getId().toString(), customerId.toString(), customerService.findCustomerById(tenantId, customerId).getName()); - } catch (ThingsboardException e) { - throw new RuntimeException(e); - } - } else { - status = HttpStatus.BAD_REQUEST; - deferredResult.setResult(new ResponseEntity<>(result.getResponse(), status)); - } + SecurityUser user = getCurrentUser(); + TenantId tenantId = user.getTenantId(); + CustomerId customerId = user.getCustomerId(); + + Device device = checkNotNull(deviceService.findDeviceByTenantIdAndName(tenantId, deviceName)); + accessControlService.checkPermission(user, Resource.DEVICE, Operation.CLAIM_DEVICES, + device.getId(), device); + String secretKey = getSecretKey(claimRequest); + + ListenableFuture future = tbDeviceService.claimDevice(tenantId, device, customerId, secretKey, user); + + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable ClaimResult result) { + HttpStatus status; + if (result != null) { + if (result.getResponse().equals(ClaimResponse.SUCCESS)) { + status = HttpStatus.OK; + deferredResult.setResult(new ResponseEntity<>(result, status)); } else { - deferredResult.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST)); + status = HttpStatus.BAD_REQUEST; + deferredResult.setResult(new ResponseEntity<>(result.getResponse(), status)); } + } else { + deferredResult.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST)); } + } - @Override - public void onFailure(Throwable t) { - deferredResult.setErrorResult(t); - } - }, MoreExecutors.directExecutor()); - return deferredResult; - } catch (Exception e) { - throw handleException(e); - } + @Override + public void onFailure(Throwable t) { + deferredResult.setErrorResult(t); + } + }, MoreExecutors.directExecutor()); + return deferredResult; } @ApiOperation(value = "Reclaim device (reClaimDevice)", @@ -759,21 +610,11 @@ public class DeviceController extends BaseController { accessControlService.checkPermission(user, Resource.DEVICE, Operation.CLAIM_DEVICES, device.getId(), device); - ListenableFuture result = claimDevicesService.reClaimDevice(tenantId, device); + ListenableFuture result = tbDeviceService.reclaimDevice(tenantId, device, user); Futures.addCallback(result, new FutureCallback<>() { @Override public void onSuccess(ReclaimResult reclaimResult) { deferredResult.setResult(new ResponseEntity(HttpStatus.OK)); - - Customer unassignedCustomer = reclaimResult.getUnassignedCustomer(); - if (unassignedCustomer != null) { - try { - logEntityAction(user, device.getId(), device, device.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, - device.getId().toString(), unassignedCustomer.getId().toString(), unassignedCustomer.getName()); - } catch (ThingsboardException e) { - throw new RuntimeException(e); - } - } } @Override @@ -787,7 +628,7 @@ public class DeviceController extends BaseController { } } - private String getSecretKey(ClaimRequest claimRequest) throws IOException { + private String getSecretKey(ClaimRequest claimRequest) { String secretKey = claimRequest.getSecretKey(); if (secretKey != null) { return secretKey; @@ -806,47 +647,15 @@ public class DeviceController extends BaseController { @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(TENANT_ID, strTenantId); checkParameter(DEVICE_ID, strDeviceId); - try { - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId, Operation.ASSIGN_TO_TENANT); + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + Device device = checkDeviceId(deviceId, Operation.ASSIGN_TO_TENANT); - TenantId newTenantId = TenantId.fromUUID(toUUID(strTenantId)); - Tenant newTenant = tenantService.findTenantById(newTenantId); - if (newTenant == null) { - throw new ThingsboardException("Could not find the specified Tenant!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); - } - - Device assignedDevice = deviceService.assignDeviceToTenant(newTenantId, device); - - logEntityAction(getCurrentUser(), deviceId, assignedDevice, - assignedDevice.getCustomerId(), - ActionType.ASSIGNED_TO_TENANT, null, strTenantId, newTenant.getName()); - - Tenant currentTenant = tenantService.findTenantById(getTenantId()); - pushAssignedFromNotification(currentTenant, newTenantId, assignedDevice); - - return assignedDevice; - } catch (Exception e) { - logEntityAction(getCurrentUser(), emptyId(EntityType.DEVICE), null, - null, - ActionType.ASSIGNED_TO_TENANT, e, strTenantId); - throw handleException(e); - } - } - - private void pushAssignedFromNotification(Tenant currentTenant, TenantId newTenantId, Device assignedDevice) { - String data = entityToStr(assignedDevice); - if (data != null) { - TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_ASSIGNED_FROM_TENANT, assignedDevice.getId(), assignedDevice.getCustomerId(), getMetaDataForAssignedFrom(currentTenant), TbMsgDataType.JSON, data); - tbClusterService.pushMsgToRuleEngine(newTenantId, assignedDevice.getId(), tbMsg, null); + TenantId newTenantId = TenantId.fromUUID(toUUID(strTenantId)); + Tenant newTenant = tenantService.findTenantById(newTenantId); + if (newTenant == null) { + throw new ThingsboardException("Could not find the specified Tenant!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); } - } - - private TbMsgMetaData getMetaDataForAssignedFrom(Tenant tenant) { - TbMsgMetaData metaData = new TbMsgMetaData(); - metaData.putValue("assignedFromTenantId", tenant.getId().getId().toString()); - metaData.putValue("assignedFromTenantName", tenant.getName()); - return metaData; + return tbDeviceService.assignDeviceToTenant(device, newTenant, getCurrentUser()); } @ApiOperation(value = "Assign device to edge (assignDeviceToEdge)", @@ -865,28 +674,13 @@ public class DeviceController extends BaseController { @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(DEVICE_ID, strDeviceId); - try { - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.READ); - - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - checkDeviceId(deviceId, Operation.READ); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + Edge edge = checkEdgeId(edgeId, Operation.READ); - Device savedDevice = checkNotNull(deviceService.assignDeviceToEdge(getCurrentUser().getTenantId(), deviceId, edgeId)); + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + checkDeviceId(deviceId, Operation.READ); - logEntityAction(deviceId, savedDevice, - savedDevice.getCustomerId(), - ActionType.ASSIGNED_TO_EDGE, null, strDeviceId, strEdgeId, edge.getName()); - - sendEntityAssignToEdgeNotificationMsg(getTenantId(), edgeId, savedDevice.getId(), EdgeEventActionType.ASSIGNED_TO_EDGE); - - return savedDevice; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), null, - null, - ActionType.ASSIGNED_TO_EDGE, e, strDeviceId, strEdgeId); - throw handleException(e); - } + return tbDeviceService.assignDeviceToEdge(getTenantId(), deviceId, edge, getCurrentUser()); } @ApiOperation(value = "Unassign device from edge (unassignDeviceFromEdge)", @@ -905,28 +699,12 @@ public class DeviceController extends BaseController { @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(DEVICE_ID, strDeviceId); - try { - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.READ); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + Edge edge = checkEdgeId(edgeId, Operation.READ); - DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId, Operation.READ); - - Device savedDevice = checkNotNull(deviceService.unassignDeviceFromEdge(getCurrentUser().getTenantId(), deviceId, edgeId)); - - logEntityAction(deviceId, device, - device.getCustomerId(), - ActionType.UNASSIGNED_FROM_EDGE, null, strDeviceId, strEdgeId, edge.getName()); - - sendEntityAssignToEdgeNotificationMsg(getTenantId(), edgeId, savedDevice.getId(), EdgeEventActionType.UNASSIGNED_FROM_EDGE); - - return savedDevice; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.DEVICE), null, - null, - ActionType.UNASSIGNED_FROM_EDGE, e, strDeviceId, strEdgeId); - throw handleException(e); - } + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); + Device device = checkDeviceId(deviceId, Operation.READ); + return tbDeviceService.unassignDeviceFromEdge(device, edge, getCurrentUser()); } @ApiOperation(value = "Get devices assigned to edge (getEdgeDevices)", @@ -992,10 +770,11 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/devices/count/{otaPackageType}/{deviceProfileId}", method = RequestMethod.GET) @ResponseBody - public Long countByDeviceProfileAndEmptyOtaPackage(@ApiParam(value = "OTA package type", allowableValues = "FIRMWARE, SOFTWARE") - @PathVariable("otaPackageType") String otaPackageType, - @ApiParam(value = "Device Profile Id. I.g. '784f394c-42b6-435a-983c-b7beff2784f9'") - @PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException { + public Long countByDeviceProfileAndEmptyOtaPackage + (@ApiParam(value = "OTA package type", allowableValues = "FIRMWARE, SOFTWARE") + @PathVariable("otaPackageType") String otaPackageType, + @ApiParam(value = "Device Profile Id. I.g. '784f394c-42b6-435a-983c-b7beff2784f9'") + @PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException { checkParameter("OtaPackageType", otaPackageType); checkParameter("DeviceProfileId", deviceProfileId); try { @@ -1012,11 +791,10 @@ public class DeviceController extends BaseController { notes = "There's an ability to import the bulk of devices using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PostMapping("/device/bulk_import") - public BulkImportResult processDevicesBulkImport(@RequestBody BulkImportRequest request) throws Exception { + public BulkImportResult processDevicesBulkImport(@RequestBody BulkImportRequest request) throws + Exception { SecurityUser user = getCurrentUser(); - return deviceBulkImportService.processBulkImport(request, user, importedDeviceInfo -> { - onDeviceCreatedOrUpdated(importedDeviceInfo.getEntity(), importedDeviceInfo.getOldEntity(), importedDeviceInfo.isUpdated(), user); - }); + return deviceBulkImportService.processBulkImport(request, user); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index a516a1e4a3..8a01e9ef02 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -34,10 +34,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntitySubtype; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeInfo; import org.thingsboard.server.common.data.edge.EdgeSearchQuery; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; @@ -48,20 +45,19 @@ import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.edge.EdgeBulkImportService; +import org.thingsboard.server.service.entitiy.edge.TbEdgeService; import org.thingsboard.server.service.importing.BulkImportRequest; import org.thingsboard.server.service.importing.BulkImportResult; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -90,6 +86,7 @@ import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LI @RequiredArgsConstructor public class EdgeController extends BaseController { private final EdgeBulkImportService edgeBulkImportService; + private final TbEdgeService tbEdgeService; public static final String EDGE_ID = "edgeId"; public static final String EDGE_SECURITY_CHECK = "If the user has the authority of 'Tenant Administrator', the server checks that the edge is owned by the same tenant. " + @@ -144,84 +141,43 @@ public class EdgeController extends BaseController { "Specify existing Edge id to update the edge. " + "Referencing non-existing Edge Id will cause 'Not Found' error." + "\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes." - + TENANT_AUTHORITY_PARAGRAPH, + + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge", method = RequestMethod.POST) @ResponseBody public Edge saveEdge(@ApiParam(value = "A JSON value representing the edge.", required = true) @RequestBody Edge edge) throws ThingsboardException { - try { - TenantId tenantId = getCurrentUser().getTenantId(); - edge.setTenantId(tenantId); - boolean created = edge.getId() == null; - - RuleChain edgeTemplateRootRuleChain = null; - if (created) { - edgeTemplateRootRuleChain = ruleChainService.getEdgeTemplateRootRuleChain(tenantId); - if (edgeTemplateRootRuleChain == null) { - throw new DataValidationException("Root edge rule chain is not available!"); - } + TenantId tenantId = getCurrentUser().getTenantId(); + edge.setTenantId(tenantId); + boolean created = edge.getId() == null; + + RuleChain edgeTemplateRootRuleChain = null; + if (created) { + edgeTemplateRootRuleChain = ruleChainService.getEdgeTemplateRootRuleChain(tenantId); + if (edgeTemplateRootRuleChain == null) { + throw new DataValidationException("Root edge rule chain is not available!"); } - - Operation operation = created ? Operation.CREATE : Operation.WRITE; - - accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, operation, - edge.getId(), edge); - - Edge savedEdge = checkNotNull(edgeService.saveEdge(edge)); - onEdgeCreatedOrUpdated(tenantId, savedEdge, edgeTemplateRootRuleChain, !created, getCurrentUser()); - - return savedEdge; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.EDGE), edge, - null, edge.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); - throw handleException(e); } - } - private void onEdgeCreatedOrUpdated(TenantId tenantId, Edge edge, RuleChain edgeTemplateRootRuleChain, boolean updated, SecurityUser user) throws Exception { - if (!updated) { - ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), edge.getId()); - edgeNotificationService.setEdgeRootRuleChain(tenantId, edge, edgeTemplateRootRuleChain.getId()); - edgeService.assignDefaultRuleChainsToEdge(tenantId, edge.getId()); - } + Operation operation = created ? Operation.CREATE : Operation.WRITE; - tbClusterService.broadcastEntityStateChangeEvent(edge.getTenantId(), edge.getId(), - updated ? ComponentLifecycleEvent.UPDATED : ComponentLifecycleEvent.CREATED); + accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, operation, edge.getId(), edge); - logEntityAction(user, edge.getId(), edge, null, updated ? ActionType.UPDATED : ActionType.ADDED, null); + return tbEdgeService.saveEdge(edge, edgeTemplateRootRuleChain, getCurrentUser()); } @ApiOperation(value = "Delete edge (deleteEdge)", - notes = "Deletes the edge. Referencing non-existing edge Id will cause an error."+ TENANT_AUTHORITY_PARAGRAPH) + notes = "Deletes the edge. Referencing non-existing edge Id will cause an error." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); - try { - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.DELETE); - edgeService.deleteEdge(getTenantId(), edgeId); - - tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, - ComponentLifecycleEvent.DELETED); - - logEntityAction(edgeId, edge, - null, - ActionType.DELETED, null, strEdgeId); - - } catch (Exception e) { - - logEntityAction(emptyId(EntityType.EDGE), - null, - null, - ActionType.DELETED, e, strEdgeId); - - throw handleException(e); - } + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + Edge edge = checkEdgeId(edgeId, Operation.DELETE); + tbEdgeService.deleteEdge(edge, getCurrentUser()); } @ApiOperation(value = "Get Tenant Edges (getEdges)", @@ -261,32 +217,11 @@ public class EdgeController extends BaseController { @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(EDGE_ID, strEdgeId); - try { - CustomerId customerId = new CustomerId(toUUID(strCustomerId)); - Customer customer = checkCustomerId(customerId, Operation.READ); - - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - checkEdgeId(edgeId, Operation.ASSIGN_TO_CUSTOMER); - - Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(getCurrentUser().getTenantId(), edgeId, customerId)); - - tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, - ComponentLifecycleEvent.UPDATED); - - logEntityAction(edgeId, savedEdge, - savedEdge.getCustomerId(), - ActionType.ASSIGNED_TO_CUSTOMER, null, strEdgeId, strCustomerId, customer.getName()); - - sendEntityAssignToCustomerNotificationMsg(savedEdge.getTenantId(), savedEdge.getId(), - customerId, EdgeEventActionType.ASSIGNED_TO_CUSTOMER); - - return savedEdge; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.EDGE), null, - null, - ActionType.ASSIGNED_TO_CUSTOMER, e, strEdgeId, strCustomerId); - throw handleException(e); - } + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); + Customer customer = checkCustomerId(customerId, Operation.READ); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + checkEdgeId(edgeId, Operation.ASSIGN_TO_CUSTOMER); + return tbEdgeService.assignEdgeToCustomer(getTenantId(), edgeId, customer, getCurrentUser()); } @ApiOperation(value = "Unassign edge from customer (unassignEdgeFromCustomer)", @@ -298,33 +233,14 @@ public class EdgeController extends BaseController { public Edge unassignEdgeFromCustomer(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); - try { - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.UNASSIGN_FROM_CUSTOMER); - if (edge.getCustomerId() == null || edge.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { - throw new IncorrectParameterException("Edge isn't assigned to any customer!"); - } - Customer customer = checkCustomerId(edge.getCustomerId(), Operation.READ); - - Edge savedEdge = checkNotNull(edgeService.unassignEdgeFromCustomer(getCurrentUser().getTenantId(), edgeId)); - - tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, - ComponentLifecycleEvent.UPDATED); - - logEntityAction(edgeId, edge, - edge.getCustomerId(), - ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEdgeId, customer.getId().toString(), customer.getName()); - - sendEntityAssignToCustomerNotificationMsg(savedEdge.getTenantId(), savedEdge.getId(), - customer.getId(), EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER); - - return savedEdge; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.EDGE), null, - null, - ActionType.UNASSIGNED_FROM_CUSTOMER, e, strEdgeId); - throw handleException(e); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + Edge edge = checkEdgeId(edgeId, Operation.UNASSIGN_FROM_CUSTOMER); + if (edge.getCustomerId() == null || edge.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { + throw new IncorrectParameterException("Edge isn't assigned to any customer!"); } + Customer customer = checkCustomerId(edge.getCustomerId(), Operation.READ); + + return tbEdgeService.unassignEdgeFromCustomer(edge, customer, getCurrentUser()); } @ApiOperation(value = "Make edge publicly available (assignEdgeToPublicCustomer)", @@ -338,26 +254,9 @@ public class EdgeController extends BaseController { public Edge assignEdgeToPublicCustomer(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); - try { - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.ASSIGN_TO_CUSTOMER); - Customer publicCustomer = customerService.findOrCreatePublicCustomer(edge.getTenantId()); - Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(getCurrentUser().getTenantId(), edgeId, publicCustomer.getId())); - - tbClusterService.broadcastEntityStateChangeEvent(getTenantId(), edgeId, - ComponentLifecycleEvent.UPDATED); - - logEntityAction(edgeId, savedEdge, - savedEdge.getCustomerId(), - ActionType.ASSIGNED_TO_CUSTOMER, null, strEdgeId, publicCustomer.getId().toString(), publicCustomer.getName()); - - return savedEdge; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.EDGE), null, - null, - ActionType.ASSIGNED_TO_CUSTOMER, e, strEdgeId); - throw handleException(e); - } + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + checkEdgeId(edgeId, Operation.ASSIGN_TO_CUSTOMER); + return tbEdgeService.assignEdgeToPublicCustomer(getTenantId(), edgeId, getCurrentUser()); } @ApiOperation(value = "Get Tenant Edges (getTenantEdges)", @@ -455,29 +354,12 @@ public class EdgeController extends BaseController { @PathVariable("ruleChainId") String strRuleChainId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter("ruleChainId", strRuleChainId); - try { - RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); - checkRuleChain(ruleChainId, Operation.WRITE); - - EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); - Edge edge = checkEdgeId(edgeId, Operation.WRITE); - accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.WRITE, - edge.getId(), edge); - - Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(getTenantId(), edge, ruleChainId); - - tbClusterService.broadcastEntityStateChangeEvent(updatedEdge.getTenantId(), updatedEdge.getId(), ComponentLifecycleEvent.UPDATED); - - logEntityAction(updatedEdge.getId(), updatedEdge, null, ActionType.UPDATED, null); - - return updatedEdge; - } catch (Exception e) { - logEntityAction(emptyId(EntityType.EDGE), - null, - null, - ActionType.UPDATED, e, strEdgeId); - throw handleException(e); - } + RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); + checkRuleChain(ruleChainId, Operation.WRITE); + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + Edge edge = checkEdgeId(edgeId, Operation.WRITE); + accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, Operation.WRITE, edge.getId(), edge); + return tbEdgeService.setEdgeRootRuleChain(edge, ruleChainId, getCurrentUser()); } @ApiOperation(value = "Get Customer Edges (getCustomerEdges)", @@ -693,12 +575,6 @@ public class EdgeController extends BaseController { throw new DataValidationException("Root edge rule chain is not available!"); } - return edgeBulkImportService.processBulkImport(request, user, importedAssetInfo -> { - try { - onEdgeCreatedOrUpdated(user.getTenantId(), importedAssetInfo.getEntity(), edgeTemplateRootRuleChain, importedAssetInfo.isUpdated(), user); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); + return edgeBulkImportService.processBulkImport(request, user); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantController.java b/application/src/main/java/org/thingsboard/server/controller/TenantController.java index 496cd60e81..6d6e99cbba 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantController.java @@ -18,8 +18,9 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; @@ -36,10 +37,9 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.install.InstallScripts; +import org.thingsboard.server.service.entitiy.tenant.TbTenantService; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; @@ -63,14 +63,13 @@ import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LI @TbCoreComponent @RequestMapping("/api") @Slf4j +@RequiredArgsConstructor public class TenantController extends BaseController { private static final String TENANT_INFO_DESCRIPTION = "The Tenant Info object extends regular Tenant object and includes Tenant Profile name. "; - @Autowired - private InstallScripts installScripts; - @Autowired - private TenantService tenantService; + private final TenantService tenantService; + private final TbTenantService tbTenantService; @ApiOperation(value = "Get Tenant (getTenantById)", notes = "Fetch the Tenant object based on the provided Tenant Id. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @@ -121,27 +120,10 @@ public class TenantController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenant", method = RequestMethod.POST) @ResponseBody - public Tenant saveTenant( - @ApiParam(value = "A JSON value representing the tenant.") - @RequestBody Tenant tenant) throws ThingsboardException { - try { - boolean newTenant = tenant.getId() == null; - - checkEntity(tenant.getId(), tenant, Resource.TENANT); - - tenant = checkNotNull(tenantService.saveTenant(tenant)); - if (newTenant) { - installScripts.createDefaultRuleChains(tenant.getId()); - installScripts.createDefaultEdgeRuleChains(tenant.getId()); - } - tenantProfileCache.evict(tenant.getId()); - tbClusterService.onTenantChange(tenant, null); - tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), - newTenant ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); - return tenant; - } catch (Exception e) { - throw handleException(e); - } + public Tenant saveTenant(@ApiParam(value = "A JSON value representing the tenant.") + @RequestBody Tenant tenant) throws ThingsboardException { + checkEntity(tenant.getId(), tenant, Resource.TENANT); + return tbTenantService.save(tenant); } @ApiOperation(value = "Delete Tenant (deleteTenant)", @@ -149,20 +131,12 @@ public class TenantController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenant/{tenantId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteTenant( - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) - @PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException { + public void deleteTenant(@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) + @PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException { checkParameter(TENANT_ID, strTenantId); - try { - TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); - Tenant tenant = checkTenantId(tenantId, Operation.DELETE); - tenantService.deleteTenant(tenantId); - tenantProfileCache.evict(tenantId); - tbClusterService.onTenantDelete(tenant, null); - tbClusterService.broadcastEntityStateChangeEvent(tenantId, tenantId, ComponentLifecycleEvent.DELETED); - } catch (Exception e) { - throw handleException(e); - } + TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); + Tenant tenant = checkTenantId(tenantId, Operation.DELETE); + tbTenantService.delete(tenant); } @ApiOperation(value = "Get Tenants (getTenants)", notes = "Returns a page of tenants registered in the platform. " + PAGE_DATA_PARAMETERS + SYSTEM_AUTHORITY_PARAGRAPH) diff --git a/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java index 4c75f7d45d..e9999d2dc1 100644 --- a/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/asset/AssetBulkImportService.java @@ -18,6 +18,7 @@ package org.thingsboard.server.service.asset; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityType; @@ -25,6 +26,7 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.asset.TbAssetService; import org.thingsboard.server.service.importing.AbstractBulkImportService; import org.thingsboard.server.service.importing.BulkImportColumnType; import org.thingsboard.server.service.security.model.SecurityUser; @@ -37,6 +39,7 @@ import java.util.Optional; @RequiredArgsConstructor public class AssetBulkImportService extends AbstractBulkImportService { private final AssetService assetService; + private final TbAssetService tbAssetService; @Override protected void setEntityFields(Asset entity, Map fields) { @@ -61,8 +64,9 @@ public class AssetBulkImportService extends AbstractBulkImportService { } @Override - protected Asset saveEntity(Asset entity, Map fields) { - return assetService.saveAsset(entity); + @SneakyThrows + protected Asset saveEntity(SecurityUser user, Asset entity, Map fields) { + return tbAssetService.save(entity, user); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java index cd655a2467..34c30d5225 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java @@ -49,6 +49,7 @@ import org.thingsboard.server.dao.device.DeviceProfileService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.device.TbDeviceService; import org.thingsboard.server.service.importing.AbstractBulkImportService; import org.thingsboard.server.service.importing.BulkImportColumnType; import org.thingsboard.server.service.security.model.SecurityUser; @@ -68,6 +69,7 @@ import java.util.concurrent.locks.ReentrantLock; @RequiredArgsConstructor public class DeviceBulkImportService extends AbstractBulkImportService { protected final DeviceService deviceService; + protected final TbDeviceService tbDeviceService; protected final DeviceCredentialsService deviceCredentialsService; protected final DeviceProfileService deviceProfileService; @@ -99,7 +101,8 @@ public class DeviceBulkImportService extends AbstractBulkImportService { } @Override - protected Device saveEntity(Device entity, Map fields) { + @SneakyThrows + protected Device saveEntity(SecurityUser user, Device entity, Map fields) { DeviceCredentials deviceCredentials; try { deviceCredentials = createDeviceCredentials(fields); @@ -118,7 +121,7 @@ public class DeviceBulkImportService extends AbstractBulkImportService { } entity.setDeviceProfileId(deviceProfile.getId()); - return deviceService.saveDeviceWithCredentials(entity, deviceCredentials); + return tbDeviceService.saveDeviceWithCredentials(user.getTenantId(), entity, deviceCredentials, user); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java index 615a7cddd2..038dcadfc8 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java @@ -18,13 +18,17 @@ package org.thingsboard.server.service.edge; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.edge.EdgeService; +import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.edge.TbEdgeService; import org.thingsboard.server.service.importing.AbstractBulkImportService; import org.thingsboard.server.service.importing.BulkImportColumnType; import org.thingsboard.server.service.security.model.SecurityUser; @@ -37,6 +41,8 @@ import java.util.Optional; @RequiredArgsConstructor public class EdgeBulkImportService extends AbstractBulkImportService { private final EdgeService edgeService; + private final TbEdgeService tbEdgeService; + private final RuleChainService ruleChainService; @Override protected void setEntityFields(Edge entity, Map fields) { @@ -66,9 +72,11 @@ public class EdgeBulkImportService extends AbstractBulkImportService { entity.setAdditionalInfo(additionalInfo); } + @SneakyThrows @Override - protected Edge saveEntity(Edge entity, Map fields) { - return edgeService.saveEdge(entity); + protected Edge saveEntity(SecurityUser user, Edge entity, Map fields) { + RuleChain edgeTemplateRootRuleChain = ruleChainService.getEdgeTemplateRootRuleChain(user.getTenantId()); + return tbEdgeService.saveEdge(entity, edgeTemplateRootRuleChain, user); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java new file mode 100644 index 0000000000..e2ccc1f3d2 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/AbstractTbEntityService.java @@ -0,0 +1,201 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.thingsboard.server.cluster.TbClusterService; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.HasName; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.AlarmInfo; +import org.thingsboard.server.common.data.alarm.AlarmQuery; +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.CustomerId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityIdFactory; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageDataIterableByTenantIdEntityId; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.alarm.AlarmService; +import org.thingsboard.server.dao.asset.AssetService; +import org.thingsboard.server.dao.customer.CustomerService; +import org.thingsboard.server.dao.device.ClaimDevicesService; +import org.thingsboard.server.dao.device.DeviceCredentialsService; +import org.thingsboard.server.dao.device.DeviceService; +import org.thingsboard.server.dao.edge.EdgeService; +import org.thingsboard.server.dao.exception.DataValidationException; +import org.thingsboard.server.dao.exception.IncorrectParameterException; +import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.rule.RuleChainService; +import org.thingsboard.server.dao.tenant.TbTenantProfileCache; +import org.thingsboard.server.dao.tenant.TenantService; +import org.thingsboard.server.service.action.EntityActionService; +import org.thingsboard.server.service.edge.EdgeNotificationService; +import org.thingsboard.server.service.executors.DbCallbackExecutorService; + +import javax.mail.MessagingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Slf4j +public abstract class AbstractTbEntityService { + + protected static final int DEFAULT_PAGE_SIZE = 1000; + + private static final ObjectMapper json = new ObjectMapper(); + + @Value("${server.log_controller_error_stack_trace}") + @Getter + private boolean logControllerErrorStackTrace; + @Value("${edges.enabled}") + @Getter + protected boolean edgesEnabled; + + @Autowired + protected DbCallbackExecutorService dbExecutor; + @Autowired + protected TbNotificationEntityService notificationEntityService; + @Autowired(required = false) + protected EdgeService edgeService; + @Autowired + protected AlarmService alarmService; + @Autowired + protected EntityActionService entityActionService; + @Autowired + protected DeviceService deviceService; + @Autowired + protected AssetService assetService; + @Autowired + protected DeviceCredentialsService deviceCredentialsService; + @Autowired + protected TenantService tenantService; + @Autowired + protected CustomerService customerService; + @Autowired + protected ClaimDevicesService claimDevicesService; + @Autowired + protected TbTenantProfileCache tenantProfileCache; + @Autowired + protected RuleChainService ruleChainService; + @Autowired + protected EdgeNotificationService edgeNotificationService; + + protected ListenableFuture removeAlarmsByEntityId(TenantId tenantId, EntityId entityId) { + ListenableFuture> alarmsFuture = + alarmService.findAlarms(tenantId, new AlarmQuery(entityId, new TimePageLink(Integer.MAX_VALUE), null, null, false)); + + ListenableFuture> alarmIdsFuture = Futures.transform(alarmsFuture, page -> + page.getData().stream().map(AlarmInfo::getId).collect(Collectors.toList()), dbExecutor); + + return Futures.transform(alarmIdsFuture, ids -> { + ids.stream().map(alarmId -> alarmService.deleteAlarm(tenantId, alarmId)).collect(Collectors.toList()); + return null; + }, dbExecutor); + } + + protected void logEntityAction(User user, TenantId tenantId, I entityId, E entity, CustomerId customerId, + ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { + if (user != null) { + entityActionService.logEntityAction(user, entityId, entity, customerId, actionType, e, additionalInfo); + } else if (e == null) { + entityActionService.pushEntityActionToRuleEngine(entityId, entity, tenantId, customerId, actionType, null, additionalInfo); + } + } + + protected T checkNotNull(T reference) throws ThingsboardException { + return checkNotNull(reference, "Requested item wasn't found!"); + } + + protected T checkNotNull(T reference, String notFoundMessage) throws ThingsboardException { + if (reference == null) { + throw new ThingsboardException(notFoundMessage, ThingsboardErrorCode.ITEM_NOT_FOUND); + } + return reference; + } + + protected T checkNotNull(Optional reference) throws ThingsboardException { + return checkNotNull(reference, "Requested item wasn't found!"); + } + + protected T checkNotNull(Optional reference, String notFoundMessage) throws ThingsboardException { + if (reference.isPresent()) { + return reference.get(); + } else { + throw new ThingsboardException(notFoundMessage, ThingsboardErrorCode.ITEM_NOT_FOUND); + } + } + + protected ThingsboardException handleException(Exception exception) { + return handleException(exception, true); + } + + protected ThingsboardException handleException(Exception exception, boolean logException) { + if (logException && logControllerErrorStackTrace) { + log.error("Error [{}]", exception.getMessage(), exception); + } + + String cause = ""; + if (exception.getCause() != null) { + cause = exception.getCause().getClass().getCanonicalName(); + } + + if (exception instanceof ThingsboardException) { + return (ThingsboardException) exception; + } else if (exception instanceof IllegalArgumentException || exception instanceof IncorrectParameterException + || exception instanceof DataValidationException || cause.contains("IncorrectParameterException")) { + return new ThingsboardException(exception.getMessage(), ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } else if (exception instanceof MessagingException) { + return new ThingsboardException("Unable to send mail: " + exception.getMessage(), ThingsboardErrorCode.GENERAL); + } else { + return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.GENERAL); + } + } + + @SuppressWarnings("unchecked") + protected I emptyId(EntityType entityType) { + return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); + } + + protected List findRelatedEdgeIds(TenantId tenantId, EntityId entityId) { + if (!edgesEnabled) { + return null; + } + if (EntityType.EDGE.equals(entityId.getEntityType())) { + return Collections.singletonList(new EdgeId(entityId.getId())); + } + PageDataIterableByTenantIdEntityId relatedEdgeIdsIterator = + new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE); + List result = new ArrayList<>(); + for (EdgeId edgeId : relatedEdgeIdsIterator) { + result.add(edgeId); + } + return result; + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java new file mode 100644 index 0000000000..b6ab974988 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java @@ -0,0 +1,299 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; +import org.thingsboard.server.cluster.TbClusterService; +import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.HasName; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventActionType; +import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgDataType; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.action.EntityActionService; +import org.thingsboard.server.service.gateway_device.GatewayNotificationsService; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.List; + +@Slf4j +@Service +@TbCoreComponent +@RequiredArgsConstructor +public class DefaultTbNotificationEntityService implements TbNotificationEntityService { + private static final ObjectMapper json = new ObjectMapper(); + + private final EntityActionService entityActionService; + private final TbClusterService tbClusterService; + private final GatewayNotificationsService gatewayNotificationsService; + + @Override + public void notifyEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, + ActionType actionType, SecurityUser user, Exception e, + Object... additionalInfo) { + logEntityAction(tenantId, entityId, entity, customerId, actionType, user, e, additionalInfo); + } + + @Override + public void notifyDeleteEntity(TenantId tenantId, I entityId, E entity, + CustomerId customerId, List relatedEdgeIds, + SecurityUser user, Object... additionalInfo) { + logEntityAction(tenantId, entityId, entity, customerId, ActionType.DELETED, user, additionalInfo); + sendDeleteNotificationMsg(tenantId, entityId, relatedEdgeIds); + } + + @Override + public void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId, + CustomerId customerId, E entity, + ActionType actionType, + EdgeEventActionType edgeActionType, + SecurityUser user, boolean sendToEdge, + Object... additionalInfo) { + logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); + + if (sendToEdge) { + sendEntityAssignToCustomerNotificationMsg(tenantId, entityId, customerId, edgeActionType); + } + } + + @Override + public void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId, + CustomerId customerId, EdgeId edgeId, + E entity, ActionType actionType, + EdgeEventActionType edgeActionType, + SecurityUser user, Object... additionalInfo) { + logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); + sendEntityAssignToEdgeNotificationMsg(tenantId, edgeId, entityId, edgeActionType); + } + + @Override + public void notifyCreateOruUpdateTenant(Tenant tenant, ComponentLifecycleEvent event) { + tbClusterService.onTenantChange(tenant, null); + tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), event); + } + + @Override + public void notifyDeleteTenant(Tenant tenant) { + tbClusterService.onTenantDelete(tenant, null); + tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), ComponentLifecycleEvent.DELETED); + } + + @Override + public void notifyCreateOrUpdateDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, + Device device, Device oldDevice, ActionType actionType, + SecurityUser user, Object... additionalInfo) { + tbClusterService.onDeviceUpdated(device, oldDevice); + logEntityAction(tenantId, deviceId, device, customerId, actionType, user, additionalInfo); + } + + @Override + public void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, + List relatedEdgeIds, SecurityUser user, Object... additionalInfo) { + gatewayNotificationsService.onDeviceDeleted(device); + tbClusterService.onDeviceDeleted(device, null); + + notifyDeleteEntity(tenantId, deviceId, device, customerId, relatedEdgeIds, user, additionalInfo); + } + + @Override + public void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, + DeviceCredentials deviceCredentials, SecurityUser user) { + tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(tenantId, deviceCredentials.getDeviceId(), deviceCredentials), null); + sendEntityNotificationMsg(tenantId, deviceId, EdgeEventActionType.CREDENTIALS_UPDATED); + logEntityAction(tenantId, deviceId, device, customerId, ActionType.CREDENTIALS_UPDATED, user, deviceCredentials); + } + + @Override + public void notifyAssignDeviceToTenant(TenantId tenantId, TenantId newTenantId, DeviceId deviceId, CustomerId customerId, + Device device, Tenant tenant, SecurityUser user, Object... additionalInfo) { + logEntityAction(tenantId, deviceId, device, customerId, ActionType.ASSIGNED_TO_TENANT, user, additionalInfo); + pushAssignedFromNotification(tenant, newTenantId, device); + } + + @Override + public void notifyCreateOrUpdateAsset(TenantId tenantId, AssetId assetId, CustomerId customerId, Asset asset, + ActionType actionType, SecurityUser user, Object... additionalInfo) { + logEntityAction(tenantId, assetId, asset, customerId, actionType, user, additionalInfo); + + if (actionType == ActionType.UPDATED) { + sendEntityNotificationMsg(asset.getTenantId(), asset.getId(), EdgeEventActionType.UPDATED); + } + } + + @Override + public void notifyEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge, ActionType actionType, + SecurityUser user, Object... additionalInfo) { + ComponentLifecycleEvent lifecycleEvent; + EdgeEventActionType edgeEventActionType = null; + switch (actionType) { + case ADDED: + lifecycleEvent = ComponentLifecycleEvent.CREATED; + break; + case UPDATED: + lifecycleEvent = ComponentLifecycleEvent.UPDATED; + break; + case ASSIGNED_TO_CUSTOMER: + lifecycleEvent = ComponentLifecycleEvent.UPDATED; + edgeEventActionType = EdgeEventActionType.ASSIGNED_TO_CUSTOMER; + break; + case UNASSIGNED_FROM_CUSTOMER: + lifecycleEvent = ComponentLifecycleEvent.UPDATED; + edgeEventActionType = EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER; + break; + case DELETED: + lifecycleEvent = ComponentLifecycleEvent.DELETED; + break; + default: + throw new IllegalArgumentException("Unknown actionType: " + actionType); + } + + tbClusterService.broadcastEntityStateChangeEvent(tenantId, edgeId, lifecycleEvent); + logEntityAction(tenantId, edgeId, edge, customerId, actionType, user, additionalInfo); + + //Send notification to edge + if (edgeEventActionType != null) { + sendEntityAssignToCustomerNotificationMsg(tenantId, edgeId, customerId, edgeEventActionType); + } + } + + @Override + public void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, SecurityUser user, Object... additionalInfo) { + logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarm, alarm.getCustomerId(), actionType, user, additionalInfo); + sendEntityNotificationMsg(alarm.getTenantId(), alarm.getId(), edgeTypeByActionType (actionType)); + } + + @Override + public void notifyDeleteAlarm(Alarm alarm, SecurityUser user, List relatedEdgeIds) { + logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarm, alarm.getCustomerId(), ActionType.ALARM_DELETE, user, null); + sendAlarmDeleteNotificationMsg(alarm, relatedEdgeIds); + } + + private void logEntityAction(TenantId tenantId, I entityId, E entity, CustomerId customerId, + ActionType actionType, SecurityUser user, Object... additionalInfo) { + logEntityAction(tenantId, entityId, entity, customerId, actionType, user, null, additionalInfo); + } + + private void logEntityAction(TenantId tenantId, I entityId, E entity, CustomerId customerId, + ActionType actionType, SecurityUser user, Exception e, Object... additionalInfo) { + if (user != null) { + entityActionService.logEntityAction(user, entityId, entity, customerId, actionType, e, additionalInfo); + } else if (e == null) { + entityActionService.pushEntityActionToRuleEngine(entityId, entity, tenantId, customerId, actionType, null, additionalInfo); + } + } + + private void sendEntityNotificationMsg(TenantId tenantId, EntityId entityId, EdgeEventActionType action) { + sendNotificationMsgToEdgeService(tenantId, null, entityId, null, null, action); + } + + private void sendEntityAssignToCustomerNotificationMsg(TenantId tenantId, EntityId entityId, CustomerId customerId, EdgeEventActionType action) { + try { + sendNotificationMsgToEdgeService(tenantId, null, entityId, json.writeValueAsString(customerId), null, action); + } catch (Exception e) { + log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e); + } + } + + private void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List edgeIds) { + sendDeleteNotificationMsg(tenantId, entityId, edgeIds, null); + } + + protected void sendAlarmDeleteNotificationMsg(Alarm alarm, List relatedEdgeIds) { + try { + sendDeleteNotificationMsg(alarm.getTenantId(), alarm.getId(), relatedEdgeIds, json.writeValueAsString(alarm)); + } catch (Exception e) { + log.warn("Failed to push delete alarm msg to core: {}", alarm, e); + } + } + private void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List edgeIds, String body) { + if (edgeIds != null && !edgeIds.isEmpty()) { + for (EdgeId edgeId : edgeIds) { + sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, null, EdgeEventActionType.DELETED); + } + } + } + + private void sendEntityAssignToEdgeNotificationMsg(TenantId tenantId, EdgeId edgeId, EntityId entityId, EdgeEventActionType action) { + sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, null, action); + } + + private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, EdgeEventActionType action) { + tbClusterService.sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, type, action); + } + + private void pushAssignedFromNotification(Tenant currentTenant, TenantId newTenantId, Device assignedDevice) { + String data = entityToStr(assignedDevice); + if (data != null) { + TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_ASSIGNED_FROM_TENANT, assignedDevice.getId(), assignedDevice.getCustomerId(), getMetaDataForAssignedFrom(currentTenant), TbMsgDataType.JSON, data); + tbClusterService.pushMsgToRuleEngine(newTenantId, assignedDevice.getId(), tbMsg, null); + } + } + + private TbMsgMetaData getMetaDataForAssignedFrom(Tenant tenant) { + TbMsgMetaData metaData = new TbMsgMetaData(); + metaData.putValue("assignedFromTenantId", tenant.getId().getId().toString()); + metaData.putValue("assignedFromTenantName", tenant.getName()); + return metaData; + } + + private String entityToStr(E entity) { + try { + return json.writeValueAsString(json.valueToTree(entity)); + } catch (JsonProcessingException e) { + log.warn("[{}] Failed to convert entity to string!", entity, e); + } + return null; + } + + private EdgeEventActionType edgeTypeByActionType (ActionType actionType) { + switch (actionType) { + case ADDED: + return EdgeEventActionType.ADDED; + case UPDATED: + return EdgeEventActionType.UPDATED; + case ALARM_ACK: + return EdgeEventActionType.ALARM_ACK; + case ALARM_CLEAR: + return EdgeEventActionType.ALARM_CLEAR; + case DELETED: + return EdgeEventActionType.DELETED; + default: + return null; + } + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java new file mode 100644 index 0000000000..181a1f41eb --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/TbNotificationEntityService.java @@ -0,0 +1,86 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy; + +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.HasName; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventActionType; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.List; + +public interface TbNotificationEntityService { + + void notifyEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, + ActionType actionType, SecurityUser user, Exception e, + Object... additionalInfo); + + void notifyDeleteEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, + List relatedEdgeIds, SecurityUser user, + Object... additionalInfo); + + void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId, + CustomerId customerId, E entity, + ActionType actionType, + EdgeEventActionType edgeActionType, + SecurityUser user, boolean sendToEdge, + Object... additionalInfo); + + void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId, + CustomerId customerId, EdgeId edgeId, + E entity, ActionType actionType, + EdgeEventActionType edgeActionType, + SecurityUser user, Object... additionalInfo); + + void notifyCreateOruUpdateTenant(Tenant tenant, ComponentLifecycleEvent event); + + void notifyDeleteTenant(Tenant tenant); + + void notifyCreateOrUpdateDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, + Device oldDevice, ActionType actionType, SecurityUser user, Object... additionalInfo); + + void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, + List relatedEdgeIds, SecurityUser user, Object... additionalInfo); + + void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, + DeviceCredentials deviceCredentials, SecurityUser user); + + void notifyAssignDeviceToTenant(TenantId tenantId, TenantId newTenantId, DeviceId deviceId, CustomerId customerId, + Device device, Tenant tenant, SecurityUser user, Object... additionalInfo); + + void notifyCreateOrUpdateAsset(TenantId tenantId, AssetId assetId, CustomerId customerId, Asset asset, + ActionType actionType, SecurityUser user, Object... additionalInfo); + + void notifyEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge, ActionType actionType, SecurityUser user, Object... additionalInfo); + + void notifyCreateOrUpdateAlarm(Alarm alarm, + ActionType actionType, SecurityUser user, Object... additionalInfo); + + void notifyDeleteAlarm(Alarm alarm, SecurityUser user, List relatedEdgeIds); +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java new file mode 100644 index 0000000000..f0ac516393 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -0,0 +1,85 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.alarm; + + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmStatus; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.AbstractTbEntityService; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.List; + +@Service +@TbCoreComponent +@AllArgsConstructor +public class DefaultTbAlarmService extends AbstractTbEntityService implements TbAlarmService { + + @Override + public Alarm save(Alarm alarm, SecurityUser user) throws ThingsboardException { + ActionType actionType = alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + TenantId tenantId = alarm.getTenantId(); + try { + Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm).getAlarm()); + notificationEntityService.notifyCreateOrUpdateAlarm(savedAlarm, actionType, user); + return savedAlarm; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ALARM), alarm, null, actionType, user, e); + throw handleException(e); + } + } + + @Override + public void ack(Alarm alarm, SecurityUser user) throws ThingsboardException { + try { + long ackTs = System.currentTimeMillis(); + alarmService.ackAlarm(user.getTenantId(), alarm.getId(), ackTs).get(); + alarm.setAckTs(ackTs); + alarm.setStatus(alarm.getStatus().isCleared() ? AlarmStatus.CLEARED_ACK : AlarmStatus.ACTIVE_ACK); + notificationEntityService.notifyCreateOrUpdateAlarm(alarm, ActionType.ALARM_ACK, user); + } catch (Exception e) { + throw handleException(e); + } + } + + @Override + public void clear(Alarm alarm, SecurityUser user) throws ThingsboardException { + try { + long clearTs = System.currentTimeMillis(); + alarmService.clearAlarm(user.getTenantId(), alarm.getId(), null, clearTs).get(); + alarm.setClearTs(clearTs); + alarm.setStatus(alarm.getStatus().isAck() ? AlarmStatus.CLEARED_ACK : AlarmStatus.CLEARED_UNACK); + notificationEntityService.notifyCreateOrUpdateAlarm(alarm, ActionType.ALARM_CLEAR, user); + } catch (Exception e) { + throw handleException(e); + } + } + + @Override + public Boolean delete(Alarm alarm, SecurityUser user) throws ThingsboardException { + List relatedEdgeIds = findRelatedEdgeIds(alarm.getTenantId(), alarm.getOriginator()); + notificationEntityService.notifyDeleteAlarm(alarm, user, relatedEdgeIds); + return alarmService.deleteAlarm(alarm.getTenantId(), alarm.getId()).isSuccessful(); + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java new file mode 100644 index 0000000000..7c3613d730 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/TbAlarmService.java @@ -0,0 +1,31 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.alarm; + +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.service.security.model.SecurityUser; + +public interface TbAlarmService { + + Alarm save (Alarm alarm, SecurityUser user) throws ThingsboardException; + + void ack (Alarm alarm, SecurityUser user) throws ThingsboardException; + + void clear (Alarm alarm, SecurityUser user) throws ThingsboardException; + + Boolean delete (Alarm alarm, SecurityUser user) throws ThingsboardException; +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java new file mode 100644 index 0000000000..84b9c707d0 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java @@ -0,0 +1,163 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.asset; + +import com.google.common.util.concurrent.ListenableFuture; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventActionType; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.AbstractTbEntityService; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.List; + +@Service +@TbCoreComponent +@AllArgsConstructor +public class DefaultTbAssetService extends AbstractTbEntityService implements TbAssetService { + @Override + public Asset save(Asset asset, SecurityUser user) throws ThingsboardException { + ActionType actionType = asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + TenantId tenantId = asset.getTenantId(); + try { + Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); + notificationEntityService.notifyCreateOrUpdateAsset(tenantId, savedAsset.getId(), savedAsset.getCustomerId(), asset, actionType, user); + return savedAsset; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), asset, null, actionType, user, e); + throw handleException(e); + } + } + + @Override + public ListenableFuture delete(Asset asset, SecurityUser user) throws ThingsboardException { + TenantId tenantId = asset.getTenantId(); + AssetId assetId = asset.getId(); + try { + List relatedEdgeIds = findRelatedEdgeIds(tenantId, assetId); + assetService.deleteAsset(tenantId, assetId); + notificationEntityService.notifyDeleteEntity(tenantId, assetId, asset, asset.getCustomerId(), relatedEdgeIds, user, asset.toString()); + + return removeAlarmsByEntityId(tenantId, assetId); + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, + ActionType.DELETED, user, e, asset.toString()); + throw handleException(e); + } + } + + @Override + public Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; + CustomerId customerId = customer.getId(); + try { + Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, customerId)); + notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, + actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); + + return savedAsset; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, + actionType, user, e, assetId.toString(), customerId.toString()); + + throw handleException(e); + } + } + + @Override + public Asset unassignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; + try { + Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(tenantId, assetId)); + CustomerId customerId = customer.getId(); + + notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, + actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, + true, customerId.toString(), customer.getName()); + + return savedAsset; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, + actionType, user, e, assetId.toString()); + throw handleException(e); + } + } + + @Override + public Asset assignAssetToPublicCustomer(TenantId tenantId, AssetId assetId, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; + try { + Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); + Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, publicCustomer.getId())); + + notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, savedAsset.getCustomerId(), savedAsset, + actionType, null, user, false, actionType.toString(), + publicCustomer.getId().toString(), publicCustomer.getName()); + + return savedAsset; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, + actionType, user, e, assetId.toString()); + throw handleException(e); + } + } + + @Override + public Asset assignAssetToEdge(TenantId tenantId, AssetId assetId, Edge edge, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_EDGE; + EdgeId edgeId = edge.getId(); + try { + Asset savedAsset = checkNotNull(assetService.assignAssetToEdge(tenantId, assetId, edgeId)); + notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, savedAsset.getCustomerId(), + edgeId, savedAsset, actionType, EdgeEventActionType.ASSIGNED_TO_EDGE, user, assetId.toString(), edgeId.toString(), edge.getName()); + + return savedAsset; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, + actionType, user, e, assetId.toString(), edgeId.toString()); + throw handleException(e); + } + } + + @Override + public Asset unassignAssetFromEdge(TenantId tenantId, Asset asset, Edge edge, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; + AssetId assetId = asset.getId(); + EdgeId edgeId = edge.getId(); + try { + Asset savedAsset = checkNotNull(assetService.unassignAssetFromEdge(tenantId, assetId, edgeId)); + + notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, asset.getCustomerId(), + edgeId, asset, actionType, EdgeEventActionType.UNASSIGNED_FROM_EDGE, user, assetId.toString(), edgeId.toString(), edge.getName()); + return savedAsset; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, + actionType, user, e, assetId.toString(), edgeId.toString()); + throw handleException(e); + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/TbAssetService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/TbAssetService.java new file mode 100644 index 0000000000..c6e1c29940 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/TbAssetService.java @@ -0,0 +1,42 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.asset; + +import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.security.model.SecurityUser; + +public interface TbAssetService { + Asset save(Asset asset, SecurityUser user) throws ThingsboardException; + + ListenableFuture delete(Asset asset, SecurityUser user) throws ThingsboardException; + + Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException; + + Asset unassignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException; + + Asset assignAssetToPublicCustomer(TenantId tenantId, AssetId assetId, SecurityUser user) throws ThingsboardException; + + Asset assignAssetToEdge(TenantId tenantId, AssetId assetId, Edge edge, SecurityUser user) throws ThingsboardException; + + Asset unassignAssetFromEdge(TenantId tenantId, Asset asset, Edge edge, SecurityUser user) throws ThingsboardException; + +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java new file mode 100644 index 0000000000..1bed17f941 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/device/DefaultTbDeviceService.java @@ -0,0 +1,279 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.device; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeEventActionType; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.dao.device.claim.ClaimResponse; +import org.thingsboard.server.dao.device.claim.ClaimResult; +import org.thingsboard.server.dao.device.claim.ReclaimResult; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.AbstractTbEntityService; +import org.thingsboard.server.service.security.model.SecurityUser; + +import java.util.List; + +@AllArgsConstructor +@TbCoreComponent +@Service +@Slf4j +public class DefaultTbDeviceService extends AbstractTbEntityService implements TbDeviceService { + + @Override + public Device save(TenantId tenantId, Device device, Device oldDevice, String accessToken, SecurityUser user) throws ThingsboardException { + ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + try { + Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); + notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(), + savedDevice, oldDevice, actionType, user); + + return savedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), device, null, actionType, user, e); + throw handleException(e); + } + } + + @Override + public Device saveDeviceWithCredentials(TenantId tenantId, Device device, DeviceCredentials credentials, SecurityUser user) throws ThingsboardException { + ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + try { + Device savedDevice = checkNotNull(deviceService.saveDeviceWithCredentials(device, credentials)); + notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(), + savedDevice, device, actionType, user); + + return savedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), device, null, actionType, user, e); + throw handleException(e); + } + } + + @Override + public ListenableFuture deleteDevice(Device device, SecurityUser user) throws ThingsboardException { + TenantId tenantId = device.getTenantId(); + DeviceId deviceId = device.getId(); + try { + List relatedEdgeIds = findRelatedEdgeIds(tenantId, deviceId); + deviceService.deleteDevice(tenantId, deviceId); + notificationEntityService.notifyDeleteDevice(tenantId, deviceId, device.getCustomerId(), device, + relatedEdgeIds, user, deviceId.toString()); + + return removeAlarmsByEntityId(tenantId, deviceId); + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + ActionType.DELETED, user, e, deviceId.toString()); + throw handleException(e); + } + } + + @Override + public Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, Customer customer, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; + CustomerId customerId = customer.getId(); + try { + Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(user.getTenantId(), deviceId, customerId)); + notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice, + actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); + + return savedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + actionType, user, e, deviceId.toString(), customerId.toString()); + throw handleException(e); + } + } + + @Override + public Device unassignDeviceFromCustomer(Device device, Customer customer, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; + TenantId tenantId = device.getTenantId(); + DeviceId deviceId = device.getId(); + try { + Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(tenantId, deviceId)); + CustomerId customerId = customer.getId(); + + notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice, + actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, + true, customerId.toString(), customer.getName()); + + return savedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + actionType, user, e, deviceId.toString()); + throw handleException(e); + } + } + + @Override + public Device assignDeviceToPublicCustomer(TenantId tenantId, DeviceId deviceId, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; + try { + Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); + Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(tenantId, deviceId, publicCustomer.getId())); + + notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, savedDevice.getCustomerId(), savedDevice, + actionType, null, user, false, deviceId.toString(), + publicCustomer.getId().toString(), publicCustomer.getName()); + + return savedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + actionType, user, e, deviceId.toString()); + throw handleException(e); + } + } + + @Override + public DeviceCredentials getDeviceCredentialsByDeviceId(Device device, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.CREDENTIALS_READ; + TenantId tenantId = device.getTenantId(); + DeviceId deviceId = device.getId(); + try { + DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, deviceId)); + notificationEntityService.notifyEntity(tenantId, deviceId, device, device.getCustomerId(), + actionType, user, null, deviceId.toString()); + return deviceCredentials; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + actionType, user, e, deviceId.toString()); + throw handleException(e); + } + } + + @Override + public DeviceCredentials updateDeviceCredentials(Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException { + TenantId tenantId = device.getTenantId(); + DeviceId deviceId = device.getId(); + try { + DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials)); + notificationEntityService.notifyUpdateDeviceCredentials(tenantId, deviceId, device.getCustomerId(), device, result, user); + return result; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + ActionType.CREDENTIALS_UPDATED, user, e, deviceCredentials); + throw handleException(e); + } + } + + @Override + public ListenableFuture claimDevice(TenantId tenantId, Device device, CustomerId customerId, String secretKey, SecurityUser user) throws ThingsboardException { + try { + ListenableFuture future = claimDevicesService.claimDevice(device, customerId, secretKey); + + return Futures.transform(future, result -> { + if (result != null && result.getResponse().equals(ClaimResponse.SUCCESS)) { + notificationEntityService.notifyEntity(tenantId, device.getId(), result.getDevice(), customerId, + ActionType.ASSIGNED_TO_CUSTOMER, user, null, device.getId().toString(), customerId.toString(), + customerService.findCustomerById(tenantId, customerId).getName()); + } + return result; + }, MoreExecutors.directExecutor()); + } catch (Exception e) { + throw handleException(e); + } + } + + @Override + public ListenableFuture reclaimDevice(TenantId tenantId, Device device, SecurityUser user) throws ThingsboardException { + try { + ListenableFuture future = claimDevicesService.reClaimDevice(tenantId, device); + + return Futures.transform(future, result -> { + Customer unassignedCustomer = result.getUnassignedCustomer(); + if (unassignedCustomer != null) { + notificationEntityService.notifyEntity(tenantId, device.getId(), device, device.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, user, null, + device.getId().toString(), unassignedCustomer.getId().toString(), unassignedCustomer.getName()); + } + return result; + }, MoreExecutors.directExecutor()); + } catch (Exception e) { + throw handleException(e); + } + } + + @Override + public Device assignDeviceToTenant(Device device, Tenant newTenant, SecurityUser user) throws ThingsboardException { + TenantId tenantId = device.getTenantId(); + TenantId newTenantId = newTenant.getId(); + try { + Tenant tenant = tenantService.findTenantById(tenantId); + Device assignedDevice = deviceService.assignDeviceToTenant(newTenantId, device); + + notificationEntityService.notifyAssignDeviceToTenant(tenantId, newTenantId, device.getId(), + assignedDevice.getCustomerId(), assignedDevice, tenant, user, newTenantId.toString(), newTenant.getName()); + + return assignedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + ActionType.ASSIGNED_TO_TENANT, user, e, newTenantId.toString()); + throw handleException(e); + } + } + + @Override + public Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, Edge edge, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_EDGE; + EdgeId edgeId = edge.getId(); + try { + Device savedDevice = checkNotNull(deviceService.assignDeviceToEdge(tenantId, deviceId, edgeId)); + notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, savedDevice.getCustomerId(), + edgeId, savedDevice, actionType, EdgeEventActionType.ASSIGNED_TO_EDGE, user, deviceId.toString(), edgeId.toString(), edge.getName()); + return savedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + actionType, user, e, deviceId.toString(), edgeId.toString()); + throw handleException(e); + } + } + + @Override + public Device unassignDeviceFromEdge(Device device, Edge edge, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; + TenantId tenantId = device.getTenantId(); + DeviceId deviceId = device.getId(); + EdgeId edgeId = edge.getId(); + try { + Device savedDevice = checkNotNull(deviceService.unassignDeviceFromEdge(tenantId, deviceId, edgeId)); + + notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, device.getCustomerId(), + edgeId, device, actionType, EdgeEventActionType.UNASSIGNED_FROM_EDGE, user, deviceId.toString(), edgeId.toString(), edge.getName()); + return savedDevice; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, + actionType, user, e, deviceId.toString(), edgeId.toString()); + throw handleException(e); + } + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/device/TbDeviceService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/device/TbDeviceService.java new file mode 100644 index 0000000000..16fd0c7448 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/device/TbDeviceService.java @@ -0,0 +1,59 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.device; + +import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.dao.device.claim.ClaimResult; +import org.thingsboard.server.dao.device.claim.ReclaimResult; +import org.thingsboard.server.service.security.model.SecurityUser; + +public interface TbDeviceService { + + Device save(TenantId tenantId, Device device, Device oldDevice, String accessToken, SecurityUser user) throws ThingsboardException; + + Device saveDeviceWithCredentials(TenantId tenantId, Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException; + + ListenableFuture deleteDevice(Device device, SecurityUser user) throws ThingsboardException; + + Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, Customer customer, SecurityUser user) throws ThingsboardException; + + Device unassignDeviceFromCustomer(Device device, Customer customer, SecurityUser user) throws ThingsboardException; + + Device assignDeviceToPublicCustomer(TenantId tenantId, DeviceId deviceId, SecurityUser user) throws ThingsboardException; + + DeviceCredentials getDeviceCredentialsByDeviceId(Device device, SecurityUser user) throws ThingsboardException; + + DeviceCredentials updateDeviceCredentials(Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException; + + ListenableFuture claimDevice(TenantId tenantId, Device device, CustomerId customerId, String secretKey, SecurityUser user) throws ThingsboardException; + + ListenableFuture reclaimDevice(TenantId tenantId, Device device, SecurityUser user) throws ThingsboardException; + + Device assignDeviceToTenant(Device device, Tenant newTenant, SecurityUser user) throws ThingsboardException; + + Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, Edge edge, SecurityUser user) throws ThingsboardException; + + Device unassignDeviceFromEdge(Device device, Edge edge, SecurityUser user) throws ThingsboardException; +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java new file mode 100644 index 0000000000..93487ac5cd --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/DefaultTbEdgeService.java @@ -0,0 +1,150 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.edge; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.RuleChainId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.AbstractTbEntityService; +import org.thingsboard.server.service.security.model.SecurityUser; + +@AllArgsConstructor +@TbCoreComponent +@Service +@Slf4j +public class DefaultTbEdgeService extends AbstractTbEntityService implements TbEdgeService { + + @Override + public Edge saveEdge(Edge edge, RuleChain edgeTemplateRootRuleChain, SecurityUser user) throws ThingsboardException { + ActionType actionType = edge.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + TenantId tenantId = edge.getTenantId(); + try { + Edge savedEdge = checkNotNull(edgeService.saveEdge(edge)); + EdgeId edgeId = savedEdge.getId(); + + if (actionType == ActionType.ADDED) { + ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), edgeId); + edgeNotificationService.setEdgeRootRuleChain(tenantId, savedEdge, edgeTemplateRootRuleChain.getId()); + edgeService.assignDefaultRuleChainsToEdge(tenantId, edgeId); + } + + notificationEntityService.notifyEdge(tenantId, edgeId, savedEdge.getCustomerId(), savedEdge, actionType, user); + + return savedEdge; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), edge, null, actionType, user, e); + throw handleException(e); + } + } + + @Override + public void deleteEdge(Edge edge, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.DELETED; + EdgeId edgeId = edge.getId(); + TenantId tenantId = edge.getTenantId(); + try { + edgeService.deleteEdge(tenantId, edgeId); + notificationEntityService.notifyEdge(tenantId, edgeId, edge.getCustomerId(), edge, actionType, user, edgeId.toString()); + + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), edge, null, actionType, user, e); + throw handleException(e); + } + } + + @Override + public Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, Customer customer, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; + CustomerId customerId = customer.getId(); + try { + Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(tenantId, edgeId, customerId)); + + notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, + edgeId.toString(), customerId.toString(), customer.getName()); + + return savedEdge; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, + actionType, user, e, edgeId.toString(), customerId.toString()); + throw handleException(e); + } + } + + @Override + public Edge unassignEdgeFromCustomer(Edge edge, Customer customer, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; + TenantId tenantId = edge.getTenantId(); + EdgeId edgeId = edge.getId(); + CustomerId customerId = customer.getId(); + try { + Edge savedEdge = checkNotNull(edgeService.unassignEdgeFromCustomer(tenantId, edgeId)); + + notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, + edgeId.toString(), customerId.toString(), customer.getName()); + return savedEdge; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, + actionType, user, e, edgeId.toString()); + throw handleException(e); + } + } + + @Override + public Edge assignEdgeToPublicCustomer(TenantId tenantId, EdgeId edgeId, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; + try { + Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); + CustomerId customerId = publicCustomer.getId(); + Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(tenantId, edgeId, customerId)); + + notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, + edgeId.toString(), customerId.toString(), publicCustomer.getName()); + + return savedEdge; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, + actionType, user, e, edgeId.toString()); + throw handleException(e); + } + } + + @Override + public Edge setEdgeRootRuleChain(Edge edge, RuleChainId ruleChainId, SecurityUser user) throws ThingsboardException { + ActionType actionType = ActionType.UPDATED; + TenantId tenantId = edge.getTenantId(); + EdgeId edgeId = edge.getId(); + try { + Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(tenantId, edge, ruleChainId); + notificationEntityService.notifyEdge(tenantId, edgeId, null, updatedEdge, actionType, user); + return updatedEdge; + } catch (Exception e) { + notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, + actionType, user, e, edgeId.toString()); + throw handleException(e); + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/edge/TbEdgeService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/TbEdgeService.java new file mode 100644 index 0000000000..5ed27fbbb3 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/edge/TbEdgeService.java @@ -0,0 +1,39 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.edge; + +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.EdgeId; +import org.thingsboard.server.common.data.id.RuleChainId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.rule.RuleChain; +import org.thingsboard.server.service.security.model.SecurityUser; + +public interface TbEdgeService { + Edge saveEdge(Edge edge, RuleChain edgeTemplateRootRuleChain, SecurityUser user) throws ThingsboardException; + + void deleteEdge(Edge edge, SecurityUser user) throws ThingsboardException; + + Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, Customer customer, SecurityUser user) throws ThingsboardException; + + Edge unassignEdgeFromCustomer(Edge edge, Customer customer, SecurityUser user) throws ThingsboardException; + + Edge assignEdgeToPublicCustomer(TenantId tenantId, EdgeId edgeId, SecurityUser user) throws ThingsboardException; + + Edge setEdgeRootRuleChain(Edge edge, RuleChainId ruleChainId, SecurityUser user) throws ThingsboardException; +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/tenant/DefaultTbTenantService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/tenant/DefaultTbTenantService.java new file mode 100644 index 0000000000..ac3d651b6b --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/tenant/DefaultTbTenantService.java @@ -0,0 +1,66 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.tenant; + +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; +import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.entitiy.AbstractTbEntityService; +import org.thingsboard.server.service.install.InstallScripts; + +@Service +@TbCoreComponent +@AllArgsConstructor +public class DefaultTbTenantService extends AbstractTbEntityService implements TbTenantService { + + @Autowired + private InstallScripts installScripts; + + @Override + public Tenant save(Tenant tenant) throws ThingsboardException { + try { + boolean newTenant = tenant.getId() == null; + Tenant savedTenant = checkNotNull(tenantService.saveTenant(tenant)); + if (newTenant) { + installScripts.createDefaultRuleChains(savedTenant.getId()); + installScripts.createDefaultEdgeRuleChains(savedTenant.getId()); + } + tenantProfileCache.evict(savedTenant.getId()); + notificationEntityService.notifyCreateOruUpdateTenant(savedTenant, newTenant ? + ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); + return savedTenant; + } catch (Exception e) { + throw handleException(e); + } + } + + @Override + public void delete(Tenant tenant) throws ThingsboardException { + try { + TenantId tenantId = tenant.getId(); + tenantService.deleteTenant(tenantId); + tenantProfileCache.evict(tenantId); + notificationEntityService.notifyDeleteTenant(tenant); + } catch (Exception e) { + throw handleException(e); + } + } +} diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/tenant/TbTenantService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/tenant/TbTenantService.java new file mode 100644 index 0000000000..0ff7bc749c --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/tenant/TbTenantService.java @@ -0,0 +1,25 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.entitiy.tenant; + +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.exception.ThingsboardException; + +public interface TbTenantService { + Tenant save(Tenant tenant) throws ThingsboardException; + + void delete(Tenant tenant) throws ThingsboardException; +} diff --git a/application/src/main/java/org/thingsboard/server/service/importing/AbstractBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/importing/AbstractBulkImportService.java index b7b740f190..81a0068a4d 100644 --- a/application/src/main/java/org/thingsboard/server/service/importing/AbstractBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/importing/AbstractBulkImportService.java @@ -95,7 +95,7 @@ public abstract class AbstractBulkImportService processBulkImport(BulkImportRequest request, SecurityUser user, Consumer> onEntityImported) throws Exception { + public final BulkImportResult processBulkImport(BulkImportRequest request, SecurityUser user) throws Exception { List entitiesData = parseData(request); BulkImportResult result = new BulkImportResult<>(); @@ -106,10 +106,9 @@ public abstract class AbstractBulkImportService DonAsynchron.submit(() -> { SecurityContextHolder.setContext(securityContext); - ImportedEntityInfo importedEntityInfo = saveEntity(entityData.getFields(), user); + ImportedEntityInfo importedEntityInfo = saveEntity(entityData.getFields(), user); E entity = importedEntityInfo.getEntity(); - onEntityImported.accept(importedEntityInfo); saveKvs(user, entity, entityData.getKvs()); return importedEntityInfo; @@ -148,7 +147,7 @@ public abstract class AbstractBulkImportService fields); - protected abstract E saveEntity(E entity, Map fields); + protected abstract E saveEntity(SecurityUser user, E entity, Map fields); protected abstract EntityType getEntityType();