Commit 1f6c0c54cd0186b24a6d1a55cc08ca659698beed

Authored by Andrii Shvaika
2 parents ddfa10a6 9ab92ba7

Merge with Yevhen branch

... ... @@ -115,7 +115,7 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService {
115 115 } finally {
116 116 updateLock.unlock();
117 117 }
118   - tsService.save(tenantId, tenantState.getEntityId(), updatedEntries, 0L);
  118 + tsService.save(tenantId, tenantState.getApiUsageState().getId(), updatedEntries, 0L);
119 119 if (stateUpdated) {
120 120 // Save new state into the database;
121 121 apiUsageStateService.update(tenantState.getApiUsageState());
... ...
... ... @@ -102,14 +102,18 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
102 102
103 103 protected volatile ExecutorService usageStatsExecutor;
104 104
105   -
106   - public DefaultTbCoreConsumerService(TbCoreQueueFactory tbCoreQueueFactory, ActorSystemContext actorContext,
107   - DeviceStateService stateService, TbLocalSubscriptionService localSubscriptionService,
  105 + public DefaultTbCoreConsumerService(TbCoreQueueFactory tbCoreQueueFactory,
  106 + ActorSystemContext actorContext,
  107 + DeviceStateService stateService,
  108 + TbLocalSubscriptionService localSubscriptionService,
  109 + SubscriptionManagerService subscriptionManagerService,
  110 + DataDecodingEncodingService encodingService,
  111 + TbCoreDeviceRpcService tbCoreDeviceRpcService,
  112 + StatsFactory statsFactory,
  113 + TbDeviceProfileCache deviceProfileCache,
  114 + TbApiUsageStateService statsService,
108 115 TbTenantProfileCache tenantProfileCache,
109   - TbApiUsageStateService apiUsageStateService,
110   - SubscriptionManagerService subscriptionManagerService, DataDecodingEncodingService encodingService,
111   - TbCoreDeviceRpcService tbCoreDeviceRpcService, StatsFactory statsFactory, TbDeviceProfileCache deviceProfileCache,
112   - TbApiUsageStateService statsService) {
  116 + TbApiUsageStateService apiUsageStateService) {
113 117 super(actorContext, encodingService, tenantProfileCache, deviceProfileCache, apiUsageStateService, tbCoreQueueFactory.createToCoreNotificationsMsgConsumer());
114 118 this.mainConsumer = tbCoreQueueFactory.createToCoreMsgConsumer();
115 119 this.usageStatsConsumer = tbCoreQueueFactory.createToUsageStatsServiceMsgConsumer();
... ... @@ -399,6 +403,9 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService<ToCore
399 403 if (mainConsumer != null) {
400 404 mainConsumer.unsubscribe();
401 405 }
  406 + if (usageStatsConsumer != null) {
  407 + usageStatsConsumer.unsubscribe();
  408 + }
402 409 }
403 410
404 411 }
... ...
... ... @@ -24,8 +24,15 @@ import org.thingsboard.rule.engine.api.RpcError;
24 24 import org.thingsboard.server.actors.ActorSystemContext;
25 25 import org.thingsboard.server.common.data.id.TenantId;
26 26 import org.thingsboard.server.common.msg.TbMsg;
27   -import org.thingsboard.server.common.msg.queue.*;
  27 +import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;
  28 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  29 +import org.thingsboard.server.common.msg.queue.RuleNodeInfo;
  30 +import org.thingsboard.server.common.msg.queue.ServiceQueue;
  31 +import org.thingsboard.server.common.msg.queue.ServiceType;
  32 +import org.thingsboard.server.common.msg.queue.TbCallback;
  33 +import org.thingsboard.server.common.msg.queue.TbMsgCallback;
28 34 import org.thingsboard.server.common.stats.StatsFactory;
  35 +import org.thingsboard.server.common.transport.util.DataDecodingEncodingService;
29 36 import org.thingsboard.server.gen.transport.TransportProtos;
30 37 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
31 38 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineNotificationMsg;
... ... @@ -36,19 +43,33 @@ import org.thingsboard.server.queue.provider.TbRuleEngineQueueFactory;
36 43 import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings;
37 44 import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration;
38 45 import org.thingsboard.server.queue.util.TbRuleEngineComponent;
39   -import org.thingsboard.server.common.transport.util.DataDecodingEncodingService;
40 46 import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
41 47 import org.thingsboard.server.service.profile.TbDeviceProfileCache;
42 48 import org.thingsboard.server.service.profile.TbTenantProfileCache;
43   -import org.thingsboard.server.service.queue.processing.*;
  49 +import org.thingsboard.server.service.queue.processing.AbstractConsumerService;
  50 +import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingDecision;
  51 +import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingResult;
  52 +import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategy;
  53 +import org.thingsboard.server.service.queue.processing.TbRuleEngineProcessingStrategyFactory;
  54 +import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategy;
  55 +import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrategyFactory;
44 56 import org.thingsboard.server.service.rpc.FromDeviceRpcResponse;
45 57 import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService;
46 58 import org.thingsboard.server.service.stats.RuleEngineStatisticsService;
47 59
48 60 import javax.annotation.PostConstruct;
49 61 import javax.annotation.PreDestroy;
50   -import java.util.*;
51   -import java.util.concurrent.*;
  62 +import java.util.Collections;
  63 +import java.util.HashSet;
  64 +import java.util.List;
  65 +import java.util.Map;
  66 +import java.util.Set;
  67 +import java.util.UUID;
  68 +import java.util.concurrent.ConcurrentHashMap;
  69 +import java.util.concurrent.ConcurrentMap;
  70 +import java.util.concurrent.ExecutorService;
  71 +import java.util.concurrent.Executors;
  72 +import java.util.concurrent.TimeUnit;
52 73
53 74 @Service
54 75 @TbRuleEngineComponent
... ... @@ -79,12 +100,15 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService<
79 100 public DefaultTbRuleEngineConsumerService(TbRuleEngineProcessingStrategyFactory processingStrategyFactory,
80 101 TbRuleEngineSubmitStrategyFactory submitStrategyFactory,
81 102 TbQueueRuleEngineSettings ruleEngineSettings,
82   - TbTenantProfileCache tenantProfileCache,
83   - TbApiUsageStateService apiUsageStateService,
84   - TbRuleEngineQueueFactory tbRuleEngineQueueFactory, RuleEngineStatisticsService statisticsService,
85   - ActorSystemContext actorContext, DataDecodingEncodingService encodingService,
  103 + TbRuleEngineQueueFactory tbRuleEngineQueueFactory,
  104 + RuleEngineStatisticsService statisticsService,
  105 + ActorSystemContext actorContext,
  106 + DataDecodingEncodingService encodingService,
86 107 TbRuleEngineDeviceRpcService tbDeviceRpcService,
87   - StatsFactory statsFactory, TbDeviceProfileCache deviceProfileCache) {
  108 + StatsFactory statsFactory,
  109 + TbDeviceProfileCache deviceProfileCache,
  110 + TbTenantProfileCache tenantProfileCache,
  111 + TbApiUsageStateService apiUsageStateService) {
88 112 super(actorContext, encodingService, tenantProfileCache, deviceProfileCache, apiUsageStateService, tbRuleEngineQueueFactory.createToRuleEngineNotificationsMsgConsumer());
89 113 this.statisticsService = statisticsService;
90 114 this.ruleEngineSettings = ruleEngineSettings;
... ...
... ... @@ -25,6 +25,7 @@ import org.springframework.http.ResponseEntity;
25 25 import org.springframework.stereotype.Component;
26 26 import org.springframework.web.context.request.async.DeferredResult;
27 27 import org.thingsboard.common.util.ThingsBoardThreadFactory;
  28 +import org.thingsboard.server.common.data.ApiUsageState;
28 29 import org.thingsboard.server.common.data.Customer;
29 30 import org.thingsboard.server.common.data.Device;
30 31 import org.thingsboard.server.common.data.DeviceProfile;
... ... @@ -33,6 +34,7 @@ import org.thingsboard.server.common.data.Tenant;
33 34 import org.thingsboard.server.common.data.User;
34 35 import org.thingsboard.server.common.data.asset.Asset;
35 36 import org.thingsboard.server.common.data.exception.ThingsboardException;
  37 +import org.thingsboard.server.common.data.id.ApiUsageStateId;
36 38 import org.thingsboard.server.common.data.id.AssetId;
37 39 import org.thingsboard.server.common.data.id.CustomerId;
38 40 import org.thingsboard.server.common.data.id.DeviceId;
... ... @@ -55,6 +57,7 @@ import org.thingsboard.server.dao.device.DeviceService;
55 57 import org.thingsboard.server.dao.entityview.EntityViewService;
56 58 import org.thingsboard.server.dao.rule.RuleChainService;
57 59 import org.thingsboard.server.dao.tenant.TenantService;
  60 +import org.thingsboard.server.dao.usagerecord.ApiUsageStateService;
58 61 import org.thingsboard.server.dao.user.UserService;
59 62 import org.thingsboard.server.service.security.model.SecurityUser;
60 63 import org.thingsboard.server.service.security.permission.AccessControlService;
... ... @@ -111,6 +114,9 @@ public class AccessValidator {
111 114 @Autowired
112 115 protected AccessControlService accessControlService;
113 116
  117 + @Autowired
  118 + protected ApiUsageStateService apiUsageStateService;
  119 +
114 120 private ExecutorService executor;
115 121
116 122 @PostConstruct
... ... @@ -193,6 +199,9 @@ public class AccessValidator {
193 199 case ENTITY_VIEW:
194 200 validateEntityView(currentUser, operation, entityId, callback);
195 201 return;
  202 + case API_USAGE_STATE:
  203 + validateApiUsageState(currentUser, operation, entityId, callback);
  204 + return;
196 205 default:
197 206 //TODO: add support of other entities
198 207 throw new IllegalStateException("Not Implemented!");
... ... @@ -237,6 +246,27 @@ public class AccessValidator {
237 246 }
238 247 }
239 248
  249 + private void validateApiUsageState(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
  250 + if (currentUser.isSystemAdmin()) {
  251 + callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
  252 + } else {
  253 + if (!operation.equals(Operation.READ_TELEMETRY)) {
  254 + callback.onSuccess(ValidationResult.accessDenied("Allowed only READ_TELEMETRY operation!"));
  255 + }
  256 + ApiUsageState apiUsageState = apiUsageStateService.findApiUsageStateById(currentUser.getTenantId(), new ApiUsageStateId(entityId.getId()));
  257 + if (apiUsageState == null) {
  258 + callback.onSuccess(ValidationResult.entityNotFound("Api Usage State with requested id wasn't found!"));
  259 + } else {
  260 + try {
  261 + accessControlService.checkPermission(currentUser, Resource.API_USAGE_STATE, operation, entityId, apiUsageState);
  262 + } catch (ThingsboardException e) {
  263 + callback.onSuccess(ValidationResult.accessDenied(e.getMessage()));
  264 + }
  265 + callback.onSuccess(ValidationResult.ok(apiUsageState));
  266 + }
  267 + }
  268 + }
  269 +
240 270 private void validateAsset(final SecurityUser currentUser, Operation operation, EntityId entityId, FutureCallback<ValidationResult> callback) {
241 271 if (currentUser.isSystemAdmin()) {
242 272 callback.onSuccess(ValidationResult.accessDenied(SYSTEM_ADMINISTRATOR_IS_NOT_ALLOWED_TO_PERFORM_THIS_OPERATION));
... ...
... ... @@ -35,7 +35,8 @@ public enum Resource {
35 35 OAUTH2_CONFIGURATION_INFO(),
36 36 OAUTH2_CONFIGURATION_TEMPLATE(),
37 37 TENANT_PROFILE(EntityType.TENANT_PROFILE),
38   - DEVICE_PROFILE(EntityType.DEVICE_PROFILE);
  38 + DEVICE_PROFILE(EntityType.DEVICE_PROFILE),
  39 + API_USAGE_STATE(EntityType.API_USAGE_STATE);
39 40
40 41 private final EntityType entityType;
41 42
... ...
... ... @@ -40,6 +40,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
40 40 put(Resource.WIDGETS_BUNDLE, widgetsPermissionChecker);
41 41 put(Resource.WIDGET_TYPE, widgetsPermissionChecker);
42 42 put(Resource.DEVICE_PROFILE, tenantEntityPermissionChecker);
  43 + put(Resource.API_USAGE_STATE, tenantEntityPermissionChecker);
43 44 }
44 45
45 46 public static final PermissionChecker tenantEntityPermissionChecker = new PermissionChecker() {
... ...
... ... @@ -16,6 +16,7 @@
16 16 package org.thingsboard.server.dao.usagerecord;
17 17
18 18 import org.thingsboard.server.common.data.ApiUsageState;
  19 +import org.thingsboard.server.common.data.id.ApiUsageStateId;
19 20 import org.thingsboard.server.common.data.id.TenantId;
20 21
21 22 public interface ApiUsageStateService {
... ... @@ -28,4 +29,5 @@ public interface ApiUsageStateService {
28 29
29 30 void deleteApiUsageStateByTenantId(TenantId tenantId);
30 31
  32 + ApiUsageState findApiUsageStateById(TenantId tenantId, ApiUsageStateId id);
31 33 }
... ...
... ... @@ -66,6 +66,8 @@ public class EntityIdFactory {
66 66 return new DeviceProfileId(uuid);
67 67 case TENANT_PROFILE:
68 68 return new TenantProfileId(uuid);
  69 + case API_USAGE_STATE:
  70 + return new ApiUsageStateId(uuid);
69 71 }
70 72 throw new IllegalArgumentException("EntityType " + type + " is not supported!");
71 73 }
... ...
  1 +/**
  2 + * Copyright © 2016-2020 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.query;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.id.EntityId;
  20 +
  21 +@Data
  22 +public class ApiUsageStateFilter implements EntityFilter {
  23 + @Override
  24 + public EntityFilterType getType() {
  25 + return EntityFilterType.API_USAGE_STATE;
  26 + }
  27 +
  28 +}
... ...
... ... @@ -32,6 +32,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
32 32 @JsonSubTypes.Type(value = AssetTypeFilter.class, name = "assetType"),
33 33 @JsonSubTypes.Type(value = DeviceTypeFilter.class, name = "deviceType"),
34 34 @JsonSubTypes.Type(value = EntityViewTypeFilter.class, name = "entityViewType"),
  35 + @JsonSubTypes.Type(value = ApiUsageStateFilter.class, name = "apiUsageState"),
35 36 @JsonSubTypes.Type(value = RelationsQueryFilter.class, name = "relationsQuery"),
36 37 @JsonSubTypes.Type(value = AssetSearchQueryFilter.class, name = "assetSearchQuery"),
37 38 @JsonSubTypes.Type(value = DeviceSearchQueryFilter.class, name = "deviceSearchQuery"),
... ...
... ... @@ -25,7 +25,8 @@ public enum EntityFilterType {
25 25 RELATIONS_QUERY("relationsQuery"),
26 26 ASSET_SEARCH_QUERY("assetSearchQuery"),
27 27 DEVICE_SEARCH_QUERY("deviceSearchQuery"),
28   - ENTITY_VIEW_SEARCH_QUERY("entityViewSearchQuery");
  28 + ENTITY_VIEW_SEARCH_QUERY("entityViewSearchQuery"),
  29 + API_USAGE_STATE("apiUsageState");
29 30
30 31 private final String label;
31 32
... ...
... ... @@ -210,6 +210,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
210 210 entityTableMap.put(EntityType.CUSTOMER, "customer");
211 211 entityTableMap.put(EntityType.USER, "tb_user");
212 212 entityTableMap.put(EntityType.TENANT, "tenant");
  213 + entityTableMap.put(EntityType.API_USAGE_STATE, "(select aus.id, aus.created_time, aus.tenant_id, '' as name, '' as additional_info from api_usage_state as aus)");
213 214 }
214 215
215 216 public static EntityType[] RELATION_QUERY_ENTITY_TYPES = new EntityType[]{
... ... @@ -431,6 +432,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
431 432 case DEVICE_SEARCH_QUERY:
432 433 case ASSET_SEARCH_QUERY:
433 434 case ENTITY_VIEW_SEARCH_QUERY:
  435 + case API_USAGE_STATE:
434 436 return "";
435 437 default:
436 438 throw new RuntimeException("Not implemented!");
... ... @@ -682,6 +684,8 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
682 684 return EntityType.ENTITY_VIEW;
683 685 case RELATIONS_QUERY:
684 686 return ((RelationsQueryFilter) entityFilter).getRootEntity().getEntityType();
  687 + case API_USAGE_STATE:
  688 + return EntityType.API_USAGE_STATE;
685 689 default:
686 690 throw new RuntimeException("Not implemented!");
687 691 }
... ...
... ... @@ -20,6 +20,7 @@ import org.springframework.stereotype.Service;
20 20 import org.thingsboard.server.common.data.EntityType;
21 21 import org.thingsboard.server.common.data.Tenant;
22 22 import org.thingsboard.server.common.data.ApiUsageState;
  23 +import org.thingsboard.server.common.data.id.ApiUsageStateId;
23 24 import org.thingsboard.server.common.data.id.TenantId;
24 25 import org.thingsboard.server.dao.entity.AbstractEntityService;
25 26 import org.thingsboard.server.dao.exception.DataValidationException;
... ... @@ -74,6 +75,13 @@ public class ApiApiUsageStateServiceImpl extends AbstractEntityService implement
74 75 return apiUsageStateDao.findTenantApiUsageState(tenantId.getId());
75 76 }
76 77
  78 + @Override
  79 + public ApiUsageState findApiUsageStateById(TenantId tenantId, ApiUsageStateId id) {
  80 + log.trace("Executing findApiUsageStateById, tenantId [{}], apiUsageStateId [{}]", tenantId, id);
  81 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  82 + validateId(id, "Incorrect apiUsageStateId " + id);
  83 + return apiUsageStateDao.findById(tenantId, id.getId()); }
  84 +
77 85 private DataValidator<ApiUsageState> apiUsageStateValidator =
78 86 new DataValidator<ApiUsageState>() {
79 87 @Override
... ...
... ... @@ -753,6 +753,9 @@ export class EntityService {
753 753 case AliasFilterType.entityViewType:
754 754 result.entityFilter = deepClone(filter);
755 755 return of(result);
  756 + case AliasFilterType.apiUsageState:
  757 + result.entityFilter = deepClone(filter);
  758 + return of(result);
756 759 case AliasFilterType.relationsQuery:
757 760 result.stateEntity = filter.rootStateEntity;
758 761 let rootEntityType;
... ...
... ... @@ -28,6 +28,7 @@ export enum AliasFilterType {
28 28 assetType = 'assetType',
29 29 deviceType = 'deviceType',
30 30 entityViewType = 'entityViewType',
  31 + apiUsageState = 'apiUsageState',
31 32 relationsQuery = 'relationsQuery',
32 33 assetSearchQuery = 'assetSearchQuery',
33 34 deviceSearchQuery = 'deviceSearchQuery',
... ... @@ -43,6 +44,7 @@ export const aliasFilterTypeTranslationMap = new Map<AliasFilterType, string>(
43 44 [ AliasFilterType.assetType, 'alias.filter-type-asset-type' ],
44 45 [ AliasFilterType.deviceType, 'alias.filter-type-device-type' ],
45 46 [ AliasFilterType.entityViewType, 'alias.filter-type-entity-view-type' ],
  47 + [ AliasFilterType.apiUsageState, 'alias.filter-type-apiUsageState' ],
46 48 [ AliasFilterType.relationsQuery, 'alias.filter-type-relations-query' ],
47 49 [ AliasFilterType.assetSearchQuery, 'alias.filter-type-asset-search-query' ],
48 50 [ AliasFilterType.deviceSearchQuery, 'alias.filter-type-device-search-query' ],
... ... @@ -106,6 +108,10 @@ export interface EntitySearchQueryFilter {
106 108 fetchLastLevelOnly?: boolean;
107 109 }
108 110
  111 +export interface ApiUsageStateFilter {
  112 +
  113 +}
  114 +
109 115 export interface AssetSearchQueryFilter extends EntitySearchQueryFilter {
110 116 assetTypes?: string[];
111 117 }
... ... @@ -129,7 +135,8 @@ export type EntityFilters =
129 135 RelationsQueryFilter &
130 136 AssetSearchQueryFilter &
131 137 DeviceSearchQueryFilter &
132   - EntityViewSearchQueryFilter;
  138 + EntityViewSearchQueryFilter &
  139 + EntitySearchQueryFilter;
133 140
134 141 export interface EntityAliasFilter extends EntityFilters {
135 142 type?: AliasFilterType;
... ...
... ... @@ -288,6 +288,7 @@
288 288 "filter-type-device-search-query-description": "Devices with types {{deviceTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
289 289 "filter-type-entity-view-search-query": "Entity view search query",
290 290 "filter-type-entity-view-search-query-description": "Entity views with types {{entityViewTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}",
  291 + "filter-type-apiUsageState": "Api Usage State",
291 292 "entity-filter": "Entity filter",
292 293 "resolve-multiple": "Resolve as multiple entities",
293 294 "filter-type": "Filter type",
... ...