Claiming devices using claimData attribute (#2105)
* Claiming devices using claimData attribute * Fixed license header
This commit is contained in:
parent
25e36583f8
commit
2b7df84ae9
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright © 2016-2019 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;
|
||||
|
||||
import lombok.Data;
|
||||
import org.thingsboard.server.dao.device.claim.ClaimData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ClaimDataInfo {
|
||||
|
||||
private final boolean fromCache;
|
||||
private final List<Object> key;
|
||||
private final ClaimData data;
|
||||
|
||||
}
|
||||
@ -23,12 +23,13 @@ import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.device.claim.ClaimResult;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public interface ClaimDevicesService {
|
||||
|
||||
ListenableFuture<Void> registerClaimingInfo(TenantId tenantId, DeviceId deviceId, String secretKey, long durationMs);
|
||||
|
||||
ListenableFuture<ClaimResult> claimDevice(Device device, CustomerId customerId, String secretKey);
|
||||
ListenableFuture<ClaimResult> claimDevice(Device device, CustomerId customerId, String secretKey) throws ExecutionException, InterruptedException;
|
||||
|
||||
ListenableFuture<List<Void>> reClaimDevice(TenantId tenantId, Device device);
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.dao.device;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -23,6 +24,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
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.DataConstants;
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
@ -37,9 +39,12 @@ import org.thingsboard.server.dao.device.claim.ClaimResponse;
|
||||
import org.thingsboard.server.dao.device.claim.ClaimResult;
|
||||
import org.thingsboard.server.dao.model.ModelConstants;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static org.thingsboard.server.common.data.CacheConstants.CLAIM_DEVICES_CACHE;
|
||||
|
||||
@ -48,6 +53,8 @@ import static org.thingsboard.server.common.data.CacheConstants.CLAIM_DEVICES_CA
|
||||
public class ClaimDevicesServiceImpl implements ClaimDevicesService {
|
||||
|
||||
private static final String CLAIM_ATTRIBUTE_NAME = "claimingAllowed";
|
||||
private static final String CLAIM_DATA_ATTRIBUTE_NAME = "claimingData";
|
||||
private static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@Autowired
|
||||
private DeviceService deviceService;
|
||||
@ -95,24 +102,45 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<ClaimResult> claimDevice(Device device, CustomerId customerId, String secretKey) {
|
||||
private ClaimDataInfo getClaimData(Cache cache, Device device) throws ExecutionException, InterruptedException {
|
||||
List<Object> key = constructCacheKey(device.getId());
|
||||
ClaimData claimDataFromCache = cache.get(key, ClaimData.class);
|
||||
if (claimDataFromCache != null) {
|
||||
return new ClaimDataInfo(true, key, claimDataFromCache);
|
||||
} else {
|
||||
Optional<AttributeKvEntry> claimDataAttr = attributesService.find(device.getTenantId(), device.getId(),
|
||||
DataConstants.SERVER_SCOPE, CLAIM_DATA_ATTRIBUTE_NAME).get();
|
||||
if (claimDataAttr.isPresent()) {
|
||||
try {
|
||||
ClaimData claimDataFromAttribute = mapper.readValue(claimDataAttr.get().getValueAsString(), ClaimData.class);
|
||||
return new ClaimDataInfo(false, key, claimDataFromAttribute);
|
||||
} catch (IOException e) {
|
||||
log.warn("Failed to read Claim Data [{}] from attribute!", claimDataAttr, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<ClaimResult> claimDevice(Device device, CustomerId customerId, String secretKey) throws ExecutionException, InterruptedException {
|
||||
Cache cache = cacheManager.getCache(CLAIM_DEVICES_CACHE);
|
||||
ClaimData claimData = cache.get(key, ClaimData.class);
|
||||
ClaimDataInfo claimData = getClaimData(cache, device);
|
||||
if (claimData != null) {
|
||||
long currTs = System.currentTimeMillis();
|
||||
if (currTs > claimData.getExpirationTime() || !secretKey.equals(claimData.getSecretKey())) {
|
||||
if (currTs > claimData.getData().getExpirationTime() || !secretKeyIsEmptyOrEqual(secretKey, claimData.getData().getSecretKey())) {
|
||||
log.warn("The claiming timeout occurred or wrong 'secretKey' provided for the device [{}]", device.getName());
|
||||
cache.evict(key);
|
||||
if (claimData.isFromCache()) {
|
||||
cache.evict(claimData.getKey());
|
||||
}
|
||||
return Futures.immediateFuture(new ClaimResult(null, ClaimResponse.FAILURE));
|
||||
} else {
|
||||
if (device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
|
||||
device.setCustomerId(customerId);
|
||||
Device savedDevice = deviceService.saveDevice(device);
|
||||
return Futures.transform(removeClaimingSavedData(cache, key, device), result -> new ClaimResult(savedDevice, ClaimResponse.SUCCESS));
|
||||
return Futures.transform(removeClaimingSavedData(cache, claimData, device), result -> new ClaimResult(savedDevice, ClaimResponse.SUCCESS));
|
||||
}
|
||||
return Futures.transform(removeClaimingSavedData(cache, key, device), result -> new ClaimResult(null, ClaimResponse.CLAIMED));
|
||||
return Futures.transform(removeClaimingSavedData(cache, claimData, device), result -> new ClaimResult(null, ClaimResponse.CLAIMED));
|
||||
}
|
||||
} else {
|
||||
log.warn("Failed to find the device's claiming message![{}]", device.getName());
|
||||
@ -124,6 +152,10 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean secretKeyIsEmptyOrEqual(String secretKeyA, String secretKeyB) {
|
||||
return (StringUtils.isEmpty(secretKeyA) && StringUtils.isEmpty(secretKeyB)) || secretKeyA.equals(secretKeyB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<List<Void>> reClaimDevice(TenantId tenantId, Device device) {
|
||||
if (!device.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) {
|
||||
@ -159,13 +191,12 @@ public class ClaimDevicesServiceImpl implements ClaimDevicesService {
|
||||
return systemDurationMs;
|
||||
}
|
||||
|
||||
private ListenableFuture<List<Void>> removeClaimingSavedData(Cache cache, List<Object> key, Device device) {
|
||||
cache.evict(key);
|
||||
if (isAllowedClaimingByDefault) {
|
||||
return Futures.immediateFuture(null);
|
||||
private ListenableFuture<List<Void>> removeClaimingSavedData(Cache cache, ClaimDataInfo data, Device device) {
|
||||
if (data.isFromCache()) {
|
||||
cache.evict(data.getKey());
|
||||
}
|
||||
return attributesService.removeAll(device.getTenantId(),
|
||||
device.getId(), DataConstants.SERVER_SCOPE, Collections.singletonList(CLAIM_ATTRIBUTE_NAME));
|
||||
device.getId(), DataConstants.SERVER_SCOPE, Arrays.asList(CLAIM_ATTRIBUTE_NAME, CLAIM_DATA_ATTRIBUTE_NAME));
|
||||
}
|
||||
|
||||
private void cacheEviction(DeviceId deviceId) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user