Browse Source

added resource dao support (#4213)

* Version set to 3.3.0-SNAPSHOT

* added resource dao

* added resource support in transport lvl (get resources and "update", "delete" notifications)

* refactoring

* added resource table to hsql schema

* added check for models dir in InstallScripts

* added pageLink support to getResources
pull/4232/head
Yevhen Bondarenko 5 years ago
committed by GitHub
parent
commit
e2dd5b96ae
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 90
      application/src/main/java/org/thingsboard/server/controller/ResourceController.java
  2. 7
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  3. 5
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  4. 48
      application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
  5. 19
      application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
  6. 2
      application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java
  7. 1
      application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java
  8. 29
      application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java
  9. 5
      application/src/main/java/org/thingsboard/server/service/queue/TbClusterService.java
  10. 57
      application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
  11. 35
      common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java
  12. 37
      common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/Resource.java
  13. 20
      common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java
  14. 2
      common/queue/src/main/java/org/thingsboard/server/queue/util/TbLwM2mTransportComponent.java
  15. 37
      common/queue/src/main/proto/queue.proto
  16. 4
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java
  17. 17
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java
  18. 9
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  19. 45
      dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceCompositeKey.java
  20. 77
      dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceEntity.java
  21. 96
      dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java
  22. 35
      dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java
  23. 77
      dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java
  24. 31
      dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java
  25. 5
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
  26. 8
      dao/src/main/resources/sql/schema-entities-hsql.sql
  27. 8
      dao/src/main/resources/sql/schema-entities.sql
  28. 1
      dao/src/test/resources/sql/hsql/drop-all-tables.sql
  29. 3
      dao/src/test/resources/sql/psql/drop-all-tables.sql

90
application/src/main/java/org/thingsboard/server/controller/ResourceController.java

@ -0,0 +1,90 @@
/**
* 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.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
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.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.queue.util.TbCoreComponent;
@Slf4j
@RestController
@TbCoreComponent
@RequestMapping("/api")
public class ResourceController extends BaseController {
private final ResourceService resourceService;
public ResourceController(ResourceService resourceService) {
this.resourceService = resourceService;
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@RequestMapping(value = "/resource", method = RequestMethod.POST)
@ResponseBody
public Resource saveResource(Resource resource) throws ThingsboardException {
try {
resource.setTenantId(getTenantId());
Resource savedResource = checkNotNull(resourceService.saveResource(resource));
tbClusterService.onResourceChange(savedResource, null);
return savedResource;
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@RequestMapping(value = "/resource", method = RequestMethod.GET)
@ResponseBody
public PageData<Resource> getResources(@RequestParam(required = false) boolean system,
@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
PageLink pageLink = createPageLink(pageSize, page, null, sortProperty, sortOrder);
return checkNotNull(resourceService.findResourcesByTenantId(system ? TenantId.SYS_TENANT_ID : getTenantId(), pageLink));
} catch (Exception e) {
throw handleException(e);
}
}
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@RequestMapping(value = "/resource/{resourceType}/{resourceId}", method = RequestMethod.DELETE)
@ResponseBody
public void deleteResource(@PathVariable("resourceType") ResourceType resourceType,
@PathVariable("resourceId") String resourceId) throws ThingsboardException {
try {
Resource resource = checkNotNull(resourceService.getResource(getTenantId(), resourceType, resourceId));
resourceService.deleteResource(getTenantId(), resourceType, resourceId);
tbClusterService.onResourceDeleted(resource, null);
} catch (Exception e) {
throw handleException(e);
}
}
}

7
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -194,6 +194,12 @@ public class ThingsboardInstallService {
log.info("Updating system data...");
systemDataLoaderService.updateSystemWidgets();
break;
case "3.2.2":
log.info("Upgrading ThingsBoard from version 3.2.2 to 3.3.0 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.2.2");
log.info("Updating system data...");
break;
default:
throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion);
@ -226,6 +232,7 @@ public class ThingsboardInstallService {
systemDataLoaderService.createAdminSettings();
systemDataLoaderService.loadSystemWidgets();
systemDataLoaderService.createOAuth2Templates();
systemDataLoaderService.loadSystemLwm2mResources();
// systemDataLoaderService.loadSystemPlugins();
// systemDataLoaderService.loadSystemRules();

5
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -445,6 +445,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
installScripts.loadSystemWidgets();
}
@Override
public void loadSystemLwm2mResources() throws Exception {
installScripts.loadSystemLwm2mResources();
}
private User createUser(Authority authority,
TenantId tenantId,
CustomerId customerId,

48
application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java

@ -24,15 +24,17 @@ import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.widget.WidgetTypeService;
import org.thingsboard.server.dao.widget.WidgetsBundleService;
@ -42,6 +44,7 @@ import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Optional;
import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper;
@ -66,8 +69,11 @@ public class InstallScripts {
public static final String WIDGET_BUNDLES_DIR = "widget_bundles";
public static final String OAUTH2_CONFIG_TEMPLATES_DIR = "oauth2_config_templates";
public static final String DASHBOARDS_DIR = "dashboards";
public static final String MODELS_DIR = "models";
public static final String CREDENTIALS_DIR = "credentials";
public static final String JSON_EXT = ".json";
public static final String XML_EXT = ".xml";
@Value("${install.data_dir:}")
private String dataDir;
@ -87,6 +93,9 @@ public class InstallScripts {
@Autowired
private OAuth2ConfigTemplateService oAuth2TemplateService;
@Autowired
private ResourceService resourceService;
public Path getTenantRuleChainsDir() {
return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR);
}
@ -186,6 +195,42 @@ public class InstallScripts {
}
}
public void loadSystemLwm2mResources() throws Exception {
Path modelsDir = Paths.get(getDataDir(), MODELS_DIR);
if (Files.isDirectory(modelsDir)) {
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(modelsDir, path -> path.toString().endsWith(XML_EXT))) {
dirStream.forEach(
path -> {
try {
Resource resource = new Resource();
resource.setTenantId(TenantId.SYS_TENANT_ID);
resource.setResourceType(ResourceType.LWM2M_MODEL);
resource.setResourceId(path.getFileName().toString());
resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(path)));
resourceService.saveResource(resource);
} catch (Exception e) {
log.error("Unable to load lwm2m model [{}]", path.toString());
throw new RuntimeException("Unable to load lwm2m model", e);
}
}
);
}
}
Path jksPath = Paths.get(getDataDir(), CREDENTIALS_DIR, "serverKeyStore.jks");
try {
Resource resource = new Resource();
resource.setTenantId(TenantId.SYS_TENANT_ID);
resource.setResourceType(ResourceType.JKS);
resource.setResourceId(jksPath.getFileName().toString());
resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath)));
resourceService.saveResource(resource);
} catch (Exception e) {
log.error("Unable to load lwm2m serverKeyStore [{}]", jksPath.toString());
throw new RuntimeException("Unable to load l2m2m serverKeyStore", e);
}
}
public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception {
Path dashboardsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR);
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) {
@ -208,7 +253,6 @@ public class InstallScripts {
}
}
public void loadDemoRuleChains(TenantId tenantId) throws Exception {
try {
createDefaultRuleChains(tenantId);

19
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java

@ -434,6 +434,25 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.info("Schema updated.");
}
break;
case "3.2.2":
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
log.info("Updating schema ...");
try {
conn.createStatement().execute("CREATE TABLE IF NOT EXISTS resource (" +
" tenant_id uuid NOT NULL," +
" resource_type varchar(32) NOT NULL," +
" resource_id varchar(255) NOT NULL," +
" resource_value varchar," +
" CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)" +
" );");
conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3003000;");
} catch (Exception e) {
log.error("Failed updating schema!!!", e);
}
log.info("Schema updated.");
}
break;
default:
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
}

2
application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java

@ -33,4 +33,6 @@ public interface SystemDataLoaderService {
void deleteSystemWidgetBundle(String bundleAlias) throws Exception;
void loadSystemLwm2mResources() throws Exception;
}

1
application/src/main/java/org/thingsboard/server/service/lwm2m/LwM2MModelsRepository.java

@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap;
import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode;
import java.math.BigInteger;

29
application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java

@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.transport.resource.Resource;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
import org.thingsboard.server.common.msg.queue.ServiceType;
@ -247,6 +248,34 @@ public class DefaultTbClusterService implements TbClusterService {
onEntityDelete(entity.getTenantId(), entity.getId(), entity.getName(), callback);
}
@Override
public void onResourceChange(Resource resource, TbQueueCallback callback) {
TenantId tenantId = resource.getTenantId();
log.trace("[{}][{}][{}] Processing change resource", tenantId, resource.getResourceType(), resource.getResourceId());
TransportProtos.ResourceUpdateMsg resourceUpdateMsg = TransportProtos.ResourceUpdateMsg.newBuilder()
.setTenantIdMSB(tenantId.getId().getMostSignificantBits())
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setResourceType(resource.getResourceType().name())
.setResourceId(resource.getResourceId())
.build();
ToTransportMsg transportMsg = ToTransportMsg.newBuilder().setResourceUpdateMsg(resourceUpdateMsg).build();
broadcast(transportMsg, callback);
}
@Override
public void onResourceDeleted(Resource resource, TbQueueCallback callback) {
TenantId tenantId = resource.getTenantId();
log.trace("[{}][{}][{}] Processing delete resource", tenantId, resource.getResourceType(), resource.getResourceId());
TransportProtos.ResourceDeleteMsg resourceUpdateMsg = TransportProtos.ResourceDeleteMsg.newBuilder()
.setTenantIdMSB(tenantId.getId().getMostSignificantBits())
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setResourceType(resource.getResourceType().name())
.setResourceId(resource.getResourceId())
.build();
ToTransportMsg transportMsg = ToTransportMsg.newBuilder().setResourceDeleteMsg(resourceUpdateMsg).build();
broadcast(transportMsg, callback);
}
public <T> void onEntityChange(TenantId tenantId, EntityId entityid, T entity, TbQueueCallback callback) {
String entityName = (entity instanceof HasName) ? ((HasName) entity).getName() : entity.getClass().getName();
log.trace("[{}][{}][{}] Processing [{}] change event", tenantId, entityid.getEntityType(), entityid.getId(), entityName);

5
application/src/main/java/org/thingsboard/server/service/queue/TbClusterService.java

@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.TenantProfile;
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.transport.resource.Resource;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
import org.thingsboard.server.gen.transport.TransportProtos;
@ -71,4 +72,8 @@ public interface TbClusterService {
void onDeviceChange(Device device, TbQueueCallback callback);
void onDeviceDeleted(Device device, TbQueueCallback callback);
void onResourceChange(Resource resource, TbQueueCallback callback);
void onResourceDeleted(Resource resource, TbQueueCallback callback);
}

57
application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java

@ -25,6 +25,7 @@ import com.google.protobuf.ByteString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.ApiUsageState;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
@ -38,9 +39,12 @@ import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
import org.thingsboard.server.common.data.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
import org.thingsboard.server.common.msg.EncryptionUtil;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
@ -53,14 +57,15 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException;
import org.thingsboard.server.dao.device.provision.ProvisionRequest;
import org.thingsboard.server.dao.device.provision.ProvisionResponse;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionResponseStatus;
import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg;
@ -77,11 +82,14 @@ import org.thingsboard.server.service.profile.TbDeviceProfileCache;
import org.thingsboard.server.service.queue.TbClusterService;
import org.thingsboard.server.service.state.DeviceStateService;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
* Created by ashvayka on 05.10.18.
@ -104,6 +112,7 @@ public class DefaultTransportApiService implements TransportApiService {
private final TbClusterService tbClusterService;
private final DataDecodingEncodingService dataDecodingEncodingService;
private final DeviceProvisionService deviceProvisionService;
private final ResourceService resourceService;
private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>();
@ -112,7 +121,7 @@ public class DefaultTransportApiService implements TransportApiService {
RelationService relationService, DeviceCredentialsService deviceCredentialsService,
DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService,
TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService,
DeviceProvisionService deviceProvisionService) {
DeviceProvisionService deviceProvisionService, ResourceService resourceService) {
this.deviceProfileCache = deviceProfileCache;
this.tenantProfileCache = tenantProfileCache;
this.apiUsageStateService = apiUsageStateService;
@ -124,6 +133,7 @@ public class DefaultTransportApiService implements TransportApiService {
this.tbClusterService = tbClusterService;
this.dataDecodingEncodingService = dataDecodingEncodingService;
this.deviceProvisionService = deviceProvisionService;
this.resourceService = resourceService;
}
@Override
@ -157,6 +167,9 @@ public class DefaultTransportApiService implements TransportApiService {
} else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) {
return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()),
value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor());
} else if (transportApiRequestMsg.hasResourcesRequestMsg()) {
return Futures.transform(handle(transportApiRequestMsg.getResourcesRequestMsg()),
value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor());
}
return Futures.transform(getEmptyTransportApiResponseFuture(),
value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor());
@ -315,9 +328,9 @@ public class DefaultTransportApiService implements TransportApiService {
return TransportApiResponseMsg.newBuilder().setProvisionDeviceResponseMsg(TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build()).build();
}
TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse = TransportProtos.ProvisionDeviceResponseMsg.newBuilder()
.setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name()))
.setStatus(status);
switch (deviceCredentials.getCredentialsType()){
.setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name()))
.setStatus(status);
switch (deviceCredentials.getCredentialsType()) {
case ACCESS_TOKEN:
provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId());
break;
@ -353,6 +366,40 @@ public class DefaultTransportApiService implements TransportApiService {
return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build());
}
private ListenableFuture<TransportApiResponseMsg> handle(GetResourcesRequestMsg requestMsg) {
TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));
TransportProtos.GetResourcesResponseMsg.Builder builder = TransportProtos.GetResourcesResponseMsg.newBuilder();
String resourceType = requestMsg.getResourceType();
String resourceId = requestMsg.getResourceId();
List<TransportProtos.ResourceMsg> resources;
if (resourceType != null && resourceId != null) {
resources = Collections.singletonList(toProto(
resourceService.getResource(tenantId, ResourceType.valueOf(resourceType), resourceId)));
} else {
//TODO: add page link params to request proto if need or remove this
resources = resourceService.findResourcesByTenantId(tenantId, new PageLink(100))
.getData()
.stream()
.map(this::toProto)
.collect(Collectors.toList());
}
builder.addAllResources(resources);
return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setResourcesResponseMsg(builder).build());
}
private TransportProtos.ResourceMsg toProto(Resource resource) {
return TransportProtos.ResourceMsg.newBuilder()
.setTenantIdMSB(resource.getTenantId().getId().getMostSignificantBits())
.setTenantIdLSB(resource.getTenantId().getId().getLeastSignificantBits())
.setResourceType(resource.getResourceType().name())
.setResourceId(resource.getResourceId())
.setValue(resource.getValue())
.build();
}
private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) {
return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, deviceId), device -> {
if (device == null) {

35
common/dao-api/src/main/java/org/thingsboard/server/dao/resource/ResourceService.java

@ -0,0 +1,35 @@
/**
* 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.resource;
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.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
public interface ResourceService {
Resource saveResource(Resource resource);
Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId);
PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink);
void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId);
void deleteResourcesByTenantId(TenantId tenantId);
}

37
common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/Resource.java

@ -0,0 +1,37 @@
/**
* 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.common.data.transport.resource;
import lombok.Data;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.TenantId;
@Data
public class Resource implements HasTenantId {
private TenantId tenantId;
private ResourceType resourceType;
private String resourceId;
private String value;
@Override
public String toString() {
return "Resource{" +
"tenantId=" + tenantId +
", resourceType=" + resourceType +
", resourceId='" + resourceId + '\'' +
'}';
}
}

20
common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java

@ -0,0 +1,20 @@
/**
* 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.common.data.transport.resource;
public enum ResourceType {
LWM2M_MODEL, JKS, PKCS_12
}

2
common/queue/src/main/java/org/thingsboard/server/queue/util/TbLwM2mTransportComponent.java

@ -21,6 +21,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')")
public @interface TbLwM2mTransportComponent {
}

37
common/queue/src/main/proto/queue.proto

@ -201,6 +201,25 @@ message LwM2MResponseMsg {
LwM2MRegistrationResponseMsg registrationMsg = 1;
}
message ResourceMsg {
int64 tenantIdMSB = 1;
int64 tenantIdLSB = 2;
string resourceType = 3;
string resourceId = 4;
string value = 5;
}
message GetResourcesRequestMsg {
int64 tenantIdMSB = 1;
int64 tenantIdLSB = 2;
string resourceType = 3;
string resourceId = 4;
}
message GetResourcesResponseMsg {
repeated ResourceMsg resources = 1;
}
message ValidateDeviceLwM2MCredentialsRequestMsg {
string credentialsId = 1;
}
@ -242,6 +261,20 @@ message EntityDeleteMsg {
int64 entityIdLSB = 3;
}
message ResourceUpdateMsg {
int64 tenantIdMSB = 1;
int64 tenantIdLSB = 2;
string resourceType = 3;
string resourceId = 4;
}
message ResourceDeleteMsg {
int64 tenantIdMSB = 1;
int64 tenantIdLSB = 2;
string resourceType = 3;
string resourceId = 4;
}
message SessionCloseNotificationProto {
string message = 1;
}
@ -525,6 +558,7 @@ message TransportApiRequestMsg {
ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6;
ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7;
ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8;
GetResourcesRequestMsg resourcesRequestMsg = 9;
}
/* Response from ThingsBoard Core Service to Transport Service */
@ -534,6 +568,7 @@ message TransportApiResponseMsg {
GetEntityProfileResponseMsg entityProfileResponseMsg = 3;
ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4;
LwM2MResponseMsg lwM2MResponseMsg = 6;
GetResourcesResponseMsg resourcesResponseMsg = 7;
}
/* Messages that are handled by ThingsBoard Core Service */
@ -578,6 +613,8 @@ message ToTransportMsg {
EntityDeleteMsg entityDeleteMsg = 9;
ProvisionDeviceResponseMsg provisionResponse = 10;
ToTransportUpdateCredentialsProto toTransportUpdateCredentialsNotification = 11;
ResourceUpdateMsg resourceUpdateMsg = 12;
ResourceDeleteMsg resourceDeleteMsg = 13;
}
message UsageStatsKVProto{

4
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportService.java

@ -25,6 +25,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestM
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
@ -51,6 +53,8 @@ public interface TransportService {
GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg);
GetResourcesResponseMsg getResources(GetResourcesRequestMsg msg);
void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg,
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);

17
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java

@ -254,6 +254,18 @@ public class DefaultTransportService implements TransportService {
}
}
@Override
public TransportProtos.GetResourcesResponseMsg getResources(TransportProtos.GetResourcesRequestMsg msg) {
TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =
new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setResourcesRequestMsg(msg).build());
try {
TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get();
return response.getValue().getResourcesResponseMsg();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg,
TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
@ -688,6 +700,10 @@ public class DefaultTransportService implements TransportService {
} else if (EntityType.DEVICE.equals(entityType)) {
rateLimitService.remove(new DeviceId(entityUuid));
}
} else if (toSessionMsg.hasResourceUpdateMsg()) {
//TODO: update resource cache
} else if (toSessionMsg.hasResourceDeleteMsg()) {
//TODO: remove resource from cache
} else {
//TODO: should we notify the device actor about missed session?
log.debug("[{}] Missing session.", sessionId);
@ -695,6 +711,7 @@ public class DefaultTransportService implements TransportService {
}
}
public void onProfileUpdate(DeviceProfile deviceProfile) {
long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits();
long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits();

9
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -453,6 +453,15 @@ public class ModelConstants {
public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec";
public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec";
/**
* Resource constants.
*/
public static final String RESOURCE_TABLE_NAME = "resource";
public static final String RESOURCE_TENANT_ID_COLUMN = TENANT_ID_COLUMN;
public static final String RESOURCE_TYPE_COLUMN = "resource_type";
public static final String RESOURCE_ID_COLUMN = "resource_id";
public static final String RESOURCE_VALUE_COLUMN = "resource_value";
/**
* Cassandra attributes and timeseries constants.
*/

45
dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceCompositeKey.java

@ -0,0 +1,45 @@
/**
* 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.model.sql;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.transport.resource.Resource;
import javax.persistence.Transient;
import java.io.Serializable;
import java.util.UUID;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ResourceCompositeKey implements Serializable {
@Transient
private static final long serialVersionUID = -3789469030818742769L;
private UUID tenantId;
private String resourceType;
private String resourceId;
public ResourceCompositeKey(Resource resource) {
this.tenantId = resource.getTenantId().getId();
this.resourceType = resource.getResourceType().name();
this.resourceId = resource.getResourceId();
}
}

77
dao/src/main/java/org/thingsboard/server/dao/model/sql/ResourceEntity.java

@ -0,0 +1,77 @@
/**
* 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.model.sql;
import lombok.Data;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
import org.thingsboard.server.dao.model.ToData;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TABLE_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TENANT_ID_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TYPE_COLUMN;
import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_VALUE_COLUMN;
@Data
@Entity
@Table(name = RESOURCE_TABLE_NAME)
@IdClass(ResourceCompositeKey.class)
public class ResourceEntity implements ToData<Resource> {
@Id
@Column(name = RESOURCE_TENANT_ID_COLUMN, columnDefinition = "uuid")
private UUID tenantId;
@Id
@Column(name = RESOURCE_TYPE_COLUMN)
private String resourceType;
@Id
@Column(name = RESOURCE_ID_COLUMN)
private String resourceId;
@Column(name = RESOURCE_VALUE_COLUMN)
private String value;
public ResourceEntity() {
}
public ResourceEntity(Resource resource) {
this.tenantId = resource.getTenantId().getId();
this.resourceType = resource.getResourceType().name();
this.resourceId = resource.getResourceId();
this.value = resource.getValue();
}
@Override
public Resource toData() {
Resource resource = new Resource();
resource.setTenantId(new TenantId(tenantId));
resource.setResourceType(ResourceType.valueOf(resourceType));
resource.setResourceId(resourceId);
resource.setValue(value);
return resource;
}
}

96
dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java

@ -0,0 +1,96 @@
/**
* 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.resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
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.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
import org.thingsboard.server.dao.exception.DataValidationException;
import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Service
@Slf4j
public class BaseResourceService implements ResourceService {
private final ResourceDao resourceDao;
public BaseResourceService(ResourceDao resourceDao) {
this.resourceDao = resourceDao;
}
@Override
public Resource saveResource(Resource resource) {
log.trace("Executing saveResource [{}]", resource);
validate(resource);
return resourceDao.saveResource(resource);
}
@Override
public Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId) {
log.trace("Executing getResource [{}] [{}] [{}]", tenantId, resourceType, resourceId);
validate(tenantId, resourceType, resourceId);
return resourceDao.getResource(tenantId, resourceType, resourceId);
}
@Override
public void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) {
log.trace("Executing deleteResource [{}] [{}] [{}]", tenantId, resourceType, resourceId);
validate(tenantId, resourceType, resourceId);
resourceDao.deleteResource(tenantId, resourceType, resourceId);
}
@Override
public PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findByTenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
return resourceDao.findAllByTenantId(tenantId, pageLink);
}
@Override
public void deleteResourcesByTenantId(TenantId tenantId) {
log.trace("Executing deleteDevicesByTenantId, tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
resourceDao.removeAllByTenantId(tenantId);
}
protected void validate(Resource resource) {
if (resource == null) {
throw new DataValidationException("Resource should be specified!");
}
if (resource.getValue() == null) {
throw new DataValidationException("Resource value should be specified!");
}
validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceId());
}
protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) {
if (resourceType == null) {
throw new DataValidationException("Resource type should be specified!");
}
if (resourceId == null) {
throw new DataValidationException("Resource id should be specified!");
}
validateId(tenantId, "Incorrect tenantId ");
}
}

35
dao/src/main/java/org/thingsboard/server/dao/resource/ResourceDao.java

@ -0,0 +1,35 @@
/**
* 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.resource;
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.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
public interface ResourceDao {
Resource saveResource(Resource resource);
Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId);
void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId);
PageData<Resource> findAllByTenantId(TenantId tenantId, PageLink pageLink);
void removeAllByTenantId(TenantId tenantId);
}

77
dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceDaoImpl.java

@ -0,0 +1,77 @@
/**
* 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.sql.resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
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.transport.resource.Resource;
import org.thingsboard.server.common.data.transport.resource.ResourceType;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.ResourceCompositeKey;
import org.thingsboard.server.dao.model.sql.ResourceEntity;
import org.thingsboard.server.dao.resource.ResourceDao;
@Slf4j
@Component
public class ResourceDaoImpl implements ResourceDao {
private final ResourceRepository resourceRepository;
public ResourceDaoImpl(ResourceRepository resourceRepository) {
this.resourceRepository = resourceRepository;
}
@Override
@Transactional
public Resource saveResource(Resource resource) {
return DaoUtil.getData(resourceRepository.save(new ResourceEntity(resource)));
}
@Override
public Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId) {
ResourceCompositeKey key = new ResourceCompositeKey();
key.setTenantId(tenantId.getId());
key.setResourceType(resourceType.name());
key.setResourceId(resourceId);
return DaoUtil.getData(resourceRepository.findById(key));
}
@Override
@Transactional
public void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) {
ResourceCompositeKey key = new ResourceCompositeKey();
key.setTenantId(tenantId.getId());
key.setResourceType(resourceType.name());
key.setResourceId(resourceId);
resourceRepository.deleteById(key);
}
@Override
public PageData<Resource> findAllByTenantId(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(resourceRepository.findAllByTenantId(tenantId.getId(), DaoUtil.toPageable(pageLink)));
}
@Override
public void removeAllByTenantId(TenantId tenantId) {
resourceRepository.removeAllByTenantId(tenantId.getId());
}
}

31
dao/src/main/java/org/thingsboard/server/dao/sql/resource/ResourceRepository.java

@ -0,0 +1,31 @@
/**
* 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.sql.resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.thingsboard.server.dao.model.sql.ResourceCompositeKey;
import org.thingsboard.server.dao.model.sql.ResourceEntity;
import java.util.UUID;
public interface ResourceRepository extends CrudRepository<ResourceEntity, ResourceCompositeKey> {
Page<ResourceEntity> findAllByTenantId(UUID tenantId, Pageable pageable);
void removeAllByTenantId(UUID tenantId);
}

5
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java

@ -35,6 +35,7 @@ import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.resource.ResourceService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
@ -88,6 +89,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
@Autowired
private RuleChainService ruleChainService;
@Autowired
private ResourceService resourceService;
@Override
public Tenant findTenantById(TenantId tenantId) {
log.trace("Executing findTenantById [{}]", tenantId);
@ -140,6 +144,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
userService.deleteTenantAdmins(tenantId);
ruleChainService.deleteRuleChainsByTenantId(tenantId);
apiUsageStateService.deleteApiUsageStateByTenantId(tenantId);
resourceService.deleteResourcesByTenantId(tenantId);
tenantDao.removeById(tenantId, tenantId.getId());
deleteEntityRelations(tenantId, tenantId);
}

8
dao/src/main/resources/sql/schema-entities-hsql.sql

@ -420,3 +420,11 @@ CREATE TABLE IF NOT EXISTS api_usage_state (
sms_exec varchar(32),
CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id)
);
CREATE TABLE IF NOT EXISTS resource (
tenant_id uuid NOT NULL,
resource_type varchar(32) NOT NULL,
resource_id varchar(255) NOT NULL,
resource_value varchar,
CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)
);

8
dao/src/main/resources/sql/schema-entities.sql

@ -447,6 +447,14 @@ CREATE TABLE IF NOT EXISTS api_usage_state (
CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id)
);
CREATE TABLE IF NOT EXISTS resource (
tenant_id uuid NOT NULL,
resource_type varchar(32) NOT NULL,
resource_id varchar(255) NOT NULL,
resource_value varchar,
CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)
);
CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint)
LANGUAGE plpgsql AS
$$

1
dao/src/test/resources/sql/hsql/drop-all-tables.sql

@ -28,4 +28,5 @@ DROP TABLE IF EXISTS oauth2_client_registration;
DROP TABLE IF EXISTS oauth2_client_registration_info;
DROP TABLE IF EXISTS oauth2_client_registration_template;
DROP TABLE IF EXISTS api_usage_state;
DROP TABLE IF EXISTS resource;
DROP FUNCTION IF EXISTS to_uuid;

3
dao/src/test/resources/sql/psql/drop-all-tables.sql

@ -28,4 +28,5 @@ DROP TABLE IF EXISTS tb_schema_settings;
DROP TABLE IF EXISTS oauth2_client_registration;
DROP TABLE IF EXISTS oauth2_client_registration_info;
DROP TABLE IF EXISTS oauth2_client_registration_template;
DROP TABLE IF EXISTS api_usage_state;
DROP TABLE IF EXISTS api_usage_state;
DROP TABLE IF EXISTS resource;

Loading…
Cancel
Save