Forbid change of device profile type or transport type when used by devices.
This commit is contained in:
parent
06573211b3
commit
d8ae8282a0
@ -62,9 +62,11 @@ import org.thingsboard.server.common.data.BaseData;
|
|||||||
import org.thingsboard.server.common.data.Customer;
|
import org.thingsboard.server.common.data.Customer;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.DeviceProfileType;
|
import org.thingsboard.server.common.data.DeviceProfileType;
|
||||||
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
import org.thingsboard.server.common.data.Tenant;
|
||||||
import org.thingsboard.server.common.data.User;
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;
|
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;
|
||||||
|
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
|
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
|
||||||
import org.thingsboard.server.common.data.id.HasId;
|
import org.thingsboard.server.common.data.id.HasId;
|
||||||
import org.thingsboard.server.common.data.id.RuleChainId;
|
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||||
@ -315,10 +317,13 @@ public abstract class AbstractWebTest {
|
|||||||
DeviceProfile deviceProfile = new DeviceProfile();
|
DeviceProfile deviceProfile = new DeviceProfile();
|
||||||
deviceProfile.setName(name);
|
deviceProfile.setName(name);
|
||||||
deviceProfile.setType(DeviceProfileType.DEFAULT);
|
deviceProfile.setType(DeviceProfileType.DEFAULT);
|
||||||
|
deviceProfile.setTransportType(DeviceTransportType.DEFAULT);
|
||||||
deviceProfile.setDescription(name + " Test");
|
deviceProfile.setDescription(name + " Test");
|
||||||
DeviceProfileData deviceProfileData = new DeviceProfileData();
|
DeviceProfileData deviceProfileData = new DeviceProfileData();
|
||||||
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();
|
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();
|
||||||
|
DefaultDeviceProfileTransportConfiguration transportConfiguration = new DefaultDeviceProfileTransportConfiguration();
|
||||||
deviceProfileData.setConfiguration(configuration);
|
deviceProfileData.setConfiguration(configuration);
|
||||||
|
deviceProfileData.setTransportConfiguration(transportConfiguration);
|
||||||
deviceProfile.setProfileData(deviceProfileData);
|
deviceProfile.setProfileData(deviceProfileData);
|
||||||
deviceProfile.setDefault(false);
|
deviceProfile.setDefault(false);
|
||||||
deviceProfile.setDefaultRuleChainId(new RuleChainId(Uuids.timeBased()));
|
deviceProfile.setDefaultRuleChainId(new RuleChainId(Uuids.timeBased()));
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.Device;
|
|||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.DeviceProfileInfo;
|
import org.thingsboard.server.common.data.DeviceProfileInfo;
|
||||||
import org.thingsboard.server.common.data.DeviceProfileType;
|
import org.thingsboard.server.common.data.DeviceProfileType;
|
||||||
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
import org.thingsboard.server.common.data.Tenant;
|
||||||
import org.thingsboard.server.common.data.User;
|
import org.thingsboard.server.common.data.User;
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
@ -154,13 +155,32 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController
|
|||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
public void testSaveSameDeviceProfileWithDifferentType() throws Exception {
|
public void testChangeDeviceProfileTypeWithExistingDevices() throws Exception {
|
||||||
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
|
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
|
||||||
DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
|
DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
|
||||||
|
Device device = new Device();
|
||||||
|
device.setName("Test device");
|
||||||
|
device.setType("default");
|
||||||
|
device.setDeviceProfileId(savedDeviceProfile.getId());
|
||||||
|
doPost("/api/device", device, Device.class);
|
||||||
//TODO uncomment once we have other device types;
|
//TODO uncomment once we have other device types;
|
||||||
//savedDeviceProfile.setType(DeviceProfileType.LWM2M);
|
//savedDeviceProfile.setType(DeviceProfileType.LWM2M);
|
||||||
doPost("/api/deviceProfile", savedDeviceProfile).andExpect(status().isBadRequest())
|
doPost("/api/deviceProfile", savedDeviceProfile).andExpect(status().isBadRequest())
|
||||||
.andExpect(statusReason(containsString("Changing type of device profile is prohibited")));
|
.andExpect(statusReason(containsString("Can't change device profile type because devices referenced it")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeDeviceProfileTransportTypeWithExistingDevices() throws Exception {
|
||||||
|
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
|
||||||
|
DeviceProfile savedDeviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
|
||||||
|
Device device = new Device();
|
||||||
|
device.setName("Test device");
|
||||||
|
device.setType("default");
|
||||||
|
device.setDeviceProfileId(savedDeviceProfile.getId());
|
||||||
|
doPost("/api/device", device, Device.class);
|
||||||
|
savedDeviceProfile.setTransportType(DeviceTransportType.MQTT);
|
||||||
|
doPost("/api/deviceProfile", savedDeviceProfile).andExpect(status().isBadRequest())
|
||||||
|
.andExpect(statusReason(containsString("Can't change device profile transport type because devices referenced it")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -183,4 +183,5 @@ public interface DeviceDao extends Dao<Device> {
|
|||||||
*/
|
*/
|
||||||
ListenableFuture<Device> findDeviceByTenantIdAndIdAsync(TenantId tenantId, UUID id);
|
ListenableFuture<Device> findDeviceByTenantIdAndIdAsync(TenantId tenantId, UUID id);
|
||||||
|
|
||||||
|
Long countDevicesByDeviceProfileId(TenantId tenantId, UUID deviceProfileId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,9 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeviceProfileDao deviceProfileDao;
|
private DeviceProfileDao deviceProfileDao;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceDao deviceDao;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TenantDao tenantDao;
|
private TenantDao tenantDao;
|
||||||
|
|
||||||
@ -241,6 +244,12 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
|
|||||||
if (StringUtils.isEmpty(deviceProfile.getName())) {
|
if (StringUtils.isEmpty(deviceProfile.getName())) {
|
||||||
throw new DataValidationException("Device profile name should be specified!");
|
throw new DataValidationException("Device profile name should be specified!");
|
||||||
}
|
}
|
||||||
|
if (deviceProfile.getType() == null) {
|
||||||
|
throw new DataValidationException("Device profile type should be specified!");
|
||||||
|
}
|
||||||
|
if (deviceProfile.getTransportType() == null) {
|
||||||
|
throw new DataValidationException("Device profile transport type should be specified!");
|
||||||
|
}
|
||||||
if (deviceProfile.getTenantId() == null) {
|
if (deviceProfile.getTenantId() == null) {
|
||||||
throw new DataValidationException("Device profile should be assigned to tenant!");
|
throw new DataValidationException("Device profile should be assigned to tenant!");
|
||||||
} else {
|
} else {
|
||||||
@ -262,8 +271,20 @@ public class DeviceProfileServiceImpl extends AbstractEntityService implements D
|
|||||||
DeviceProfile old = deviceProfileDao.findById(deviceProfile.getTenantId(), deviceProfile.getId().getId());
|
DeviceProfile old = deviceProfileDao.findById(deviceProfile.getTenantId(), deviceProfile.getId().getId());
|
||||||
if (old == null) {
|
if (old == null) {
|
||||||
throw new DataValidationException("Can't update non existing device profile!");
|
throw new DataValidationException("Can't update non existing device profile!");
|
||||||
} else if (!old.getType().equals(deviceProfile.getType())) {
|
}
|
||||||
throw new DataValidationException("Changing type of device profile is prohibited!");
|
boolean profileTypeChanged = !old.getType().equals(deviceProfile.getType());
|
||||||
|
boolean transportTypeChanged = !old.getTransportType().equals(deviceProfile.getTransportType());
|
||||||
|
if (profileTypeChanged || transportTypeChanged) {
|
||||||
|
Long profileDeviceCount = deviceDao.countDevicesByDeviceProfileId(deviceProfile.getTenantId(), deviceProfile.getId().getId());
|
||||||
|
if (profileDeviceCount > 0) {
|
||||||
|
String message = null;
|
||||||
|
if (profileTypeChanged) {
|
||||||
|
message = "Can't change device profile type because devices referenced it!";
|
||||||
|
} else if (transportTypeChanged) {
|
||||||
|
message = "Can't change device profile transport type because devices referenced it!";
|
||||||
|
}
|
||||||
|
throw new DataValidationException(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -133,4 +133,6 @@ public interface DeviceRepository extends PagingAndSortingRepository<DeviceEntit
|
|||||||
|
|
||||||
DeviceEntity findByTenantIdAndId(UUID tenantId, UUID id);
|
DeviceEntity findByTenantIdAndId(UUID tenantId, UUID id);
|
||||||
|
|
||||||
|
Long countByDeviceProfileId(UUID deviceProfileId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -183,6 +183,11 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
|
|||||||
return service.submit(() -> DaoUtil.getData(deviceRepository.findByTenantIdAndId(tenantId.getId(), id)));
|
return service.submit(() -> DaoUtil.getData(deviceRepository.findByTenantIdAndId(tenantId.getId(), id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long countDevicesByDeviceProfileId(TenantId tenantId, UUID deviceProfileId) {
|
||||||
|
return deviceRepository.countByDeviceProfileId(deviceProfileId);
|
||||||
|
}
|
||||||
|
|
||||||
private List<EntitySubtype> convertTenantDeviceTypesToDto(UUID tenantId, List<String> types) {
|
private List<EntitySubtype> convertTenantDeviceTypesToDto(UUID tenantId, List<String> types) {
|
||||||
List<EntitySubtype> list = Collections.emptyList();
|
List<EntitySubtype> list = Collections.emptyList();
|
||||||
if (types != null && !types.isEmpty()) {
|
if (types != null && !types.isEmpty()) {
|
||||||
|
|||||||
@ -30,9 +30,11 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||||||
import org.thingsboard.server.common.data.BaseData;
|
import org.thingsboard.server.common.data.BaseData;
|
||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.DeviceProfileType;
|
import org.thingsboard.server.common.data.DeviceProfileType;
|
||||||
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
import org.thingsboard.server.common.data.EntityType;
|
||||||
import org.thingsboard.server.common.data.Event;
|
import org.thingsboard.server.common.data.Event;
|
||||||
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;
|
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileConfiguration;
|
||||||
|
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration;
|
||||||
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
|
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
|
||||||
import org.thingsboard.server.common.data.id.EntityId;
|
import org.thingsboard.server.common.data.id.EntityId;
|
||||||
import org.thingsboard.server.common.data.id.HasId;
|
import org.thingsboard.server.common.data.id.HasId;
|
||||||
@ -197,10 +199,13 @@ public abstract class AbstractServiceTest {
|
|||||||
deviceProfile.setTenantId(tenantId);
|
deviceProfile.setTenantId(tenantId);
|
||||||
deviceProfile.setName(name);
|
deviceProfile.setName(name);
|
||||||
deviceProfile.setType(DeviceProfileType.DEFAULT);
|
deviceProfile.setType(DeviceProfileType.DEFAULT);
|
||||||
|
deviceProfile.setTransportType(DeviceTransportType.DEFAULT);
|
||||||
deviceProfile.setDescription(name + " Test");
|
deviceProfile.setDescription(name + " Test");
|
||||||
DeviceProfileData deviceProfileData = new DeviceProfileData();
|
DeviceProfileData deviceProfileData = new DeviceProfileData();
|
||||||
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();
|
DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration();
|
||||||
|
DefaultDeviceProfileTransportConfiguration transportConfiguration = new DefaultDeviceProfileTransportConfiguration();
|
||||||
deviceProfileData.setConfiguration(configuration);
|
deviceProfileData.setConfiguration(configuration);
|
||||||
|
deviceProfileData.setTransportConfiguration(transportConfiguration);
|
||||||
deviceProfile.setProfileData(deviceProfileData);
|
deviceProfile.setProfileData(deviceProfileData);
|
||||||
deviceProfile.setDefault(false);
|
deviceProfile.setDefault(false);
|
||||||
deviceProfile.setDefaultRuleChainId(new RuleChainId(Uuids.timeBased()));
|
deviceProfile.setDefaultRuleChainId(new RuleChainId(Uuids.timeBased()));
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.Device;
|
|||||||
import org.thingsboard.server.common.data.DeviceProfile;
|
import org.thingsboard.server.common.data.DeviceProfile;
|
||||||
import org.thingsboard.server.common.data.DeviceProfileInfo;
|
import org.thingsboard.server.common.data.DeviceProfileInfo;
|
||||||
import org.thingsboard.server.common.data.DeviceProfileType;
|
import org.thingsboard.server.common.data.DeviceProfileType;
|
||||||
|
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||||
import org.thingsboard.server.common.data.Tenant;
|
import org.thingsboard.server.common.data.Tenant;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.page.PageData;
|
import org.thingsboard.server.common.data.page.PageData;
|
||||||
@ -148,14 +149,34 @@ public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
|
|||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
@Test(expected = DataValidationException.class)
|
@Test(expected = DataValidationException.class)
|
||||||
public void testSaveSameDeviceProfileWithDifferentType() {
|
public void testChangeDeviceProfileTypeWithExistingDevices() {
|
||||||
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
|
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
|
||||||
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
|
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
|
||||||
|
Device device = new Device();
|
||||||
|
device.setTenantId(tenantId);
|
||||||
|
device.setName("Test device");
|
||||||
|
device.setType("default");
|
||||||
|
device.setDeviceProfileId(savedDeviceProfile.getId());
|
||||||
|
deviceService.saveDevice(device);
|
||||||
//TODO: once we have more profile types, we should test that we can not change profile type in runtime and uncomment the @Ignore.
|
//TODO: once we have more profile types, we should test that we can not change profile type in runtime and uncomment the @Ignore.
|
||||||
// savedDeviceProfile.setType(DeviceProfileType.LWM2M);
|
// savedDeviceProfile.setType(DeviceProfileType.LWM2M);
|
||||||
deviceProfileService.saveDeviceProfile(savedDeviceProfile);
|
deviceProfileService.saveDeviceProfile(savedDeviceProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = DataValidationException.class)
|
||||||
|
public void testChangeDeviceProfileTransportTypeWithExistingDevices() {
|
||||||
|
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
|
||||||
|
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
|
||||||
|
Device device = new Device();
|
||||||
|
device.setTenantId(tenantId);
|
||||||
|
device.setName("Test device");
|
||||||
|
device.setType("default");
|
||||||
|
device.setDeviceProfileId(savedDeviceProfile.getId());
|
||||||
|
deviceService.saveDevice(device);
|
||||||
|
savedDeviceProfile.setTransportType(DeviceTransportType.MQTT);
|
||||||
|
deviceProfileService.saveDeviceProfile(savedDeviceProfile);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = DataValidationException.class)
|
@Test(expected = DataValidationException.class)
|
||||||
public void testDeleteDeviceProfileWithExistingDevice() {
|
public void testDeleteDeviceProfileWithExistingDevice() {
|
||||||
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
|
DeviceProfile deviceProfile = this.createDeviceProfile(tenantId,"Device Profile");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user