Commit e2dd5b96aef5aca4c6a21012a5bbbda9b489169d
Committed by
GitHub
1 parent
3f4714c2
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
Showing
29 changed files
with
801 additions
and
9 deletions
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.controller; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
20 | +import org.springframework.web.bind.annotation.PathVariable; | ||
21 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
22 | +import org.springframework.web.bind.annotation.RequestMethod; | ||
23 | +import org.springframework.web.bind.annotation.RequestParam; | ||
24 | +import org.springframework.web.bind.annotation.ResponseBody; | ||
25 | +import org.springframework.web.bind.annotation.RestController; | ||
26 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
27 | +import org.thingsboard.server.common.data.id.TenantId; | ||
28 | +import org.thingsboard.server.common.data.page.PageData; | ||
29 | +import org.thingsboard.server.common.data.page.PageLink; | ||
30 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
31 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
32 | +import org.thingsboard.server.dao.resource.ResourceService; | ||
33 | +import org.thingsboard.server.queue.util.TbCoreComponent; | ||
34 | + | ||
35 | +@Slf4j | ||
36 | +@RestController | ||
37 | +@TbCoreComponent | ||
38 | +@RequestMapping("/api") | ||
39 | +public class ResourceController extends BaseController { | ||
40 | + | ||
41 | + private final ResourceService resourceService; | ||
42 | + | ||
43 | + public ResourceController(ResourceService resourceService) { | ||
44 | + this.resourceService = resourceService; | ||
45 | + } | ||
46 | + | ||
47 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | ||
48 | + @RequestMapping(value = "/resource", method = RequestMethod.POST) | ||
49 | + @ResponseBody | ||
50 | + public Resource saveResource(Resource resource) throws ThingsboardException { | ||
51 | + try { | ||
52 | + resource.setTenantId(getTenantId()); | ||
53 | + Resource savedResource = checkNotNull(resourceService.saveResource(resource)); | ||
54 | + tbClusterService.onResourceChange(savedResource, null); | ||
55 | + return savedResource; | ||
56 | + } catch (Exception e) { | ||
57 | + throw handleException(e); | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
61 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | ||
62 | + @RequestMapping(value = "/resource", method = RequestMethod.GET) | ||
63 | + @ResponseBody | ||
64 | + public PageData<Resource> getResources(@RequestParam(required = false) boolean system, | ||
65 | + @RequestParam int pageSize, | ||
66 | + @RequestParam int page, | ||
67 | + @RequestParam(required = false) String sortProperty, | ||
68 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
69 | + try { | ||
70 | + PageLink pageLink = createPageLink(pageSize, page, null, sortProperty, sortOrder); | ||
71 | + return checkNotNull(resourceService.findResourcesByTenantId(system ? TenantId.SYS_TENANT_ID : getTenantId(), pageLink)); | ||
72 | + } catch (Exception e) { | ||
73 | + throw handleException(e); | ||
74 | + } | ||
75 | + } | ||
76 | + | ||
77 | + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") | ||
78 | + @RequestMapping(value = "/resource/{resourceType}/{resourceId}", method = RequestMethod.DELETE) | ||
79 | + @ResponseBody | ||
80 | + public void deleteResource(@PathVariable("resourceType") ResourceType resourceType, | ||
81 | + @PathVariable("resourceId") String resourceId) throws ThingsboardException { | ||
82 | + try { | ||
83 | + Resource resource = checkNotNull(resourceService.getResource(getTenantId(), resourceType, resourceId)); | ||
84 | + resourceService.deleteResource(getTenantId(), resourceType, resourceId); | ||
85 | + tbClusterService.onResourceDeleted(resource, null); | ||
86 | + } catch (Exception e) { | ||
87 | + throw handleException(e); | ||
88 | + } | ||
89 | + } | ||
90 | +} |
@@ -194,6 +194,12 @@ public class ThingsboardInstallService { | @@ -194,6 +194,12 @@ public class ThingsboardInstallService { | ||
194 | log.info("Updating system data..."); | 194 | log.info("Updating system data..."); |
195 | systemDataLoaderService.updateSystemWidgets(); | 195 | systemDataLoaderService.updateSystemWidgets(); |
196 | break; | 196 | break; |
197 | + case "3.2.2": | ||
198 | + log.info("Upgrading ThingsBoard from version 3.2.2 to 3.3.0 ..."); | ||
199 | + databaseEntitiesUpgradeService.upgradeDatabase("3.2.2"); | ||
200 | + | ||
201 | + log.info("Updating system data..."); | ||
202 | + break; | ||
197 | default: | 203 | default: |
198 | throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion); | 204 | throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion); |
199 | 205 | ||
@@ -226,6 +232,7 @@ public class ThingsboardInstallService { | @@ -226,6 +232,7 @@ public class ThingsboardInstallService { | ||
226 | systemDataLoaderService.createAdminSettings(); | 232 | systemDataLoaderService.createAdminSettings(); |
227 | systemDataLoaderService.loadSystemWidgets(); | 233 | systemDataLoaderService.loadSystemWidgets(); |
228 | systemDataLoaderService.createOAuth2Templates(); | 234 | systemDataLoaderService.createOAuth2Templates(); |
235 | + systemDataLoaderService.loadSystemLwm2mResources(); | ||
229 | // systemDataLoaderService.loadSystemPlugins(); | 236 | // systemDataLoaderService.loadSystemPlugins(); |
230 | // systemDataLoaderService.loadSystemRules(); | 237 | // systemDataLoaderService.loadSystemRules(); |
231 | 238 |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -445,6 +445,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -445,6 +445,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
445 | installScripts.loadSystemWidgets(); | 445 | installScripts.loadSystemWidgets(); |
446 | } | 446 | } |
447 | 447 | ||
448 | + @Override | ||
449 | + public void loadSystemLwm2mResources() throws Exception { | ||
450 | + installScripts.loadSystemLwm2mResources(); | ||
451 | + } | ||
452 | + | ||
448 | private User createUser(Authority authority, | 453 | private User createUser(Authority authority, |
449 | TenantId tenantId, | 454 | TenantId tenantId, |
450 | CustomerId customerId, | 455 | CustomerId customerId, |
@@ -24,15 +24,17 @@ import org.springframework.util.StringUtils; | @@ -24,15 +24,17 @@ import org.springframework.util.StringUtils; | ||
24 | import org.thingsboard.server.common.data.Dashboard; | 24 | import org.thingsboard.server.common.data.Dashboard; |
25 | import org.thingsboard.server.common.data.id.CustomerId; | 25 | import org.thingsboard.server.common.data.id.CustomerId; |
26 | import org.thingsboard.server.common.data.id.EntityId; | 26 | import org.thingsboard.server.common.data.id.EntityId; |
27 | -import org.thingsboard.server.common.data.id.RuleChainId; | ||
28 | import org.thingsboard.server.common.data.id.TenantId; | 27 | import org.thingsboard.server.common.data.id.TenantId; |
29 | import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; | 28 | import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; |
30 | import org.thingsboard.server.common.data.rule.RuleChain; | 29 | import org.thingsboard.server.common.data.rule.RuleChain; |
31 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 30 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
31 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
32 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
32 | import org.thingsboard.server.common.data.widget.WidgetType; | 33 | import org.thingsboard.server.common.data.widget.WidgetType; |
33 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 34 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
34 | import org.thingsboard.server.dao.dashboard.DashboardService; | 35 | import org.thingsboard.server.dao.dashboard.DashboardService; |
35 | import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; | 36 | import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; |
37 | +import org.thingsboard.server.dao.resource.ResourceService; | ||
36 | import org.thingsboard.server.dao.rule.RuleChainService; | 38 | import org.thingsboard.server.dao.rule.RuleChainService; |
37 | import org.thingsboard.server.dao.widget.WidgetTypeService; | 39 | import org.thingsboard.server.dao.widget.WidgetTypeService; |
38 | import org.thingsboard.server.dao.widget.WidgetsBundleService; | 40 | import org.thingsboard.server.dao.widget.WidgetsBundleService; |
@@ -42,6 +44,7 @@ import java.nio.file.DirectoryStream; | @@ -42,6 +44,7 @@ import java.nio.file.DirectoryStream; | ||
42 | import java.nio.file.Files; | 44 | import java.nio.file.Files; |
43 | import java.nio.file.Path; | 45 | import java.nio.file.Path; |
44 | import java.nio.file.Paths; | 46 | import java.nio.file.Paths; |
47 | +import java.util.Base64; | ||
45 | import java.util.Optional; | 48 | import java.util.Optional; |
46 | 49 | ||
47 | import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper; | 50 | import static org.thingsboard.server.service.install.DatabaseHelper.objectMapper; |
@@ -66,8 +69,11 @@ public class InstallScripts { | @@ -66,8 +69,11 @@ public class InstallScripts { | ||
66 | public static final String WIDGET_BUNDLES_DIR = "widget_bundles"; | 69 | public static final String WIDGET_BUNDLES_DIR = "widget_bundles"; |
67 | public static final String OAUTH2_CONFIG_TEMPLATES_DIR = "oauth2_config_templates"; | 70 | public static final String OAUTH2_CONFIG_TEMPLATES_DIR = "oauth2_config_templates"; |
68 | public static final String DASHBOARDS_DIR = "dashboards"; | 71 | public static final String DASHBOARDS_DIR = "dashboards"; |
72 | + public static final String MODELS_DIR = "models"; | ||
73 | + public static final String CREDENTIALS_DIR = "credentials"; | ||
69 | 74 | ||
70 | public static final String JSON_EXT = ".json"; | 75 | public static final String JSON_EXT = ".json"; |
76 | + public static final String XML_EXT = ".xml"; | ||
71 | 77 | ||
72 | @Value("${install.data_dir:}") | 78 | @Value("${install.data_dir:}") |
73 | private String dataDir; | 79 | private String dataDir; |
@@ -87,6 +93,9 @@ public class InstallScripts { | @@ -87,6 +93,9 @@ public class InstallScripts { | ||
87 | @Autowired | 93 | @Autowired |
88 | private OAuth2ConfigTemplateService oAuth2TemplateService; | 94 | private OAuth2ConfigTemplateService oAuth2TemplateService; |
89 | 95 | ||
96 | + @Autowired | ||
97 | + private ResourceService resourceService; | ||
98 | + | ||
90 | public Path getTenantRuleChainsDir() { | 99 | public Path getTenantRuleChainsDir() { |
91 | return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR); | 100 | return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, RULE_CHAINS_DIR); |
92 | } | 101 | } |
@@ -186,6 +195,42 @@ public class InstallScripts { | @@ -186,6 +195,42 @@ public class InstallScripts { | ||
186 | } | 195 | } |
187 | } | 196 | } |
188 | 197 | ||
198 | + public void loadSystemLwm2mResources() throws Exception { | ||
199 | + Path modelsDir = Paths.get(getDataDir(), MODELS_DIR); | ||
200 | + if (Files.isDirectory(modelsDir)) { | ||
201 | + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(modelsDir, path -> path.toString().endsWith(XML_EXT))) { | ||
202 | + dirStream.forEach( | ||
203 | + path -> { | ||
204 | + try { | ||
205 | + Resource resource = new Resource(); | ||
206 | + resource.setTenantId(TenantId.SYS_TENANT_ID); | ||
207 | + resource.setResourceType(ResourceType.LWM2M_MODEL); | ||
208 | + resource.setResourceId(path.getFileName().toString()); | ||
209 | + resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(path))); | ||
210 | + resourceService.saveResource(resource); | ||
211 | + } catch (Exception e) { | ||
212 | + log.error("Unable to load lwm2m model [{}]", path.toString()); | ||
213 | + throw new RuntimeException("Unable to load lwm2m model", e); | ||
214 | + } | ||
215 | + } | ||
216 | + ); | ||
217 | + } | ||
218 | + } | ||
219 | + | ||
220 | + Path jksPath = Paths.get(getDataDir(), CREDENTIALS_DIR, "serverKeyStore.jks"); | ||
221 | + try { | ||
222 | + Resource resource = new Resource(); | ||
223 | + resource.setTenantId(TenantId.SYS_TENANT_ID); | ||
224 | + resource.setResourceType(ResourceType.JKS); | ||
225 | + resource.setResourceId(jksPath.getFileName().toString()); | ||
226 | + resource.setValue(Base64.getEncoder().encodeToString(Files.readAllBytes(jksPath))); | ||
227 | + resourceService.saveResource(resource); | ||
228 | + } catch (Exception e) { | ||
229 | + log.error("Unable to load lwm2m serverKeyStore [{}]", jksPath.toString()); | ||
230 | + throw new RuntimeException("Unable to load l2m2m serverKeyStore", e); | ||
231 | + } | ||
232 | + } | ||
233 | + | ||
189 | public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception { | 234 | public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception { |
190 | Path dashboardsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR); | 235 | Path dashboardsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, DASHBOARDS_DIR); |
191 | try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) { | 236 | try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(dashboardsDir, path -> path.toString().endsWith(JSON_EXT))) { |
@@ -208,7 +253,6 @@ public class InstallScripts { | @@ -208,7 +253,6 @@ public class InstallScripts { | ||
208 | } | 253 | } |
209 | } | 254 | } |
210 | 255 | ||
211 | - | ||
212 | public void loadDemoRuleChains(TenantId tenantId) throws Exception { | 256 | public void loadDemoRuleChains(TenantId tenantId) throws Exception { |
213 | try { | 257 | try { |
214 | createDefaultRuleChains(tenantId); | 258 | createDefaultRuleChains(tenantId); |
@@ -434,6 +434,25 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService | @@ -434,6 +434,25 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService | ||
434 | log.info("Schema updated."); | 434 | log.info("Schema updated."); |
435 | } | 435 | } |
436 | break; | 436 | break; |
437 | + case "3.2.2": | ||
438 | + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | ||
439 | + log.info("Updating schema ..."); | ||
440 | + try { | ||
441 | + conn.createStatement().execute("CREATE TABLE IF NOT EXISTS resource (" + | ||
442 | + " tenant_id uuid NOT NULL," + | ||
443 | + " resource_type varchar(32) NOT NULL," + | ||
444 | + " resource_id varchar(255) NOT NULL," + | ||
445 | + " resource_value varchar," + | ||
446 | + " CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id)" + | ||
447 | + " );"); | ||
448 | + | ||
449 | + conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3003000;"); | ||
450 | + } catch (Exception e) { | ||
451 | + log.error("Failed updating schema!!!", e); | ||
452 | + } | ||
453 | + log.info("Schema updated."); | ||
454 | + } | ||
455 | + break; | ||
437 | default: | 456 | default: |
438 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); | 457 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); |
439 | } | 458 | } |
@@ -33,4 +33,6 @@ public interface SystemDataLoaderService { | @@ -33,4 +33,6 @@ public interface SystemDataLoaderService { | ||
33 | 33 | ||
34 | void deleteSystemWidgetBundle(String bundleAlias) throws Exception; | 34 | void deleteSystemWidgetBundle(String bundleAlias) throws Exception; |
35 | 35 | ||
36 | + void loadSystemLwm2mResources() throws Exception; | ||
37 | + | ||
36 | } | 38 | } |
@@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.page.PageLink; | @@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.page.PageLink; | ||
33 | import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap; | 33 | import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigBootstrap; |
34 | import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; | 34 | import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; |
35 | import org.thingsboard.server.dao.service.Validator; | 35 | import org.thingsboard.server.dao.service.Validator; |
36 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | ||
36 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; | 37 | import org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode; |
37 | 38 | ||
38 | import java.math.BigInteger; | 39 | import java.math.BigInteger; |
@@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
34 | import org.thingsboard.server.common.data.id.RuleChainId; | 34 | import org.thingsboard.server.common.data.id.RuleChainId; |
35 | import org.thingsboard.server.common.data.id.TenantId; | 35 | import org.thingsboard.server.common.data.id.TenantId; |
36 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 36 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
37 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
37 | import org.thingsboard.server.common.msg.TbMsg; | 38 | import org.thingsboard.server.common.msg.TbMsg; |
38 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; | 39 | import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; |
39 | import org.thingsboard.server.common.msg.queue.ServiceType; | 40 | import org.thingsboard.server.common.msg.queue.ServiceType; |
@@ -247,6 +248,34 @@ public class DefaultTbClusterService implements TbClusterService { | @@ -247,6 +248,34 @@ public class DefaultTbClusterService implements TbClusterService { | ||
247 | onEntityDelete(entity.getTenantId(), entity.getId(), entity.getName(), callback); | 248 | onEntityDelete(entity.getTenantId(), entity.getId(), entity.getName(), callback); |
248 | } | 249 | } |
249 | 250 | ||
251 | + @Override | ||
252 | + public void onResourceChange(Resource resource, TbQueueCallback callback) { | ||
253 | + TenantId tenantId = resource.getTenantId(); | ||
254 | + log.trace("[{}][{}][{}] Processing change resource", tenantId, resource.getResourceType(), resource.getResourceId()); | ||
255 | + TransportProtos.ResourceUpdateMsg resourceUpdateMsg = TransportProtos.ResourceUpdateMsg.newBuilder() | ||
256 | + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) | ||
257 | + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) | ||
258 | + .setResourceType(resource.getResourceType().name()) | ||
259 | + .setResourceId(resource.getResourceId()) | ||
260 | + .build(); | ||
261 | + ToTransportMsg transportMsg = ToTransportMsg.newBuilder().setResourceUpdateMsg(resourceUpdateMsg).build(); | ||
262 | + broadcast(transportMsg, callback); | ||
263 | + } | ||
264 | + | ||
265 | + @Override | ||
266 | + public void onResourceDeleted(Resource resource, TbQueueCallback callback) { | ||
267 | + TenantId tenantId = resource.getTenantId(); | ||
268 | + log.trace("[{}][{}][{}] Processing delete resource", tenantId, resource.getResourceType(), resource.getResourceId()); | ||
269 | + TransportProtos.ResourceDeleteMsg resourceUpdateMsg = TransportProtos.ResourceDeleteMsg.newBuilder() | ||
270 | + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) | ||
271 | + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) | ||
272 | + .setResourceType(resource.getResourceType().name()) | ||
273 | + .setResourceId(resource.getResourceId()) | ||
274 | + .build(); | ||
275 | + ToTransportMsg transportMsg = ToTransportMsg.newBuilder().setResourceDeleteMsg(resourceUpdateMsg).build(); | ||
276 | + broadcast(transportMsg, callback); | ||
277 | + } | ||
278 | + | ||
250 | public <T> void onEntityChange(TenantId tenantId, EntityId entityid, T entity, TbQueueCallback callback) { | 279 | public <T> void onEntityChange(TenantId tenantId, EntityId entityid, T entity, TbQueueCallback callback) { |
251 | String entityName = (entity instanceof HasName) ? ((HasName) entity).getName() : entity.getClass().getName(); | 280 | String entityName = (entity instanceof HasName) ? ((HasName) entity).getName() : entity.getClass().getName(); |
252 | log.trace("[{}][{}][{}] Processing [{}] change event", tenantId, entityid.getEntityType(), entityid.getId(), entityName); | 281 | log.trace("[{}][{}][{}] Processing [{}] change event", tenantId, entityid.getEntityType(), entityid.getId(), entityName); |
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.TenantProfile; | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.TenantProfile; | ||
24 | import org.thingsboard.server.common.data.id.EntityId; | 24 | import org.thingsboard.server.common.data.id.EntityId; |
25 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
26 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 26 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
27 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
27 | import org.thingsboard.server.common.msg.TbMsg; | 28 | import org.thingsboard.server.common.msg.TbMsg; |
28 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; | 29 | import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; |
29 | import org.thingsboard.server.gen.transport.TransportProtos; | 30 | import org.thingsboard.server.gen.transport.TransportProtos; |
@@ -71,4 +72,8 @@ public interface TbClusterService { | @@ -71,4 +72,8 @@ public interface TbClusterService { | ||
71 | void onDeviceChange(Device device, TbQueueCallback callback); | 72 | void onDeviceChange(Device device, TbQueueCallback callback); |
72 | 73 | ||
73 | void onDeviceDeleted(Device device, TbQueueCallback callback); | 74 | void onDeviceDeleted(Device device, TbQueueCallback callback); |
75 | + | ||
76 | + void onResourceChange(Resource resource, TbQueueCallback callback); | ||
77 | + | ||
78 | + void onResourceDeleted(Resource resource, TbQueueCallback callback); | ||
74 | } | 79 | } |
@@ -25,6 +25,7 @@ import com.google.protobuf.ByteString; | @@ -25,6 +25,7 @@ import com.google.protobuf.ByteString; | ||
25 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
26 | import org.springframework.stereotype.Service; | 26 | import org.springframework.stereotype.Service; |
27 | import org.springframework.util.StringUtils; | 27 | import org.springframework.util.StringUtils; |
28 | +import org.thingsboard.common.util.JacksonUtil; | ||
28 | import org.thingsboard.server.common.data.ApiUsageState; | 29 | import org.thingsboard.server.common.data.ApiUsageState; |
29 | import org.thingsboard.server.common.data.DataConstants; | 30 | import org.thingsboard.server.common.data.DataConstants; |
30 | import org.thingsboard.server.common.data.Device; | 31 | import org.thingsboard.server.common.data.Device; |
@@ -38,9 +39,12 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -38,9 +39,12 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
38 | import org.thingsboard.server.common.data.id.DeviceId; | 39 | import org.thingsboard.server.common.data.id.DeviceId; |
39 | import org.thingsboard.server.common.data.id.DeviceProfileId; | 40 | import org.thingsboard.server.common.data.id.DeviceProfileId; |
40 | import org.thingsboard.server.common.data.id.TenantId; | 41 | import org.thingsboard.server.common.data.id.TenantId; |
42 | +import org.thingsboard.server.common.data.page.PageLink; | ||
41 | import org.thingsboard.server.common.data.relation.EntityRelation; | 43 | import org.thingsboard.server.common.data.relation.EntityRelation; |
42 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 44 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
43 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 45 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
46 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
47 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
44 | import org.thingsboard.server.common.msg.EncryptionUtil; | 48 | import org.thingsboard.server.common.msg.EncryptionUtil; |
45 | import org.thingsboard.server.common.msg.TbMsg; | 49 | import org.thingsboard.server.common.msg.TbMsg; |
46 | import org.thingsboard.server.common.msg.TbMsgDataType; | 50 | import org.thingsboard.server.common.msg.TbMsgDataType; |
@@ -53,14 +57,15 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException; | @@ -53,14 +57,15 @@ import org.thingsboard.server.dao.device.provision.ProvisionFailedException; | ||
53 | import org.thingsboard.server.dao.device.provision.ProvisionRequest; | 57 | import org.thingsboard.server.dao.device.provision.ProvisionRequest; |
54 | import org.thingsboard.server.dao.device.provision.ProvisionResponse; | 58 | import org.thingsboard.server.dao.device.provision.ProvisionResponse; |
55 | import org.thingsboard.server.dao.relation.RelationService; | 59 | import org.thingsboard.server.dao.relation.RelationService; |
60 | +import org.thingsboard.server.dao.resource.ResourceService; | ||
56 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; | 61 | import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
57 | -import org.thingsboard.common.util.JacksonUtil; | ||
58 | import org.thingsboard.server.gen.transport.TransportProtos; | 62 | import org.thingsboard.server.gen.transport.TransportProtos; |
59 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; | 63 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; |
60 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; | 64 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; |
61 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; | 65 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; |
62 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; | 66 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; |
63 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg; | 67 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg; |
68 | +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesRequestMsg; | ||
64 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; | 69 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
65 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionResponseStatus; | 70 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionResponseStatus; |
66 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; | 71 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
@@ -77,11 +82,14 @@ import org.thingsboard.server.service.profile.TbDeviceProfileCache; | @@ -77,11 +82,14 @@ import org.thingsboard.server.service.profile.TbDeviceProfileCache; | ||
77 | import org.thingsboard.server.service.queue.TbClusterService; | 82 | import org.thingsboard.server.service.queue.TbClusterService; |
78 | import org.thingsboard.server.service.state.DeviceStateService; | 83 | import org.thingsboard.server.service.state.DeviceStateService; |
79 | 84 | ||
85 | +import java.util.Collections; | ||
86 | +import java.util.List; | ||
80 | import java.util.UUID; | 87 | import java.util.UUID; |
81 | import java.util.concurrent.ConcurrentHashMap; | 88 | import java.util.concurrent.ConcurrentHashMap; |
82 | import java.util.concurrent.ConcurrentMap; | 89 | import java.util.concurrent.ConcurrentMap; |
83 | import java.util.concurrent.locks.Lock; | 90 | import java.util.concurrent.locks.Lock; |
84 | import java.util.concurrent.locks.ReentrantLock; | 91 | import java.util.concurrent.locks.ReentrantLock; |
92 | +import java.util.stream.Collectors; | ||
85 | 93 | ||
86 | /** | 94 | /** |
87 | * Created by ashvayka on 05.10.18. | 95 | * Created by ashvayka on 05.10.18. |
@@ -104,6 +112,7 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -104,6 +112,7 @@ public class DefaultTransportApiService implements TransportApiService { | ||
104 | private final TbClusterService tbClusterService; | 112 | private final TbClusterService tbClusterService; |
105 | private final DataDecodingEncodingService dataDecodingEncodingService; | 113 | private final DataDecodingEncodingService dataDecodingEncodingService; |
106 | private final DeviceProvisionService deviceProvisionService; | 114 | private final DeviceProvisionService deviceProvisionService; |
115 | + private final ResourceService resourceService; | ||
107 | 116 | ||
108 | private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>(); | 117 | private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>(); |
109 | 118 | ||
@@ -112,7 +121,7 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -112,7 +121,7 @@ public class DefaultTransportApiService implements TransportApiService { | ||
112 | RelationService relationService, DeviceCredentialsService deviceCredentialsService, | 121 | RelationService relationService, DeviceCredentialsService deviceCredentialsService, |
113 | DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService, | 122 | DeviceStateService deviceStateService, DbCallbackExecutorService dbCallbackExecutorService, |
114 | TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService, | 123 | TbClusterService tbClusterService, DataDecodingEncodingService dataDecodingEncodingService, |
115 | - DeviceProvisionService deviceProvisionService) { | 124 | + DeviceProvisionService deviceProvisionService, ResourceService resourceService) { |
116 | this.deviceProfileCache = deviceProfileCache; | 125 | this.deviceProfileCache = deviceProfileCache; |
117 | this.tenantProfileCache = tenantProfileCache; | 126 | this.tenantProfileCache = tenantProfileCache; |
118 | this.apiUsageStateService = apiUsageStateService; | 127 | this.apiUsageStateService = apiUsageStateService; |
@@ -124,6 +133,7 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -124,6 +133,7 @@ public class DefaultTransportApiService implements TransportApiService { | ||
124 | this.tbClusterService = tbClusterService; | 133 | this.tbClusterService = tbClusterService; |
125 | this.dataDecodingEncodingService = dataDecodingEncodingService; | 134 | this.dataDecodingEncodingService = dataDecodingEncodingService; |
126 | this.deviceProvisionService = deviceProvisionService; | 135 | this.deviceProvisionService = deviceProvisionService; |
136 | + this.resourceService = resourceService; | ||
127 | } | 137 | } |
128 | 138 | ||
129 | @Override | 139 | @Override |
@@ -157,6 +167,9 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -157,6 +167,9 @@ public class DefaultTransportApiService implements TransportApiService { | ||
157 | } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { | 167 | } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { |
158 | return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), | 168 | return Futures.transform(handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()), |
159 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 169 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); |
170 | + } else if (transportApiRequestMsg.hasResourcesRequestMsg()) { | ||
171 | + return Futures.transform(handle(transportApiRequestMsg.getResourcesRequestMsg()), | ||
172 | + value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | ||
160 | } | 173 | } |
161 | return Futures.transform(getEmptyTransportApiResponseFuture(), | 174 | return Futures.transform(getEmptyTransportApiResponseFuture(), |
162 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); | 175 | value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), MoreExecutors.directExecutor()); |
@@ -315,9 +328,9 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -315,9 +328,9 @@ public class DefaultTransportApiService implements TransportApiService { | ||
315 | return TransportApiResponseMsg.newBuilder().setProvisionDeviceResponseMsg(TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build()).build(); | 328 | return TransportApiResponseMsg.newBuilder().setProvisionDeviceResponseMsg(TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build()).build(); |
316 | } | 329 | } |
317 | TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse = TransportProtos.ProvisionDeviceResponseMsg.newBuilder() | 330 | TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse = TransportProtos.ProvisionDeviceResponseMsg.newBuilder() |
318 | - .setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name())) | ||
319 | - .setStatus(status); | ||
320 | - switch (deviceCredentials.getCredentialsType()){ | 331 | + .setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name())) |
332 | + .setStatus(status); | ||
333 | + switch (deviceCredentials.getCredentialsType()) { | ||
321 | case ACCESS_TOKEN: | 334 | case ACCESS_TOKEN: |
322 | provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId()); | 335 | provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId()); |
323 | break; | 336 | break; |
@@ -353,6 +366,40 @@ public class DefaultTransportApiService implements TransportApiService { | @@ -353,6 +366,40 @@ public class DefaultTransportApiService implements TransportApiService { | ||
353 | return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); | 366 | return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); |
354 | } | 367 | } |
355 | 368 | ||
369 | + private ListenableFuture<TransportApiResponseMsg> handle(GetResourcesRequestMsg requestMsg) { | ||
370 | + TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); | ||
371 | + TransportProtos.GetResourcesResponseMsg.Builder builder = TransportProtos.GetResourcesResponseMsg.newBuilder(); | ||
372 | + String resourceType = requestMsg.getResourceType(); | ||
373 | + String resourceId = requestMsg.getResourceId(); | ||
374 | + | ||
375 | + List<TransportProtos.ResourceMsg> resources; | ||
376 | + | ||
377 | + if (resourceType != null && resourceId != null) { | ||
378 | + resources = Collections.singletonList(toProto( | ||
379 | + resourceService.getResource(tenantId, ResourceType.valueOf(resourceType), resourceId))); | ||
380 | + } else { | ||
381 | + //TODO: add page link params to request proto if need or remove this | ||
382 | + resources = resourceService.findResourcesByTenantId(tenantId, new PageLink(100)) | ||
383 | + .getData() | ||
384 | + .stream() | ||
385 | + .map(this::toProto) | ||
386 | + .collect(Collectors.toList()); | ||
387 | + } | ||
388 | + | ||
389 | + builder.addAllResources(resources); | ||
390 | + return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setResourcesResponseMsg(builder).build()); | ||
391 | + } | ||
392 | + | ||
393 | + private TransportProtos.ResourceMsg toProto(Resource resource) { | ||
394 | + return TransportProtos.ResourceMsg.newBuilder() | ||
395 | + .setTenantIdMSB(resource.getTenantId().getId().getMostSignificantBits()) | ||
396 | + .setTenantIdLSB(resource.getTenantId().getId().getLeastSignificantBits()) | ||
397 | + .setResourceType(resource.getResourceType().name()) | ||
398 | + .setResourceId(resource.getResourceId()) | ||
399 | + .setValue(resource.getValue()) | ||
400 | + .build(); | ||
401 | + } | ||
402 | + | ||
356 | private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) { | 403 | private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) { |
357 | return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, deviceId), device -> { | 404 | return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, deviceId), device -> { |
358 | if (device == null) { | 405 | if (device == null) { |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.resource; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.id.TenantId; | ||
19 | +import org.thingsboard.server.common.data.page.PageData; | ||
20 | +import org.thingsboard.server.common.data.page.PageLink; | ||
21 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
22 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
23 | + | ||
24 | + | ||
25 | +public interface ResourceService { | ||
26 | + Resource saveResource(Resource resource); | ||
27 | + | ||
28 | + Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); | ||
29 | + | ||
30 | + PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink); | ||
31 | + | ||
32 | + void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); | ||
33 | + | ||
34 | + void deleteResourcesByTenantId(TenantId tenantId); | ||
35 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/Resource.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.transport.resource; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.HasTenantId; | ||
20 | +import org.thingsboard.server.common.data.id.TenantId; | ||
21 | + | ||
22 | +@Data | ||
23 | +public class Resource implements HasTenantId { | ||
24 | + private TenantId tenantId; | ||
25 | + private ResourceType resourceType; | ||
26 | + private String resourceId; | ||
27 | + private String value; | ||
28 | + | ||
29 | + @Override | ||
30 | + public String toString() { | ||
31 | + return "Resource{" + | ||
32 | + "tenantId=" + tenantId + | ||
33 | + ", resourceType=" + resourceType + | ||
34 | + ", resourceId='" + resourceId + '\'' + | ||
35 | + '}'; | ||
36 | + } | ||
37 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/transport/resource/ResourceType.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.transport.resource; | ||
17 | + | ||
18 | +public enum ResourceType { | ||
19 | + LWM2M_MODEL, JKS, PKCS_12 | ||
20 | +} |
@@ -21,6 +21,6 @@ import java.lang.annotation.Retention; | @@ -21,6 +21,6 @@ import java.lang.annotation.Retention; | ||
21 | import java.lang.annotation.RetentionPolicy; | 21 | import java.lang.annotation.RetentionPolicy; |
22 | 22 | ||
23 | @Retention(RetentionPolicy.RUNTIME) | 23 | @Retention(RetentionPolicy.RUNTIME) |
24 | -@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' ) || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") | 24 | +@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled}'=='true')") |
25 | public @interface TbLwM2mTransportComponent { | 25 | public @interface TbLwM2mTransportComponent { |
26 | } | 26 | } |
@@ -201,6 +201,25 @@ message LwM2MResponseMsg { | @@ -201,6 +201,25 @@ message LwM2MResponseMsg { | ||
201 | LwM2MRegistrationResponseMsg registrationMsg = 1; | 201 | LwM2MRegistrationResponseMsg registrationMsg = 1; |
202 | } | 202 | } |
203 | 203 | ||
204 | +message ResourceMsg { | ||
205 | + int64 tenantIdMSB = 1; | ||
206 | + int64 tenantIdLSB = 2; | ||
207 | + string resourceType = 3; | ||
208 | + string resourceId = 4; | ||
209 | + string value = 5; | ||
210 | +} | ||
211 | + | ||
212 | +message GetResourcesRequestMsg { | ||
213 | + int64 tenantIdMSB = 1; | ||
214 | + int64 tenantIdLSB = 2; | ||
215 | + string resourceType = 3; | ||
216 | + string resourceId = 4; | ||
217 | +} | ||
218 | + | ||
219 | +message GetResourcesResponseMsg { | ||
220 | + repeated ResourceMsg resources = 1; | ||
221 | +} | ||
222 | + | ||
204 | message ValidateDeviceLwM2MCredentialsRequestMsg { | 223 | message ValidateDeviceLwM2MCredentialsRequestMsg { |
205 | string credentialsId = 1; | 224 | string credentialsId = 1; |
206 | } | 225 | } |
@@ -242,6 +261,20 @@ message EntityDeleteMsg { | @@ -242,6 +261,20 @@ message EntityDeleteMsg { | ||
242 | int64 entityIdLSB = 3; | 261 | int64 entityIdLSB = 3; |
243 | } | 262 | } |
244 | 263 | ||
264 | +message ResourceUpdateMsg { | ||
265 | + int64 tenantIdMSB = 1; | ||
266 | + int64 tenantIdLSB = 2; | ||
267 | + string resourceType = 3; | ||
268 | + string resourceId = 4; | ||
269 | +} | ||
270 | + | ||
271 | +message ResourceDeleteMsg { | ||
272 | + int64 tenantIdMSB = 1; | ||
273 | + int64 tenantIdLSB = 2; | ||
274 | + string resourceType = 3; | ||
275 | + string resourceId = 4; | ||
276 | +} | ||
277 | + | ||
245 | message SessionCloseNotificationProto { | 278 | message SessionCloseNotificationProto { |
246 | string message = 1; | 279 | string message = 1; |
247 | } | 280 | } |
@@ -525,6 +558,7 @@ message TransportApiRequestMsg { | @@ -525,6 +558,7 @@ message TransportApiRequestMsg { | ||
525 | ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6; | 558 | ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 6; |
526 | ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7; | 559 | ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 7; |
527 | ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8; | 560 | ValidateDeviceLwM2MCredentialsRequestMsg validateDeviceLwM2MCredentialsRequestMsg = 8; |
561 | + GetResourcesRequestMsg resourcesRequestMsg = 9; | ||
528 | } | 562 | } |
529 | 563 | ||
530 | /* Response from ThingsBoard Core Service to Transport Service */ | 564 | /* Response from ThingsBoard Core Service to Transport Service */ |
@@ -534,6 +568,7 @@ message TransportApiResponseMsg { | @@ -534,6 +568,7 @@ message TransportApiResponseMsg { | ||
534 | GetEntityProfileResponseMsg entityProfileResponseMsg = 3; | 568 | GetEntityProfileResponseMsg entityProfileResponseMsg = 3; |
535 | ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; | 569 | ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 4; |
536 | LwM2MResponseMsg lwM2MResponseMsg = 6; | 570 | LwM2MResponseMsg lwM2MResponseMsg = 6; |
571 | + GetResourcesResponseMsg resourcesResponseMsg = 7; | ||
537 | } | 572 | } |
538 | 573 | ||
539 | /* Messages that are handled by ThingsBoard Core Service */ | 574 | /* Messages that are handled by ThingsBoard Core Service */ |
@@ -578,6 +613,8 @@ message ToTransportMsg { | @@ -578,6 +613,8 @@ message ToTransportMsg { | ||
578 | EntityDeleteMsg entityDeleteMsg = 9; | 613 | EntityDeleteMsg entityDeleteMsg = 9; |
579 | ProvisionDeviceResponseMsg provisionResponse = 10; | 614 | ProvisionDeviceResponseMsg provisionResponse = 10; |
580 | ToTransportUpdateCredentialsProto toTransportUpdateCredentialsNotification = 11; | 615 | ToTransportUpdateCredentialsProto toTransportUpdateCredentialsNotification = 11; |
616 | + ResourceUpdateMsg resourceUpdateMsg = 12; | ||
617 | + ResourceDeleteMsg resourceDeleteMsg = 13; | ||
581 | } | 618 | } |
582 | 619 | ||
583 | message UsageStatsKVProto{ | 620 | message UsageStatsKVProto{ |
@@ -25,6 +25,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestM | @@ -25,6 +25,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestM | ||
25 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; | 25 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileRequestMsg; |
26 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; | 26 | import org.thingsboard.server.gen.transport.TransportProtos.GetEntityProfileResponseMsg; |
27 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; | 27 | import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; |
28 | +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesRequestMsg; | ||
29 | +import org.thingsboard.server.gen.transport.TransportProtos.GetResourcesResponseMsg; | ||
28 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; | 30 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; |
29 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; | 31 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; |
30 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; | 32 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
@@ -51,6 +53,8 @@ public interface TransportService { | @@ -51,6 +53,8 @@ public interface TransportService { | ||
51 | 53 | ||
52 | GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg); | 54 | GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg); |
53 | 55 | ||
56 | + GetResourcesResponseMsg getResources(GetResourcesRequestMsg msg); | ||
57 | + | ||
54 | void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg, | 58 | void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg, |
55 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | 59 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); |
56 | 60 |
@@ -255,6 +255,18 @@ public class DefaultTransportService implements TransportService { | @@ -255,6 +255,18 @@ public class DefaultTransportService implements TransportService { | ||
255 | } | 255 | } |
256 | 256 | ||
257 | @Override | 257 | @Override |
258 | + public TransportProtos.GetResourcesResponseMsg getResources(TransportProtos.GetResourcesRequestMsg msg) { | ||
259 | + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg = | ||
260 | + new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setResourcesRequestMsg(msg).build()); | ||
261 | + try { | ||
262 | + TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
263 | + return response.getValue().getResourcesResponseMsg(); | ||
264 | + } catch (InterruptedException | ExecutionException e) { | ||
265 | + throw new RuntimeException(e); | ||
266 | + } | ||
267 | + } | ||
268 | + | ||
269 | + @Override | ||
258 | public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg, | 270 | public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg, |
259 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | 271 | TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { |
260 | log.trace("Processing msg: {}", msg); | 272 | log.trace("Processing msg: {}", msg); |
@@ -688,6 +700,10 @@ public class DefaultTransportService implements TransportService { | @@ -688,6 +700,10 @@ public class DefaultTransportService implements TransportService { | ||
688 | } else if (EntityType.DEVICE.equals(entityType)) { | 700 | } else if (EntityType.DEVICE.equals(entityType)) { |
689 | rateLimitService.remove(new DeviceId(entityUuid)); | 701 | rateLimitService.remove(new DeviceId(entityUuid)); |
690 | } | 702 | } |
703 | + } else if (toSessionMsg.hasResourceUpdateMsg()) { | ||
704 | + //TODO: update resource cache | ||
705 | + } else if (toSessionMsg.hasResourceDeleteMsg()) { | ||
706 | + //TODO: remove resource from cache | ||
691 | } else { | 707 | } else { |
692 | //TODO: should we notify the device actor about missed session? | 708 | //TODO: should we notify the device actor about missed session? |
693 | log.debug("[{}] Missing session.", sessionId); | 709 | log.debug("[{}] Missing session.", sessionId); |
@@ -695,6 +711,7 @@ public class DefaultTransportService implements TransportService { | @@ -695,6 +711,7 @@ public class DefaultTransportService implements TransportService { | ||
695 | } | 711 | } |
696 | } | 712 | } |
697 | 713 | ||
714 | + | ||
698 | public void onProfileUpdate(DeviceProfile deviceProfile) { | 715 | public void onProfileUpdate(DeviceProfile deviceProfile) { |
699 | long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits(); | 716 | long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits(); |
700 | long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits(); | 717 | long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits(); |
@@ -454,6 +454,15 @@ public class ModelConstants { | @@ -454,6 +454,15 @@ public class ModelConstants { | ||
454 | public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec"; | 454 | public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec"; |
455 | 455 | ||
456 | /** | 456 | /** |
457 | + * Resource constants. | ||
458 | + */ | ||
459 | + public static final String RESOURCE_TABLE_NAME = "resource"; | ||
460 | + public static final String RESOURCE_TENANT_ID_COLUMN = TENANT_ID_COLUMN; | ||
461 | + public static final String RESOURCE_TYPE_COLUMN = "resource_type"; | ||
462 | + public static final String RESOURCE_ID_COLUMN = "resource_id"; | ||
463 | + public static final String RESOURCE_VALUE_COLUMN = "resource_value"; | ||
464 | + | ||
465 | + /** | ||
457 | * Cassandra attributes and timeseries constants. | 466 | * Cassandra attributes and timeseries constants. |
458 | */ | 467 | */ |
459 | public static final String ATTRIBUTES_KV_CF = "attributes_kv_cf"; | 468 | public static final String ATTRIBUTES_KV_CF = "attributes_kv_cf"; |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.model.sql; | ||
17 | + | ||
18 | +import lombok.AllArgsConstructor; | ||
19 | +import lombok.Data; | ||
20 | +import lombok.NoArgsConstructor; | ||
21 | +import org.thingsboard.server.common.data.relation.EntityRelation; | ||
22 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
23 | + | ||
24 | +import javax.persistence.Transient; | ||
25 | +import java.io.Serializable; | ||
26 | +import java.util.UUID; | ||
27 | + | ||
28 | +@NoArgsConstructor | ||
29 | +@AllArgsConstructor | ||
30 | +@Data | ||
31 | +public class ResourceCompositeKey implements Serializable { | ||
32 | + | ||
33 | + @Transient | ||
34 | + private static final long serialVersionUID = -3789469030818742769L; | ||
35 | + | ||
36 | + private UUID tenantId; | ||
37 | + private String resourceType; | ||
38 | + private String resourceId; | ||
39 | + | ||
40 | + public ResourceCompositeKey(Resource resource) { | ||
41 | + this.tenantId = resource.getTenantId().getId(); | ||
42 | + this.resourceType = resource.getResourceType().name(); | ||
43 | + this.resourceId = resource.getResourceId(); | ||
44 | + } | ||
45 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.model.sql; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.id.TenantId; | ||
20 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
21 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
22 | +import org.thingsboard.server.dao.model.ToData; | ||
23 | + | ||
24 | +import javax.persistence.Column; | ||
25 | +import javax.persistence.Entity; | ||
26 | +import javax.persistence.Id; | ||
27 | +import javax.persistence.IdClass; | ||
28 | +import javax.persistence.Table; | ||
29 | +import java.util.UUID; | ||
30 | + | ||
31 | +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_ID_COLUMN; | ||
32 | +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TABLE_NAME; | ||
33 | +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TENANT_ID_COLUMN; | ||
34 | +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_TYPE_COLUMN; | ||
35 | +import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_VALUE_COLUMN; | ||
36 | + | ||
37 | +@Data | ||
38 | +@Entity | ||
39 | +@Table(name = RESOURCE_TABLE_NAME) | ||
40 | +@IdClass(ResourceCompositeKey.class) | ||
41 | +public class ResourceEntity implements ToData<Resource> { | ||
42 | + | ||
43 | + @Id | ||
44 | + @Column(name = RESOURCE_TENANT_ID_COLUMN, columnDefinition = "uuid") | ||
45 | + private UUID tenantId; | ||
46 | + | ||
47 | + @Id | ||
48 | + @Column(name = RESOURCE_TYPE_COLUMN) | ||
49 | + private String resourceType; | ||
50 | + | ||
51 | + @Id | ||
52 | + @Column(name = RESOURCE_ID_COLUMN) | ||
53 | + private String resourceId; | ||
54 | + | ||
55 | + @Column(name = RESOURCE_VALUE_COLUMN) | ||
56 | + private String value; | ||
57 | + | ||
58 | + public ResourceEntity() { | ||
59 | + } | ||
60 | + | ||
61 | + public ResourceEntity(Resource resource) { | ||
62 | + this.tenantId = resource.getTenantId().getId(); | ||
63 | + this.resourceType = resource.getResourceType().name(); | ||
64 | + this.resourceId = resource.getResourceId(); | ||
65 | + this.value = resource.getValue(); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public Resource toData() { | ||
70 | + Resource resource = new Resource(); | ||
71 | + resource.setTenantId(new TenantId(tenantId)); | ||
72 | + resource.setResourceType(ResourceType.valueOf(resourceType)); | ||
73 | + resource.setResourceId(resourceId); | ||
74 | + resource.setValue(value); | ||
75 | + return resource; | ||
76 | + } | ||
77 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.resource; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.stereotype.Service; | ||
20 | +import org.thingsboard.server.common.data.id.TenantId; | ||
21 | +import org.thingsboard.server.common.data.page.PageData; | ||
22 | +import org.thingsboard.server.common.data.page.PageLink; | ||
23 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
24 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
25 | +import org.thingsboard.server.dao.exception.DataValidationException; | ||
26 | + | ||
27 | +import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID; | ||
28 | +import static org.thingsboard.server.dao.service.Validator.validateId; | ||
29 | + | ||
30 | +@Service | ||
31 | +@Slf4j | ||
32 | +public class BaseResourceService implements ResourceService { | ||
33 | + | ||
34 | + private final ResourceDao resourceDao; | ||
35 | + | ||
36 | + public BaseResourceService(ResourceDao resourceDao) { | ||
37 | + this.resourceDao = resourceDao; | ||
38 | + } | ||
39 | + | ||
40 | + @Override | ||
41 | + public Resource saveResource(Resource resource) { | ||
42 | + log.trace("Executing saveResource [{}]", resource); | ||
43 | + validate(resource); | ||
44 | + return resourceDao.saveResource(resource); | ||
45 | + } | ||
46 | + | ||
47 | + @Override | ||
48 | + public Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId) { | ||
49 | + log.trace("Executing getResource [{}] [{}] [{}]", tenantId, resourceType, resourceId); | ||
50 | + validate(tenantId, resourceType, resourceId); | ||
51 | + return resourceDao.getResource(tenantId, resourceType, resourceId); | ||
52 | + } | ||
53 | + | ||
54 | + @Override | ||
55 | + public void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { | ||
56 | + log.trace("Executing deleteResource [{}] [{}] [{}]", tenantId, resourceType, resourceId); | ||
57 | + validate(tenantId, resourceType, resourceId); | ||
58 | + resourceDao.deleteResource(tenantId, resourceType, resourceId); | ||
59 | + } | ||
60 | + | ||
61 | + @Override | ||
62 | + public PageData<Resource> findResourcesByTenantId(TenantId tenantId, PageLink pageLink) { | ||
63 | + log.trace("Executing findByTenantId [{}]", tenantId); | ||
64 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
65 | + return resourceDao.findAllByTenantId(tenantId, pageLink); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public void deleteResourcesByTenantId(TenantId tenantId) { | ||
70 | + log.trace("Executing deleteDevicesByTenantId, tenantId [{}]", tenantId); | ||
71 | + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); | ||
72 | + resourceDao.removeAllByTenantId(tenantId); | ||
73 | + } | ||
74 | + | ||
75 | + protected void validate(Resource resource) { | ||
76 | + if (resource == null) { | ||
77 | + throw new DataValidationException("Resource should be specified!"); | ||
78 | + } | ||
79 | + | ||
80 | + if (resource.getValue() == null) { | ||
81 | + throw new DataValidationException("Resource value should be specified!"); | ||
82 | + } | ||
83 | + validate(resource.getTenantId(), resource.getResourceType(), resource.getResourceId()); | ||
84 | + } | ||
85 | + | ||
86 | + protected void validate(TenantId tenantId, ResourceType resourceType, String resourceId) { | ||
87 | + if (resourceType == null) { | ||
88 | + throw new DataValidationException("Resource type should be specified!"); | ||
89 | + } | ||
90 | + if (resourceId == null) { | ||
91 | + throw new DataValidationException("Resource id should be specified!"); | ||
92 | + } | ||
93 | + validateId(tenantId, "Incorrect tenantId "); | ||
94 | + } | ||
95 | + | ||
96 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.resource; | ||
17 | + | ||
18 | +import org.thingsboard.server.common.data.id.TenantId; | ||
19 | +import org.thingsboard.server.common.data.page.PageData; | ||
20 | +import org.thingsboard.server.common.data.page.PageLink; | ||
21 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
22 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
23 | + | ||
24 | +public interface ResourceDao { | ||
25 | + | ||
26 | + Resource saveResource(Resource resource); | ||
27 | + | ||
28 | + Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId); | ||
29 | + | ||
30 | + void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId); | ||
31 | + | ||
32 | + PageData<Resource> findAllByTenantId(TenantId tenantId, PageLink pageLink); | ||
33 | + | ||
34 | + void removeAllByTenantId(TenantId tenantId); | ||
35 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.sql.resource; | ||
17 | + | ||
18 | +import lombok.extern.slf4j.Slf4j; | ||
19 | +import org.springframework.stereotype.Component; | ||
20 | +import org.springframework.transaction.annotation.Transactional; | ||
21 | +import org.thingsboard.server.common.data.id.TenantId; | ||
22 | +import org.thingsboard.server.common.data.page.PageData; | ||
23 | +import org.thingsboard.server.common.data.page.PageLink; | ||
24 | +import org.thingsboard.server.common.data.transport.resource.Resource; | ||
25 | +import org.thingsboard.server.common.data.transport.resource.ResourceType; | ||
26 | +import org.thingsboard.server.dao.DaoUtil; | ||
27 | +import org.thingsboard.server.dao.model.sql.ResourceCompositeKey; | ||
28 | +import org.thingsboard.server.dao.model.sql.ResourceEntity; | ||
29 | +import org.thingsboard.server.dao.resource.ResourceDao; | ||
30 | + | ||
31 | +@Slf4j | ||
32 | +@Component | ||
33 | +public class ResourceDaoImpl implements ResourceDao { | ||
34 | + | ||
35 | + private final ResourceRepository resourceRepository; | ||
36 | + | ||
37 | + public ResourceDaoImpl(ResourceRepository resourceRepository) { | ||
38 | + this.resourceRepository = resourceRepository; | ||
39 | + } | ||
40 | + | ||
41 | + @Override | ||
42 | + @Transactional | ||
43 | + public Resource saveResource(Resource resource) { | ||
44 | + return DaoUtil.getData(resourceRepository.save(new ResourceEntity(resource))); | ||
45 | + } | ||
46 | + | ||
47 | + @Override | ||
48 | + public Resource getResource(TenantId tenantId, ResourceType resourceType, String resourceId) { | ||
49 | + ResourceCompositeKey key = new ResourceCompositeKey(); | ||
50 | + key.setTenantId(tenantId.getId()); | ||
51 | + key.setResourceType(resourceType.name()); | ||
52 | + key.setResourceId(resourceId); | ||
53 | + | ||
54 | + return DaoUtil.getData(resourceRepository.findById(key)); | ||
55 | + } | ||
56 | + | ||
57 | + @Override | ||
58 | + @Transactional | ||
59 | + public void deleteResource(TenantId tenantId, ResourceType resourceType, String resourceId) { | ||
60 | + ResourceCompositeKey key = new ResourceCompositeKey(); | ||
61 | + key.setTenantId(tenantId.getId()); | ||
62 | + key.setResourceType(resourceType.name()); | ||
63 | + key.setResourceId(resourceId); | ||
64 | + | ||
65 | + resourceRepository.deleteById(key); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public PageData<Resource> findAllByTenantId(TenantId tenantId, PageLink pageLink) { | ||
70 | + return DaoUtil.toPageData(resourceRepository.findAllByTenantId(tenantId.getId(), DaoUtil.toPageable(pageLink))); | ||
71 | + } | ||
72 | + | ||
73 | + @Override | ||
74 | + public void removeAllByTenantId(TenantId tenantId) { | ||
75 | + resourceRepository.removeAllByTenantId(tenantId.getId()); | ||
76 | + } | ||
77 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2021 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.dao.sql.resource; | ||
17 | + | ||
18 | +import org.springframework.data.domain.Page; | ||
19 | +import org.springframework.data.domain.Pageable; | ||
20 | +import org.springframework.data.repository.CrudRepository; | ||
21 | +import org.thingsboard.server.dao.model.sql.ResourceCompositeKey; | ||
22 | +import org.thingsboard.server.dao.model.sql.ResourceEntity; | ||
23 | + | ||
24 | +import java.util.UUID; | ||
25 | + | ||
26 | +public interface ResourceRepository extends CrudRepository<ResourceEntity, ResourceCompositeKey> { | ||
27 | + | ||
28 | + Page<ResourceEntity> findAllByTenantId(UUID tenantId, Pageable pageable); | ||
29 | + | ||
30 | + void removeAllByTenantId(UUID tenantId); | ||
31 | +} |
@@ -35,6 +35,7 @@ import org.thingsboard.server.dao.device.DeviceService; | @@ -35,6 +35,7 @@ import org.thingsboard.server.dao.device.DeviceService; | ||
35 | import org.thingsboard.server.dao.entity.AbstractEntityService; | 35 | import org.thingsboard.server.dao.entity.AbstractEntityService; |
36 | import org.thingsboard.server.dao.entityview.EntityViewService; | 36 | import org.thingsboard.server.dao.entityview.EntityViewService; |
37 | import org.thingsboard.server.dao.exception.DataValidationException; | 37 | import org.thingsboard.server.dao.exception.DataValidationException; |
38 | +import org.thingsboard.server.dao.resource.ResourceService; | ||
38 | import org.thingsboard.server.dao.rule.RuleChainService; | 39 | import org.thingsboard.server.dao.rule.RuleChainService; |
39 | import org.thingsboard.server.dao.service.DataValidator; | 40 | import org.thingsboard.server.dao.service.DataValidator; |
40 | import org.thingsboard.server.dao.service.PaginatedRemover; | 41 | import org.thingsboard.server.dao.service.PaginatedRemover; |
@@ -88,6 +89,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | @@ -88,6 +89,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | ||
88 | @Autowired | 89 | @Autowired |
89 | private RuleChainService ruleChainService; | 90 | private RuleChainService ruleChainService; |
90 | 91 | ||
92 | + @Autowired | ||
93 | + private ResourceService resourceService; | ||
94 | + | ||
91 | @Override | 95 | @Override |
92 | public Tenant findTenantById(TenantId tenantId) { | 96 | public Tenant findTenantById(TenantId tenantId) { |
93 | log.trace("Executing findTenantById [{}]", tenantId); | 97 | log.trace("Executing findTenantById [{}]", tenantId); |
@@ -140,6 +144,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | @@ -140,6 +144,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe | ||
140 | userService.deleteTenantAdmins(tenantId); | 144 | userService.deleteTenantAdmins(tenantId); |
141 | ruleChainService.deleteRuleChainsByTenantId(tenantId); | 145 | ruleChainService.deleteRuleChainsByTenantId(tenantId); |
142 | apiUsageStateService.deleteApiUsageStateByTenantId(tenantId); | 146 | apiUsageStateService.deleteApiUsageStateByTenantId(tenantId); |
147 | + resourceService.deleteResourcesByTenantId(tenantId); | ||
143 | tenantDao.removeById(tenantId, tenantId.getId()); | 148 | tenantDao.removeById(tenantId, tenantId.getId()); |
144 | deleteEntityRelations(tenantId, tenantId); | 149 | deleteEntityRelations(tenantId, tenantId); |
145 | } | 150 | } |
@@ -420,3 +420,11 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( | @@ -420,3 +420,11 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( | ||
420 | sms_exec varchar(32), | 420 | sms_exec varchar(32), |
421 | CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) | 421 | CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) |
422 | ); | 422 | ); |
423 | + | ||
424 | +CREATE TABLE IF NOT EXISTS resource ( | ||
425 | + tenant_id uuid NOT NULL, | ||
426 | + resource_type varchar(32) NOT NULL, | ||
427 | + resource_id varchar(255) NOT NULL, | ||
428 | + resource_value varchar, | ||
429 | + CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id) | ||
430 | +); |
@@ -447,6 +447,14 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( | @@ -447,6 +447,14 @@ CREATE TABLE IF NOT EXISTS api_usage_state ( | ||
447 | CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) | 447 | CONSTRAINT api_usage_state_unq_key UNIQUE (tenant_id, entity_id) |
448 | ); | 448 | ); |
449 | 449 | ||
450 | +CREATE TABLE IF NOT EXISTS resource ( | ||
451 | + tenant_id uuid NOT NULL, | ||
452 | + resource_type varchar(32) NOT NULL, | ||
453 | + resource_id varchar(255) NOT NULL, | ||
454 | + resource_value varchar, | ||
455 | + CONSTRAINT resource_unq_key UNIQUE (tenant_id, resource_type, resource_id) | ||
456 | +); | ||
457 | + | ||
450 | CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) | 458 | CREATE OR REPLACE PROCEDURE cleanup_events_by_ttl(IN ttl bigint, IN debug_ttl bigint, INOUT deleted bigint) |
451 | LANGUAGE plpgsql AS | 459 | LANGUAGE plpgsql AS |
452 | $$ | 460 | $$ |
@@ -28,4 +28,5 @@ DROP TABLE IF EXISTS oauth2_client_registration; | @@ -28,4 +28,5 @@ DROP TABLE IF EXISTS oauth2_client_registration; | ||
28 | DROP TABLE IF EXISTS oauth2_client_registration_info; | 28 | DROP TABLE IF EXISTS oauth2_client_registration_info; |
29 | DROP TABLE IF EXISTS oauth2_client_registration_template; | 29 | DROP TABLE IF EXISTS oauth2_client_registration_template; |
30 | DROP TABLE IF EXISTS api_usage_state; | 30 | DROP TABLE IF EXISTS api_usage_state; |
31 | +DROP TABLE IF EXISTS resource; | ||
31 | DROP FUNCTION IF EXISTS to_uuid; | 32 | DROP FUNCTION IF EXISTS to_uuid; |
@@ -28,4 +28,5 @@ DROP TABLE IF EXISTS tb_schema_settings; | @@ -28,4 +28,5 @@ DROP TABLE IF EXISTS tb_schema_settings; | ||
28 | DROP TABLE IF EXISTS oauth2_client_registration; | 28 | DROP TABLE IF EXISTS oauth2_client_registration; |
29 | DROP TABLE IF EXISTS oauth2_client_registration_info; | 29 | DROP TABLE IF EXISTS oauth2_client_registration_info; |
30 | DROP TABLE IF EXISTS oauth2_client_registration_template; | 30 | DROP TABLE IF EXISTS oauth2_client_registration_template; |
31 | -DROP TABLE IF EXISTS api_usage_state; | ||
31 | +DROP TABLE IF EXISTS api_usage_state; | ||
32 | +DROP TABLE IF EXISTS resource; |