From 92ba5907b0e8fb335e6562d636a3bcb627099f92 Mon Sep 17 00:00:00 2001 From: zbeacon Date: Tue, 3 Nov 2020 16:51:41 +0200 Subject: [PATCH 01/23] Added validation for deviceName/attribute key contains only spaces situation --- .../thingsboard/server/controller/TelemetryController.java | 5 +++++ .../org/thingsboard/server/dao/device/DeviceServiceImpl.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index af4eb0f08f..e8c4756a6f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -393,6 +393,11 @@ public class TelemetryController extends BaseController { if (attributes.isEmpty()) { return getImmediateDeferredResult("No attributes data found in request body!", HttpStatus.BAD_REQUEST); } + for (AttributeKvEntry attributeKvEntry: attributes) { + if (attributeKvEntry.getKey().isEmpty() || attributeKvEntry.getKey().trim().length() == 0) { + return getImmediateDeferredResult("Key cannot be empty or contains only spaces", HttpStatus.BAD_REQUEST); + } + } SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_ATTRIBUTES, entityIdSrc, (result, tenantId, entityId) -> { tsSubService.saveAndNotify(tenantId, entityId, scope, attributes, new FutureCallback() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index cb6d74cf10..8d29b9c447 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -388,7 +388,7 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe if (StringUtils.isEmpty(device.getType())) { throw new DataValidationException("Device type should be specified!"); } - if (StringUtils.isEmpty(device.getName())) { + if (StringUtils.isEmpty(device.getName()) || device.getName().trim().length() == 0) { throw new DataValidationException("Device name should be specified!"); } if (device.getTenantId() == null) { From 580c8aef51a355254ba14eff88974fee83e12f13 Mon Sep 17 00:00:00 2001 From: zbeacon Date: Fri, 30 Oct 2020 14:28:30 +0200 Subject: [PATCH 02/23] Added handler for too long payload exception in MQTT transport --- .../server/transport/mqtt/MqttTransportHandler.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index 5d24f812eb..abb8f629f1 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -115,7 +115,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement log.trace("[{}] Processing msg: {}", sessionId, msg); try { if (msg instanceof MqttMessage) { - processMqttMsg(ctx, (MqttMessage) msg); + MqttMessage message = (MqttMessage) msg; + if (message.decoderResult().isSuccess()) { + processMqttMsg(ctx, message); + } else { + log.error("[{}] Message processing failed: {}", sessionId, message.decoderResult().cause().getMessage()); + ctx.close(); + } } else { ctx.close(); } From f6e9959ca5e215a61c5b8029c203dd166e1d5c9e Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Wed, 11 Nov 2020 12:22:00 +0200 Subject: [PATCH 03/23] Minor improvements --- .../DefaultSystemDataLoaderService.java | 3 --- .../usagestats/DefaultTbApiUsageClient.java | 4 +++- .../transport/mqtt/MqttTransportHandler.java | 6 +++-- .../DefaultTransportRateLimitService.java | 24 ++++++++++++++----- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index fd757ed6dd..6c7678f023 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -134,7 +134,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { TenantProfile isolatedTbCoreProfile = new TenantProfile(); isolatedTbCoreProfile.setDefault(false); isolatedTbCoreProfile.setName("Isolated TB Core"); - isolatedTbCoreProfile.setProfileData(new TenantProfileData()); isolatedTbCoreProfile.setDescription("Isolated TB Core tenant profile"); isolatedTbCoreProfile.setIsolatedTbCore(true); isolatedTbCoreProfile.setIsolatedTbRuleEngine(false); @@ -148,7 +147,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { TenantProfile isolatedTbRuleEngineProfile = new TenantProfile(); isolatedTbRuleEngineProfile.setDefault(false); isolatedTbRuleEngineProfile.setName("Isolated TB Rule Engine"); - isolatedTbRuleEngineProfile.setProfileData(new TenantProfileData()); isolatedTbRuleEngineProfile.setDescription("Isolated TB Rule Engine tenant profile"); isolatedTbRuleEngineProfile.setIsolatedTbCore(false); isolatedTbRuleEngineProfile.setIsolatedTbRuleEngine(true); @@ -163,7 +161,6 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { TenantProfile isolatedTbCoreAndTbRuleEngineProfile = new TenantProfile(); isolatedTbCoreAndTbRuleEngineProfile.setDefault(false); isolatedTbCoreAndTbRuleEngineProfile.setName("Isolated TB Core and TB Rule Engine"); - isolatedTbCoreAndTbRuleEngineProfile.setProfileData(new TenantProfileData()); isolatedTbCoreAndTbRuleEngineProfile.setDescription("Isolated TB Core and TB Rule Engine tenant profile"); isolatedTbCoreAndTbRuleEngineProfile.setIsolatedTbCore(true); isolatedTbCoreAndTbRuleEngineProfile.setIsolatedTbRuleEngine(true); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageClient.java b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageClient.java index 0702322838..5c5b593d96 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageClient.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageClient.java @@ -94,7 +94,9 @@ public class DefaultTbApiUsageClient implements TbApiUsageClient { TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, tenantId).newByTopic(msgProducer.getDefaultTopic()); msgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), builder.build()), null); })); - log.info("Report statistics for: {} tenants", report.size()); + if (!report.isEmpty()) { + log.info("Report statistics for: {} tenants", report.size()); + } } catch (Exception e) { log.warn("Failed to report statistics: ", e); } diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index 14712a7cb3..024e42f9ac 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -464,8 +464,10 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement String userName = msg.payload().userName(); log.info("[{}] Processing connect msg for client with user name: {}!", sessionId, userName); TransportProtos.ValidateBasicMqttCredRequestMsg.Builder request = TransportProtos.ValidateBasicMqttCredRequestMsg.newBuilder() - .setClientId(msg.payload().clientIdentifier()) - .setUserName(userName); + .setClientId(msg.payload().clientIdentifier()); + if (userName != null) { + request.setUserName(userName); + } String password = msg.payload().password(); if (password != null) { request.setPassword(password); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java index b6f160ad1e..6dc1db0fc2 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java @@ -21,6 +21,7 @@ import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; @@ -77,6 +78,7 @@ public class DefaultTransportRateLimitService implements TransportRateLimitServi @Override public void update(TenantProfileUpdateResult update) { + log.info("Received tenant profile update: {}", update.getProfile()); EntityTransportRateLimits tenantRateLimitPrototype = createRateLimits(update.getProfile(), true); EntityTransportRateLimits deviceRateLimitPrototype = createRateLimits(update.getProfile(), false); for (TenantId tenantId : update.getAffectedTenants()) { @@ -114,16 +116,26 @@ public class DefaultTransportRateLimitService implements TransportRateLimitServi tenantAllowed.put(tenantId, allowed); } - private void mergeLimits(T deviceId, EntityTransportRateLimits newRateLimits, - Function getFunction, - BiConsumer putFunction) { - EntityTransportRateLimits oldRateLimits = getFunction.apply(deviceId); + private void mergeLimits(T entityId, EntityTransportRateLimits newRateLimits, + Function getFunction, + BiConsumer putFunction) { + EntityTransportRateLimits oldRateLimits = getFunction.apply(entityId); if (oldRateLimits == null) { - putFunction.accept(deviceId, newRateLimits); + if (EntityType.TENANT.equals(entityId.getEntityType())) { + log.info("[{}] New rate limits: {}", entityId, newRateLimits); + } else { + log.debug("[{}] New rate limits: {}", entityId, newRateLimits); + } + putFunction.accept(entityId, newRateLimits); } else { EntityTransportRateLimits updated = merge(oldRateLimits, newRateLimits); if (updated != null) { - putFunction.accept(deviceId, updated); + if (EntityType.TENANT.equals(entityId.getEntityType())) { + log.info("[{}] Updated rate limits: {}", entityId, updated); + } else { + log.debug("[{}] Updated rate limits: {}", entityId, updated); + } + putFunction.accept(entityId, updated); } } } From f157d07c1f4e1550155159a383bc934964ba6f05 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Wed, 11 Nov 2020 12:45:14 +0200 Subject: [PATCH 04/23] Improvements --- .../apiusage/DefaultTbApiUsageStateService.java | 11 +++++++---- .../server/service/queue/DefaultTbClusterService.java | 1 + application/src/main/resources/thingsboard.yml | 1 - 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java index 0dcef2c88d..d7b96c78be 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java @@ -221,6 +221,7 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { @Override public void onTenantProfileUpdate(TenantProfileId tenantProfileId) { + log.info("[{}] On Tenant Profile Update", tenantProfileId); TenantProfile tenantProfile = tenantProfileCache.get(tenantProfileId); updateLock.lock(); try { @@ -236,6 +237,7 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { @Override public void onTenantUpdate(TenantId tenantId) { + log.info("[{}] On Tenant Update", tenantId); TenantProfile tenantProfile = tenantProfileCache.get(tenantId); updateLock.lock(); try { @@ -248,16 +250,17 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { } } - private void updateTenantState(TenantApiUsageState state, TenantProfile tenantProfile) { + private void updateTenantState(TenantApiUsageState state, TenantProfile profile) { + log.info("[{}] On Tenant Update.", state.getTenantId()); TenantProfileData oldProfileData = state.getTenantProfileData(); - state.setTenantProfileId(tenantProfile.getId()); - state.setTenantProfileData(tenantProfile.getProfileData()); + state.setTenantProfileId(profile.getId()); + state.setTenantProfileData(profile.getProfileData()); Map result = state.checkStateUpdatedDueToThresholds(); if (!result.isEmpty()) { persistAndNotify(state, result); } updateProfileThresholds(state.getTenantId(), state.getApiUsageState().getId(), - oldProfileData.getConfiguration(), tenantProfile.getProfileData().getConfiguration()); + oldProfileData.getConfiguration(), profile.getProfileData().getConfiguration()); } private void updateProfileThresholds(TenantId tenantId, ApiUsageStateId id, diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java index 18f064b745..edd53c6727 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbClusterService.java @@ -274,6 +274,7 @@ public class DefaultTbClusterService implements TbClusterService { TbQueueProducer> toRuleEngineProducer = producerProvider.getRuleEngineNotificationsMsgProducer(); Set tbRuleEngineServices = new HashSet<>(partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE)); if (msg.getEntityId().getEntityType().equals(EntityType.TENANT) + || msg.getEntityId().getEntityType().equals(EntityType.TENANT_PROFILE) || msg.getEntityId().getEntityType().equals(EntityType.DEVICE_PROFILE) || msg.getEntityId().getEntityType().equals(EntityType.API_USAGE_STATE)) { TbQueueProducer> toCoreNfProducer = producerProvider.getTbCoreNotificationsMsgProducer(); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index f0f4b9dd54..2766793acc 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -766,7 +766,6 @@ metrics: # Metrics percentiles returned by actuator for timer metrics. List of double values (divided by ,). percentiles: "${METRICS_TIMER_PERCENTILES:0.5}" - management: endpoints: web: From ebf10b55c8cc1f3287ffb23baab3a255160a2f03 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Wed, 11 Nov 2020 12:59:22 +0200 Subject: [PATCH 05/23] api usage state alias improvements --- .../dao/sql/query/DefaultEntityQueryRepository.java | 2 +- .../server/dao/sql/query/EntityKeyMapping.java | 3 ++- .../dao/usagerecord/ApiUsageStateServiceImpl.java | 13 +++++++++++++ ui-ngx/src/app/shared/models/entity-type.models.ts | 9 ++++++++- ui-ngx/src/assets/locale/locale.constant-en_US.json | 3 ++- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java index 380e166aa5..db61e6ab05 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java @@ -210,7 +210,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { entityTableMap.put(EntityType.CUSTOMER, "customer"); entityTableMap.put(EntityType.USER, "tb_user"); entityTableMap.put(EntityType.TENANT, "tenant"); - 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)"); + entityTableMap.put(EntityType.API_USAGE_STATE, "api_usage_state"); } public static EntityType[] RELATION_QUERY_ENTITY_TYPES = new EntityType[]{ diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index 525483f0a0..8d316aebcd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -79,7 +79,7 @@ public class EntityKeyMapping { public static final List dashboardEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE); public static final List labeledEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, ADDITIONAL_INFO); public static final List contactBasedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, EMAIL, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO); - + public static final List apiUsageStateEntityFields = Collections.singletonList(CREATED_TIME); public static final Set commonEntityFieldsSet = new HashSet<>(commonEntityFields); public static final Set relationQueryEntityFieldsSet = new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, FIRST_NAME, LAST_NAME, EMAIL, REGION, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO)); @@ -99,6 +99,7 @@ public class EntityKeyMapping { allowedEntityFieldMap.put(EntityType.RULE_NODE, new HashSet<>(commonEntityFields)); allowedEntityFieldMap.put(EntityType.WIDGET_TYPE, new HashSet<>(widgetEntityFields)); allowedEntityFieldMap.put(EntityType.WIDGETS_BUNDLE, new HashSet<>(widgetEntityFields)); + allowedEntityFieldMap.put(EntityType.API_USAGE_STATE, new HashSet<>(apiUsageStateEntityFields)); entityFieldColumnMap.put(CREATED_TIME, ModelConstants.CREATED_TIME_PROPERTY); entityFieldColumnMap.put(ENTITY_TYPE, ModelConstants.ENTITY_TYPE_PROPERTY); diff --git a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java index ed02bf7726..b525a71eaa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.usagerecord; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.ApiFeature; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.ApiUsageStateValue; @@ -27,6 +28,7 @@ import org.thingsboard.server.common.data.id.ApiUsageStateId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; +import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.tenant.profile.TenantProfileConfiguration; import org.thingsboard.server.dao.entity.AbstractEntityService; @@ -84,6 +86,17 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenant.getTenantProfileId().getId()); TenantProfileConfiguration configuration = tenantProfile.getProfileData().getConfiguration(); List profileThresholds = new ArrayList<>(); + List apiUsageStates = new ArrayList<>(); + apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + new StringDataEntry(ApiFeature.TRANSPORT.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); + apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + new StringDataEntry(ApiFeature.DB.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); + apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + new StringDataEntry(ApiFeature.RE.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); + apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + new StringDataEntry(ApiFeature.JS.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); + tsService.save(tenantId, saved.getId(), apiUsageStates, 0L); + for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) { profileThresholds.add(new BasicTsKvEntry(saved.getCreatedTime(), new LongDataEntry(key.getApiLimitKey(), configuration.getProfileThreshold(key)))); } diff --git a/ui-ngx/src/app/shared/models/entity-type.models.ts b/ui-ngx/src/app/shared/models/entity-type.models.ts index c6a94ad8b5..e53c5fb10e 100644 --- a/ui-ngx/src/app/shared/models/entity-type.models.ts +++ b/ui-ngx/src/app/shared/models/entity-type.models.ts @@ -47,7 +47,8 @@ export enum EntityType { RULE_NODE = 'RULE_NODE', ENTITY_VIEW = 'ENTITY_VIEW', WIDGETS_BUNDLE = 'WIDGETS_BUNDLE', - WIDGET_TYPE = 'WIDGET_TYPE' + WIDGET_TYPE = 'WIDGET_TYPE', + API_USAGE_STATE = 'API_USAGE_STATE' } export enum AliasEntityType { @@ -238,6 +239,12 @@ export const entityTypeTranslations = new Map Date: Wed, 11 Nov 2020 13:03:22 +0200 Subject: [PATCH 06/23] refactored --- .../thingsboard/server/dao/sql/query/EntityKeyMapping.java | 5 +++-- .../server/dao/usagerecord/ApiUsageStateServiceImpl.java | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index 8d316aebcd..7332de4b49 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -79,7 +79,8 @@ public class EntityKeyMapping { public static final List dashboardEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE); public static final List labeledEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, ADDITIONAL_INFO); public static final List contactBasedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, EMAIL, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO); - public static final List apiUsageStateEntityFields = Collections.singletonList(CREATED_TIME); + + public static final Set apiUsageStateEntityFields = Collections.singleton(CREATED_TIME); public static final Set commonEntityFieldsSet = new HashSet<>(commonEntityFields); public static final Set relationQueryEntityFieldsSet = new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, FIRST_NAME, LAST_NAME, EMAIL, REGION, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO)); @@ -99,7 +100,7 @@ public class EntityKeyMapping { allowedEntityFieldMap.put(EntityType.RULE_NODE, new HashSet<>(commonEntityFields)); allowedEntityFieldMap.put(EntityType.WIDGET_TYPE, new HashSet<>(widgetEntityFields)); allowedEntityFieldMap.put(EntityType.WIDGETS_BUNDLE, new HashSet<>(widgetEntityFields)); - allowedEntityFieldMap.put(EntityType.API_USAGE_STATE, new HashSet<>(apiUsageStateEntityFields)); + allowedEntityFieldMap.put(EntityType.API_USAGE_STATE, apiUsageStateEntityFields); entityFieldColumnMap.put(CREATED_TIME, ModelConstants.CREATED_TIME_PROPERTY); entityFieldColumnMap.put(ENTITY_TYPE, ModelConstants.ENTITY_TYPE_PROPERTY); diff --git a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java index b525a71eaa..12b5b3c01a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java @@ -85,7 +85,6 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A Tenant tenant = tenantDao.findById(tenantId, tenantId.getId()); TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenant.getTenantProfileId().getId()); TenantProfileConfiguration configuration = tenantProfile.getProfileData().getConfiguration(); - List profileThresholds = new ArrayList<>(); List apiUsageStates = new ArrayList<>(); apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), new StringDataEntry(ApiFeature.TRANSPORT.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); @@ -97,6 +96,8 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A new StringDataEntry(ApiFeature.JS.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); tsService.save(tenantId, saved.getId(), apiUsageStates, 0L); + List profileThresholds = new ArrayList<>(); + for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) { profileThresholds.add(new BasicTsKvEntry(saved.getCreatedTime(), new LongDataEntry(key.getApiLimitKey(), configuration.getProfileThreshold(key)))); } From 91aa144ae53f7598868e6b3f5c73985b6ecb32f9 Mon Sep 17 00:00:00 2001 From: Kalutka Zhenya Date: Wed, 11 Nov 2020 15:13:59 +0200 Subject: [PATCH 07/23] Fix widget margin --- ui-ngx/src/app/core/services/dashboard-utils.service.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui-ngx/src/app/core/services/dashboard-utils.service.ts b/ui-ngx/src/app/core/services/dashboard-utils.service.ts index 0b21a3f9be..a825b51f72 100644 --- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts +++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts @@ -422,6 +422,12 @@ export class DashboardUtilsService { widgetLayout.row = row; widgetLayout.col = 0; } + + widgetLayout.sizeX = Math.floor(widgetLayout.sizeX); + widgetLayout.sizeY = Math.floor(widgetLayout.sizeY); + widgetLayout.row = Math.floor(widgetLayout.row); + widgetLayout.col = Math.floor(widgetLayout.col); + layout.widgets[widget.id] = widgetLayout; } From 5de0059eb765631e7ac4862fe4c19bb4de75b98c Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Wed, 11 Nov 2020 16:25:25 +0200 Subject: [PATCH 08/23] apiUsageState improvements --- .../server/dao/usagerecord/ApiUsageStateServiceImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java index 12b5b3c01a..7836154c62 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java @@ -86,13 +86,13 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenant.getTenantProfileId().getId()); TenantProfileConfiguration configuration = tenantProfile.getProfileData().getConfiguration(); List apiUsageStates = new ArrayList<>(); - apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.TRANSPORT.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); - apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.DB.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); - apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.RE.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); - apiUsageStates.add(new BasicTsKvEntry(apiUsageState.getCreatedTime(), + apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), new StringDataEntry(ApiFeature.JS.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); tsService.save(tenantId, saved.getId(), apiUsageStates, 0L); From b02cbec0ee6b6bd2979b7f8b6e825642effa904d Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Wed, 11 Nov 2020 16:41:07 +0200 Subject: [PATCH 09/23] Minor logging improvements --- .../service/queue/processing/AbstractConsumerService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java index 0dfc9c5742..2d9ca3f042 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java @@ -153,6 +153,8 @@ public abstract class AbstractConsumerService Date: Wed, 11 Nov 2020 18:02:10 +0200 Subject: [PATCH 10/23] Improvements --- .../DefaultTbApiUsageStateService.java | 3 +-- .../transport/DefaultTransportApiService.java | 25 +++++++++++-------- docker/README.md | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java index f5d65b8397..c7206712c3 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java @@ -237,7 +237,7 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { @Override public void onTenantUpdate(TenantId tenantId) { - log.info("[{}] On Tenant Update", tenantId); + log.info("[{}] On Tenant Update.", tenantId); TenantProfile tenantProfile = tenantProfileCache.get(tenantId); updateLock.lock(); try { @@ -251,7 +251,6 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { } private void updateTenantState(TenantApiUsageState state, TenantProfile profile) { - log.info("[{}] On Tenant Update.", state.getTenantId()); TenantProfileData oldProfileData = state.getTenantProfileData(); state.setTenantProfileId(profile.getId()); state.setTenantProfileData(profile.getProfileData()); diff --git a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java index 3e9e413ceb..c7cbea8200 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java @@ -164,22 +164,25 @@ public class DefaultTransportApiService implements TransportApiService { } private ListenableFuture validateCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) { - DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName()); - if (credentials != null) { - if (credentials.getCredentialsType() == DeviceCredentialsType.ACCESS_TOKEN) { - return getDeviceInfo(credentials.getDeviceId(), credentials); - } else if (credentials.getCredentialsType() == DeviceCredentialsType.MQTT_BASIC) { - if (!checkMqttCredentials(mqtt, credentials)) { - credentials = null; + DeviceCredentials credentials = null; + if (mqtt.getUserName() != null) { + credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName()); + if (credentials != null) { + if (credentials.getCredentialsType() == DeviceCredentialsType.ACCESS_TOKEN) { + return getDeviceInfo(credentials.getDeviceId(), credentials); + } else if (credentials.getCredentialsType() == DeviceCredentialsType.MQTT_BASIC) { + if (!checkMqttCredentials(mqtt, credentials)) { + credentials = null; + } } } - } - if (credentials == null) { - credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash("|", mqtt.getClientId(), mqtt.getUserName())); if (credentials == null) { - credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash(mqtt.getClientId())); + credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash("|", mqtt.getClientId(), mqtt.getUserName())); } } + if (credentials == null) { + credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash(mqtt.getClientId())); + } if (credentials != null) { return getDeviceInfo(credentials.getDeviceId(), credentials); } else { diff --git a/docker/README.md b/docker/README.md index a1051c039e..9664edc48e 100644 --- a/docker/README.md +++ b/docker/README.md @@ -58,7 +58,7 @@ In case of any issues you can examine service logs for errors. For example to see ThingsBoard node logs execute the following command: ` -$ docker-compose logs -f tb-core1 tb-rule-engine1 +$ docker-compose logs -f tb-core1 tb-core2 tb-rule-engine1 tb-rule-engine2 tb-mqtt-transport1 tb-mqtt-transport2 ` Or use `docker-compose ps` to see the state of all the containers. From 2ccaa095cb5e255410641bcb11ee3e73b7d4e39e Mon Sep 17 00:00:00 2001 From: Kalutka Zhenya Date: Thu, 24 Sep 2020 14:47:29 +0300 Subject: [PATCH 11/23] Fix marker move --- .../home/components/widget/lib/maps/leaflet-map.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index 5d6f39850e..14d296436d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -410,10 +410,16 @@ export default abstract class LeafletMap { } convertToCustomFormat(position: L.LatLng): object { - return { - [this.options.latKeyName]: position.lat % 90, - [this.options.lngKeyName]: position.lng % 180 - }; + if(position.lng > 180){ + position.lng = 180; + }else if(position.lng < -180){ + position.lng = -180; + }; + + return { + [this.options.latKeyName]: position.lat, + [this.options.lngKeyName]: position.lng + }; } convertToPolygonFormat(points: Array): Array { From a06c8354973e361c760fd90b293a7fad41d18a6a Mon Sep 17 00:00:00 2001 From: Kalutka Zhenya Date: Mon, 28 Sep 2020 14:48:47 +0300 Subject: [PATCH 12/23] Fix marker move and marker point --- .../components/widget/lib/maps/leaflet-map.ts | 6 +++-- .../widget/lib/maps/providers/image-map.ts | 25 ++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index 14d296436d..742451ec5e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -131,10 +131,13 @@ export default abstract class LeafletMap { tooltipAnchor: [16, -28], shadowSize: [41, 41] }); + const customLatLng = this.convertToCustomFormat(mousePositionOnMap); + mousePositionOnMap.lat = customLatLng[this.options.latKeyName]; + mousePositionOnMap.lng = customLatLng[this.options.lngKeyName]; + const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map); this.addMarkers.push(newMarker); const datasourcesList = document.createElement('div'); - const customLatLng = this.convertToCustomFormat(mousePositionOnMap); const header = document.createElement('p'); header.appendChild(document.createTextNode('Select entity:')); header.setAttribute('style', 'font-size: 14px; margin: 8px 0'); @@ -415,7 +418,6 @@ export default abstract class LeafletMap { }else if(position.lng < -180){ position.lng = -180; }; - return { [this.options.latKeyName]: position.lat, [this.options.lngKeyName]: position.lng diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts index 1b20ddad01..2c967660e0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts @@ -258,10 +258,29 @@ export class ImageMap extends LeafletMap { } convertToCustomFormat(position: L.LatLng, width = this.width, height = this.height): object { - const point = this.latLngToPoint(position); + let point = this.latLngToPoint(position); + const customX = calculateNewPointCoordinate(point.x, width); + const customY = calculateNewPointCoordinate(point.y, height); + + if(customX === 0){ + point.x = 0; + } else if(customX === 1){ + point.x = width; + } + + if(customY === 0){ + point.y = 0; + } else if(customY === 1){ + point.y = height; + } + + const customLatLng = this.pointToLatLng(point.x,point.y) + return { - [this.options.xPosKeyName]: calculateNewPointCoordinate(point.x, width), - [this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, height) + [this.options.xPosKeyName]: customX, + [this.options.yPosKeyName]: customY, + [this.options.latKeyName]:customLatLng.lat, + [this.options.lngKeyName]:customLatLng.lng }; } From 60de89015acf58d7efc9903d9713661c04f8afed Mon Sep 17 00:00:00 2001 From: Kalutka Zhenya Date: Mon, 28 Sep 2020 15:01:20 +0300 Subject: [PATCH 13/23] Refactoring --- .../modules/home/components/widget/lib/maps/leaflet-map.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index 742451ec5e..f29ab38f03 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -132,8 +132,8 @@ export default abstract class LeafletMap { shadowSize: [41, 41] }); const customLatLng = this.convertToCustomFormat(mousePositionOnMap); - mousePositionOnMap.lat = customLatLng[this.options.latKeyName]; - mousePositionOnMap.lng = customLatLng[this.options.lngKeyName]; + mousePositionOnMap.lat = customLatLng[this.options.latKeyName]; + mousePositionOnMap.lng = customLatLng[this.options.lngKeyName]; const newMarker = L.marker(mousePositionOnMap, { icon }).addTo(this.map); this.addMarkers.push(newMarker); From 724b6c5247c97e661b104985fbb5956c88fae0dc Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 11 Nov 2020 18:03:33 +0200 Subject: [PATCH 14/23] Refactoring --- .../components/widget/lib/maps/leaflet-map.ts | 6 +++--- .../home/components/widget/lib/maps/markers.ts | 2 +- .../widget/lib/maps/providers/image-map.ts | 17 ++++++++--------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index f29ab38f03..0f1f08799c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -413,11 +413,11 @@ export default abstract class LeafletMap { } convertToCustomFormat(position: L.LatLng): object { - if(position.lng > 180){ + if (position.lng > 180) { position.lng = 180; - }else if(position.lng < -180){ + } else if (position.lng < -180) { position.lng = -180; - }; + } return { [this.options.latKeyName]: position.lat, [this.options.lngKeyName]: position.lng diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts index 4796956fa6..5f9e5e8362 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts @@ -94,7 +94,7 @@ export class Marker { } updateMarkerPosition(position: L.LatLng) { - if (!this.location.equals(position)) { + if (!this.leafletMarker.getLatLng().equals(position)) { this.location = position; this.leafletMarker.setLatLng(position); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts index 2c967660e0..825ace1227 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts @@ -258,29 +258,28 @@ export class ImageMap extends LeafletMap { } convertToCustomFormat(position: L.LatLng, width = this.width, height = this.height): object { - let point = this.latLngToPoint(position); + const point = this.latLngToPoint(position); const customX = calculateNewPointCoordinate(point.x, width); const customY = calculateNewPointCoordinate(point.y, height); - if(customX === 0){ + if (customX === 0) { point.x = 0; - } else if(customX === 1){ + } else if (customX === 1) { point.x = width; } - if(customY === 0){ + if (customY === 0) { point.y = 0; - } else if(customY === 1){ + } else if (customY === 1) { point.y = height; } - - const customLatLng = this.pointToLatLng(point.x,point.y) + const customLatLng = this.pointToLatLng(point.x, point.y); return { [this.options.xPosKeyName]: customX, [this.options.yPosKeyName]: customY, - [this.options.latKeyName]:customLatLng.lat, - [this.options.lngKeyName]:customLatLng.lng + [this.options.latKeyName]: customLatLng.lat, + [this.options.lngKeyName]: customLatLng.lng }; } From df21ce8043c03cf6131556abeeceae72534d48c4 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 11 Nov 2020 19:02:01 +0200 Subject: [PATCH 15/23] Fix validate credentials method --- .../server/service/transport/DefaultTransportApiService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java index c7cbea8200..5ceb9b3cd6 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java @@ -165,7 +165,7 @@ public class DefaultTransportApiService implements TransportApiService { private ListenableFuture validateCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) { DeviceCredentials credentials = null; - if (mqtt.getUserName() != null) { + if (!StringUtils.isEmpty(mqtt.getUserName())) { credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName()); if (credentials != null) { if (credentials.getCredentialsType() == DeviceCredentialsType.ACCESS_TOKEN) { From 671dfa7668a5b6279080030552b7367b9c2a17f6 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 11 Nov 2020 19:53:45 +0200 Subject: [PATCH 16/23] Add validator to unique MQTT device topic filter --- ...e-profile-transport-configuration.component.html | 3 +++ ...ice-profile-transport-configuration.component.ts | 13 +++++++++++-- ui-ngx/src/assets/locale/locale.constant-en_US.json | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.html index 00ff4760ab..5b3f3d8abf 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.html @@ -63,6 +63,9 @@ + + {{ 'device-profile.mqtt-device-topic-filters-unique' | translate }} +
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts index 18dc1b2bf4..c36d685fec 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/mqtt-device-profile-transport-configuration.component.ts @@ -51,7 +51,6 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control mqttTransportPayloadTypeTranslations = mqttTransportPayloadTypeTranslationMap; - mqttDeviceProfileTransportConfigurationFormGroup: FormGroup; private requiredValue: boolean; @@ -87,7 +86,7 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]], deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]], transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required] - }) + }, {validator: this.uniqueDeviceTopicValidator}) }); this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { this.updateModel(); @@ -147,4 +146,14 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control return null; }; } + + private uniqueDeviceTopicValidator(control: FormGroup): { [key: string]: boolean } | null { + if (control.value) { + const formValue = control.value as MqttDeviceProfileTransportConfiguration; + if (formValue.deviceAttributesTopic === formValue.deviceTelemetryTopic) { + return {unique: true}; + } + } + return null; + } } diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index f0d426be66..76799b73fd 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -885,6 +885,7 @@ "no-device-profiles-found": "No device profiles found.", "create-new-device-profile": "Create a new one!", "mqtt-device-topic-filters": "MQTT device topic filters", + "mqtt-device-topic-filters-unique": "MQTT device topic filters need to be unique.", "mqtt-device-payload-type": "MQTT device payload", "mqtt-device-payload-type-json": "JSON", "mqtt-device-payload-type-proto": "Protobuf", From 0dd9450b92a04c230fb83c9b73fabfcfc2df76ee Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Thu, 12 Nov 2020 09:55:18 +0200 Subject: [PATCH 17/23] Fix for ApiStats security checks --- .../server/dao/sql/query/DefaultEntityQueryRepository.java | 5 ++++- .../thingsboard/server/dao/sql/query/EntityKeyMapping.java | 2 +- ui-ngx/src/app/core/http/entity.service.ts | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java index db61e6ab05..8edb1917ba 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepository.java @@ -202,6 +202,9 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { " THEN (select additional_info from entity_view where id = entity_id)" + " END as additional_info"; + private static final String SELECT_API_USAGE_STATE = "(select aus.id, aus.created_time, aus.tenant_id, '13814000-1dd2-11b2-8080-808080808080'::uuid as customer_id, " + + "(select title from tenant where id = aus.tenant_id) as name from api_usage_state as aus)"; + static { entityTableMap.put(EntityType.ASSET, "asset"); entityTableMap.put(EntityType.DEVICE, "device"); @@ -210,7 +213,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository { entityTableMap.put(EntityType.CUSTOMER, "customer"); entityTableMap.put(EntityType.USER, "tb_user"); entityTableMap.put(EntityType.TENANT, "tenant"); - entityTableMap.put(EntityType.API_USAGE_STATE, "api_usage_state"); + entityTableMap.put(EntityType.API_USAGE_STATE, SELECT_API_USAGE_STATE); } public static EntityType[] RELATION_QUERY_ENTITY_TYPES = new EntityType[]{ diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index 7332de4b49..017306c47c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -80,7 +80,7 @@ public class EntityKeyMapping { public static final List labeledEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, ADDITIONAL_INFO); public static final List contactBasedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, EMAIL, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO); - public static final Set apiUsageStateEntityFields = Collections.singleton(CREATED_TIME); + public static final Set apiUsageStateEntityFields = new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME)); public static final Set commonEntityFieldsSet = new HashSet<>(commonEntityFields); public static final Set relationQueryEntityFieldsSet = new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, FIRST_NAME, LAST_NAME, EMAIL, REGION, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO)); diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index acd89e3c1b..9263838ffa 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -630,6 +630,9 @@ export class EntityService { case EntityType.DASHBOARD: entityFieldKeys.push(entityFields.title.keyName); break; + case EntityType.API_USAGE_STATE: + entityFieldKeys.push(entityFields.name.keyName); + break; } return query ? entityFieldKeys.filter((entityField) => entityField.toLowerCase().indexOf(query) === 0) : entityFieldKeys; } From 590f3a0a80ad7918b829545a83b39498afddd7be Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 12 Nov 2020 10:24:08 +0200 Subject: [PATCH 18/23] Improve tenant creation from OAuth mapper --- .../auth/oauth2/AbstractOAuth2ClientMapper.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java index f76521ac48..ea6e7d4f19 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java @@ -35,14 +35,17 @@ import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.oauth2.OAuth2User; +import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.service.install.InstallScripts; +import org.thingsboard.server.service.queue.TbClusterService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.UserPrincipal; @@ -76,6 +79,12 @@ public abstract class AbstractOAuth2ClientMapper { @Autowired private InstallScripts installScripts; + @Autowired + protected TbTenantProfileCache tenantProfileCache; + + @Autowired + protected TbClusterService tbClusterService; + private final Lock userCreationLock = new ReentrantLock(); protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2ClientRegistrationInfo clientRegistration) { @@ -162,6 +171,10 @@ public abstract class AbstractOAuth2ClientMapper { tenant.setTitle(tenantName); tenant = tenantService.saveTenant(tenant); installScripts.createDefaultRuleChains(tenant.getId()); + tenantProfileCache.evict(tenant.getId()); + tbClusterService.onTenantChange(tenant, null); + tbClusterService.onEntityStateChange(tenant.getId(), tenant.getId(), + ComponentLifecycleEvent.CREATED); } else { tenant = tenants.get(0); } From 31620008890eb6e8a474c63f8b09fd4e8c55adb9 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 12 Nov 2020 11:37:54 +0200 Subject: [PATCH 19/23] Use baseUrl from system security service for OAuth --- .../oauth2/Oauth2AuthenticationFailureHandler.java | 14 +++++++++++++- .../oauth2/Oauth2AuthenticationSuccessHandler.java | 10 ++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java index 984936874f..27a4962a0f 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java @@ -15,10 +15,15 @@ */ package org.thingsboard.server.service.security.auth.oauth2; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.security.system.SystemSecurityService; import org.thingsboard.server.utils.MiscUtils; import javax.servlet.ServletException; @@ -32,11 +37,18 @@ import java.nio.charset.StandardCharsets; @ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true") public class Oauth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + private final SystemSecurityService systemSecurityService; + + @Autowired + public Oauth2AuthenticationFailureHandler(final SystemSecurityService systemSecurityService) { + this.systemSecurityService = systemSecurityService; + } + @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - String baseUrl = MiscUtils.constructBaseUrl(request); + String baseUrl = this.systemSecurityService.getBaseUrl(TenantId.SYS_TENANT_ID, new CustomerId(EntityId.NULL_UUID), request); getRedirectStrategy().sendRedirect(request, response, baseUrl + "/login?loginError=" + URLEncoder.encode(exception.getMessage(), StandardCharsets.UTF_8.toString())); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java index 8a65eadedc..2e2eeeee61 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java @@ -22,12 +22,16 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationInfo; import org.thingsboard.server.dao.oauth2.OAuth2Service; import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtToken; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; +import org.thingsboard.server.service.security.system.SystemSecurityService; import org.thingsboard.server.utils.MiscUtils; import javax.servlet.http.HttpServletRequest; @@ -45,25 +49,27 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS private final OAuth2ClientMapperProvider oauth2ClientMapperProvider; private final OAuth2Service oAuth2Service; private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService; + private final SystemSecurityService systemSecurityService; @Autowired public Oauth2AuthenticationSuccessHandler(final JwtTokenFactory tokenFactory, final RefreshTokenRepository refreshTokenRepository, final OAuth2ClientMapperProvider oauth2ClientMapperProvider, final OAuth2Service oAuth2Service, - final OAuth2AuthorizedClientService oAuth2AuthorizedClientService) { + final OAuth2AuthorizedClientService oAuth2AuthorizedClientService, final SystemSecurityService systemSecurityService) { this.tokenFactory = tokenFactory; this.refreshTokenRepository = refreshTokenRepository; this.oauth2ClientMapperProvider = oauth2ClientMapperProvider; this.oAuth2Service = oAuth2Service; this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService; + this.systemSecurityService = systemSecurityService; } @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { - String baseUrl = MiscUtils.constructBaseUrl(request); + String baseUrl = this.systemSecurityService.getBaseUrl(TenantId.SYS_TENANT_ID, new CustomerId(EntityId.NULL_UUID), request); try { OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication; From 7a13083851cc9afe40702d37f9a28982fb92602f Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 12 Nov 2020 13:06:55 +0200 Subject: [PATCH 20/23] BaseUrl check --- .../security/system/DefaultSystemSecurityService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java index 4219dbc609..9bd22c88f5 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java @@ -202,16 +202,19 @@ public class DefaultSystemSecurityService implements SystemSecurityService { @Override public String getBaseUrl(TenantId tenantId, CustomerId customerId, HttpServletRequest httpServletRequest) { - String baseUrl; + String baseUrl = null; AdminSettings generalSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "general"); JsonNode prohibitDifferentUrl = generalSettings.getJsonValue().get("prohibitDifferentUrl"); if (prohibitDifferentUrl != null && prohibitDifferentUrl.asBoolean()) { baseUrl = generalSettings.getJsonValue().get("baseUrl").asText(); - } else { + } + + if (StringUtils.isEmpty(baseUrl)) { baseUrl = MiscUtils.constructBaseUrl(httpServletRequest); } + return baseUrl; } From 72a0126e23cd325fe95022911a5dcf592f7b99e1 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 12 Nov 2020 17:07:07 +0200 Subject: [PATCH 21/23] AlarmState improvements --- .../java/org/thingsboard/rule/engine/profile/AlarmState.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java index c59dbb75ca..535294d94c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java @@ -67,6 +67,7 @@ class AlarmState { initCurrentAlarm(ctx); lastMsgMetaData = msg.getMetaData(); lastMsgQueueName = msg.getQueueName(); + this.dataSnapshot = data; return createOrClearAlarms(ctx, data, update, AlarmRuleState::eval); } @@ -190,7 +191,7 @@ class AlarmState { } } - private TbAlarmResult calculateAlarmResult(TbContext ctx, AlarmRuleState ruleState) { + private TbAlarmResult calculateAlarmResult(TbContext ctx, AlarmRuleState ruleState) { AlarmSeverity severity = ruleState.getSeverity(); if (currentAlarm != null) { // TODO: In some extremely rare cases, we might miss the event of alarm clear (If one use in-mem queue and restarted the server) or (if one manipulated the rule chain). @@ -230,7 +231,7 @@ class AlarmState { } } - private JsonNode createDetails(AlarmRuleState ruleState) { + private JsonNode createDetails(AlarmRuleState ruleState) { ObjectNode details = JacksonUtil.OBJECT_MAPPER.createObjectNode(); String alarmDetails = ruleState.getAlarmRule().getAlarmDetails(); From cb41548b22bd11f64e3965cce5d9cec1108bacde Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Thu, 12 Nov 2020 19:32:45 +0200 Subject: [PATCH 22/23] Add cleanup of clear alarm state on non matching condition --- .../data/plugin/ComponentLifecycleEvent.java | 2 +- .../rule/engine/profile/AlarmState.java | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentLifecycleEvent.java b/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentLifecycleEvent.java index 1f242a0f88..87adc31713 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentLifecycleEvent.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentLifecycleEvent.java @@ -21,5 +21,5 @@ import java.io.Serializable; * @author Andrew Shvayka */ public enum ComponentLifecycleEvent implements Serializable { - CREATED, STARTED, ACTIVATED, SUSPENDED, UPDATED, STOPPED, DELETED, ADDED_TO_ALLOW_LIST, ADDED_TO_DENY_LIST + CREATED, STARTED, ACTIVATED, SUSPENDED, UPDATED, STOPPED, DELETED } \ No newline at end of file diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java index c59dbb75ca..390a0d22d6 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java @@ -90,8 +90,7 @@ class AlarmState { resultState = state; break; } else if (AlarmEvalResult.FALSE.equals(evalResult)) { - state.clear(); - stateUpdate |= state.checkUpdate(); + stateUpdate = clearAlarmState(stateUpdate, state); } } if (resultState != null) { @@ -99,6 +98,7 @@ class AlarmState { if (result != null) { pushMsg(ctx, result); } + stateUpdate = clearAlarmState(stateUpdate, clearState); } else if (currentAlarm != null && clearState != null) { if (!validateUpdate(update, clearState)) { log.debug("[{}] Update is not valid for current clear state", alarmDefinition.getId()); @@ -106,23 +106,26 @@ class AlarmState { } AlarmEvalResult evalResult = evalFunction.apply(clearState, data); if (AlarmEvalResult.TRUE.equals(evalResult)) { - clearState.clear(); - stateUpdate |= clearState.checkUpdate(); + stateUpdate = clearAlarmState(stateUpdate, clearState); for (AlarmRuleState state : createRulesSortedBySeverityDesc) { - state.clear(); - stateUpdate |= state.checkUpdate(); + stateUpdate = clearAlarmState(stateUpdate, state); } ctx.getAlarmService().clearAlarm(ctx.getTenantId(), currentAlarm.getId(), JacksonUtil.OBJECT_MAPPER.createObjectNode(), System.currentTimeMillis()); pushMsg(ctx, new TbAlarmResult(false, false, true, currentAlarm)); currentAlarm = null; } else if (AlarmEvalResult.FALSE.equals(evalResult)) { - clearState.clear(); - stateUpdate |= clearState.checkUpdate(); + stateUpdate = clearAlarmState(stateUpdate, clearState); } } return stateUpdate; } + public boolean clearAlarmState(boolean stateUpdate, AlarmRuleState state) { + state.clear(); + stateUpdate |= state.checkUpdate(); + return stateUpdate; + } + public boolean validateUpdate(SnapshotUpdate update, AlarmRuleState state) { if (update != null) { //Check that the update type and that keys match. @@ -273,8 +276,7 @@ class AlarmState { if (currentAlarm != null && currentAlarm.getId().equals(alarmNf.getId())) { currentAlarm = null; for (AlarmRuleState state : createRulesSortedBySeverityDesc) { - state.clear(); - updated |= state.checkUpdate(); + updated = clearAlarmState(updated, state); } } return updated; From 627c0577b08452308f925cecb3860e35292c649e Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Thu, 12 Nov 2020 19:44:49 +0200 Subject: [PATCH 23/23] Fix for ws reconnect issues --- .../service/subscription/DefaultTbLocalSubscriptionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java index 89233d2f4f..4e62628851 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java @@ -108,7 +108,7 @@ public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionSer * Since number of subscriptions is usually much less then number of devices that are pushing data. */ subscriptionsBySessionId.values().forEach(map -> map.values() - .forEach(sub -> pushSubscriptionToManagerService(sub, false))); + .forEach(sub -> pushSubscriptionToManagerService(sub, true))); } }