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 77bb1846f7..c6409ebbad 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -58,6 +58,7 @@ 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; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -503,6 +504,13 @@ public class DeviceController extends BaseController { 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)); @@ -538,14 +546,20 @@ public class DeviceController extends BaseController { accessControlService.checkPermission(user, Resource.DEVICE, Operation.CLAIM_DEVICES, device.getId(), device); - ListenableFuture> future = claimDevicesService.reClaimDevice(tenantId, device); - Futures.addCallback(future, new FutureCallback>() { + ListenableFuture result = claimDevicesService.reClaimDevice(tenantId, device); + Futures.addCallback(result, new FutureCallback<>() { @Override - public void onSuccess(@Nullable List result) { - if (result != null) { - deferredResult.setResult(new ResponseEntity(HttpStatus.OK)); - } else { - deferredResult.setResult(new ResponseEntity(HttpStatus.BAD_REQUEST)); + 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); + } } } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesService.java index 1a5b39f078..4a0315b43e 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesService.java @@ -21,8 +21,8 @@ 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.dao.device.claim.ClaimResult; +import org.thingsboard.server.dao.device.claim.ReclaimResult; -import java.util.List; import java.util.concurrent.ExecutionException; public interface ClaimDevicesService { @@ -31,6 +31,6 @@ public interface ClaimDevicesService { ListenableFuture claimDevice(Device device, CustomerId customerId, String secretKey) throws ExecutionException, InterruptedException; - ListenableFuture> reClaimDevice(TenantId tenantId, Device device); + ListenableFuture reClaimDevice(TenantId tenantId, Device device); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/claim/ReclaimResult.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/claim/ReclaimResult.java new file mode 100644 index 0000000000..5157afbd3e --- /dev/null +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/claim/ReclaimResult.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2021 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.device.claim; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.thingsboard.server.common.data.Customer; + +@Data +@AllArgsConstructor +public class ReclaimResult { + Customer unassignedCustomer; +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesServiceImpl.java index 4e9c805454..76b7f1de31 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/ClaimDevicesServiceImpl.java @@ -26,6 +26,7 @@ import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +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.id.CustomerId; @@ -35,9 +36,11 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.BooleanDataEntry; import org.thingsboard.server.dao.attributes.AttributesService; +import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.device.claim.ClaimData; 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.dao.model.ModelConstants; import java.io.IOException; @@ -62,6 +65,8 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { @Autowired private AttributesService attributesService; @Autowired + private CustomerService customerService; + @Autowired private CacheManager cacheManager; @Value("${security.claim.allowClaimingByDefault}") @@ -158,21 +163,22 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService { } @Override - public ListenableFuture> reClaimDevice(TenantId tenantId, Device device) { + public ListenableFuture reClaimDevice(TenantId tenantId, Device device) { if (!device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { cacheEviction(device.getId()); - + Customer unassignedCustomer = customerService.findCustomerById(tenantId, device.getCustomerId()); device.setCustomerId(null); deviceService.saveDevice(device); if (isAllowedClaimingByDefault) { - return Futures.immediateFuture(Collections.emptyList()); + return Futures.immediateFuture(new ReclaimResult(unassignedCustomer)); } - return attributesService.save(tenantId, device.getId(), DataConstants.SERVER_SCOPE, Collections.singletonList( - new BaseAttributeKvEntry(new BooleanDataEntry(CLAIM_ATTRIBUTE_NAME, true), - System.currentTimeMillis()))); + return Futures.transform(attributesService.save( + tenantId, device.getId(), DataConstants.SERVER_SCOPE, Collections.singletonList( + new BaseAttributeKvEntry(new BooleanDataEntry(CLAIM_ATTRIBUTE_NAME, true), System.currentTimeMillis()) + )), result -> new ReclaimResult(unassignedCustomer), MoreExecutors.directExecutor()); } cacheEviction(device.getId()); - return Futures.immediateFuture(Collections.emptyList()); + return Futures.immediateFuture(new ReclaimResult(null)); } private List constructCacheKey(DeviceId deviceId) {