diff --git a/application/src/main/java/org/thingsboard/server/controller/QueueController.java b/application/src/main/java/org/thingsboard/server/controller/QueueController.java index 3ba1df8c2a..0e79ae7955 100644 --- a/application/src/main/java/org/thingsboard/server/controller/QueueController.java +++ b/application/src/main/java/org/thingsboard/server/controller/QueueController.java @@ -83,7 +83,7 @@ public class QueueController extends BaseController { @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("serviceType", serviceType); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); - ServiceType type = ServiceType.valueOf(serviceType); + ServiceType type = ServiceType.of(serviceType); switch (type) { case TB_RULE_ENGINE: return queueService.findQueuesByTenantId(getTenantId(), pageLink); @@ -136,7 +136,7 @@ public class QueueController extends BaseController { checkEntity(queue.getId(), queue, Resource.QUEUE); - ServiceType type = ServiceType.valueOf(serviceType); + ServiceType type = ServiceType.of(serviceType); switch (type) { case TB_RULE_ENGINE: queue.setTenantId(getTenantId()); diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index f79f5ee782..d49b2b04df 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -406,7 +406,7 @@ public class UserController extends BaseController { public void setUserCredentialsEnabled( @ApiParam(value = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId, - @ApiParam(value = "Disable (\"true\") or enable (\"false\") the credentials.", defaultValue = "true") + @ApiParam(value = "Enable (\"true\") or disable (\"false\") the credentials.", defaultValue = "true") @RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java new file mode 100644 index 0000000000..465ec37bb9 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java @@ -0,0 +1,96 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.controller; + +import com.fasterxml.jackson.core.type.TypeReference; +import org.junit.Assert; +import org.junit.Test; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.queue.ProcessingStrategy; +import org.thingsboard.server.common.data.queue.ProcessingStrategyType; +import org.thingsboard.server.common.data.queue.Queue; +import org.thingsboard.server.common.data.queue.SubmitStrategy; +import org.thingsboard.server.common.data.queue.SubmitStrategyType; +import org.thingsboard.server.dao.service.DaoSqlTest; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@DaoSqlTest +public class BaseQueueControllerTest extends AbstractControllerTest { + + @Test + public void testQueueWithServiceTypeRE() throws Exception { + loginSysAdmin(); + + // create queue + Queue queue = new Queue(); + queue.setName("qwerty"); + queue.setTopic("tb_rule_engine.qwerty"); + queue.setPollInterval(25); + queue.setPartitions(10); + queue.setTenantId(TenantId.SYS_TENANT_ID); + queue.setConsumerPerPartition(false); + queue.setPackProcessingTimeout(2000); + SubmitStrategy submitStrategy = new SubmitStrategy(); + submitStrategy.setType(SubmitStrategyType.SEQUENTIAL_BY_ORIGINATOR); + queue.setSubmitStrategy(submitStrategy); + ProcessingStrategy processingStrategy = new ProcessingStrategy(); + processingStrategy.setType(ProcessingStrategyType.RETRY_ALL); + processingStrategy.setRetries(3); + processingStrategy.setFailurePercentage(0.7); + processingStrategy.setPauseBetweenRetries(3); + processingStrategy.setMaxPauseBetweenRetries(5); + queue.setProcessingStrategy(processingStrategy); + + // create queue + Queue queue2 = new Queue(); + queue2.setName("qwerty2"); + queue2.setTopic("tb_rule_engine.qwerty2"); + queue2.setPollInterval(25); + queue2.setPartitions(10); + queue2.setTenantId(TenantId.SYS_TENANT_ID); + queue2.setConsumerPerPartition(false); + queue2.setPackProcessingTimeout(2000); + submitStrategy.setType(SubmitStrategyType.SEQUENTIAL_BY_ORIGINATOR); + queue2.setSubmitStrategy(submitStrategy); + processingStrategy.setType(ProcessingStrategyType.RETRY_ALL); + processingStrategy.setRetries(3); + processingStrategy.setFailurePercentage(0.7); + processingStrategy.setPauseBetweenRetries(3); + processingStrategy.setMaxPauseBetweenRetries(5); + queue2.setProcessingStrategy(processingStrategy); + + Queue savedQueue = doPost("/api/queues?serviceType=" + "TB-RULE-ENGINE", queue, Queue.class); + Queue savedQueue2 = doPost("/api/queues?serviceType=" + "TB_RULE_ENGINE", queue2, Queue.class); + + PageLink pageLink = new PageLink(10); + PageData pageData; + pageData = doGetTypedWithPageLink("/api/queues?serviceType=TB-RULE-ENGINE&", new TypeReference<>() { + }, pageLink); + Assert.assertFalse(pageData.getData().isEmpty()); + doDelete("/api/queues/" + savedQueue.getUuidId()) + .andExpect(status().isOk()); + + pageData = doGetTypedWithPageLink("/api/queues?serviceType=TB_RULE_ENGINE&", new TypeReference<>() { + }, pageLink); + Assert.assertFalse(pageData.getData().isEmpty()); + doDelete("/api/queues/" + savedQueue2.getUuidId()) + .andExpect(status().isOk()); + } + +} diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/client/AbstractMqttClientConnectionTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/client/AbstractMqttClientConnectionTest.java index 116459e5e6..8c567e402c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/client/AbstractMqttClientConnectionTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/client/AbstractMqttClientConnectionTest.java @@ -34,7 +34,7 @@ public abstract class AbstractMqttClientConnectionTest extends AbstractMqttInteg try { client.connectAndWait("wrongAccessToken"); } catch (MqttException e) { - Assert.assertEquals(MqttException.REASON_CODE_FAILED_AUTHENTICATION, e.getReasonCode()); + Assert.assertEquals(MqttException.REASON_CODE_NOT_AUTHORIZED, e.getReasonCode()); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/credentials/BasicMqttCredentialsTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/credentials/BasicMqttCredentialsTest.java index 87337545fc..8f0dc24d7c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/credentials/BasicMqttCredentialsTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/credentials/BasicMqttCredentialsTest.java @@ -124,7 +124,7 @@ public class BasicMqttCredentialsTest extends AbstractMqttIntegrationTest { mqttTestClient.connectAndWait(USER_NAME3, "WRONG PASSWORD"); Assert.fail(); // This should not happens, because we have a wrong password } catch (MqttException e) { - Assert.assertEquals(4, e.getReasonCode()); // 4 - Reason code for bad username or password in MQTT v3 + Assert.assertEquals(5, e.getReasonCode()); // 4 - Reason code not authorized in MQTT v3 } Assertions.assertThrows(MqttException.class, () -> { testTelemetryIsNotDelivered(clientIdAndUserNameAndPasswordDevice3, mqttTestClient); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index 08f2e849f8..14fb0369ee 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -326,7 +326,7 @@ public class HashPartitionService implements PartitionService { final Map> currentMap = new HashMap<>(); services.forEach(serviceInfo -> { for (String serviceTypeStr : serviceInfo.getServiceTypesList()) { - ServiceType serviceType = ServiceType.valueOf(serviceTypeStr.toUpperCase()); + ServiceType serviceType = ServiceType.of(serviceTypeStr); if (ServiceType.TB_RULE_ENGINE.equals(serviceType)) { partitionTopicsMap.keySet().forEach(queueKey -> currentMap.computeIfAbsent(queueKey, key -> new ArrayList<>()).add(serviceInfo)); @@ -389,7 +389,7 @@ public class HashPartitionService implements PartitionService { private void addNode(Map> queueServiceList, ServiceInfo instance) { for (String serviceTypeStr : instance.getServiceTypesList()) { - ServiceType serviceType = ServiceType.valueOf(serviceTypeStr.toUpperCase()); + ServiceType serviceType = ServiceType.of(serviceTypeStr); if (ServiceType.TB_RULE_ENGINE.equals(serviceType)) { partitionTopicsMap.keySet().forEach(key -> { if (key.getType().equals(ServiceType.TB_RULE_ENGINE)) { diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/ReturnCodeResolver.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/ReturnCodeResolver.java index 5c97286a2d..e4b8e8fc2f 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/ReturnCodeResolver.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/ReturnCodeResolver.java @@ -27,7 +27,6 @@ public class ReturnCodeResolver { if (!MqttVersion.MQTT_5.equals(mqttVersion) && !ReturnCode.SUCCESS.equals(returnCode)) { switch (returnCode) { case BAD_USERNAME_OR_PASSWORD: - return MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD; case NOT_AUTHORIZED_5: return MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; case SERVER_UNAVAILABLE_5: diff --git a/dao/src/main/resources/sql/schema-views-and-functions.sql b/dao/src/main/resources/sql/schema-views-and-functions.sql index eaa09d78cc..3cd20ac0c4 100644 --- a/dao/src/main/resources/sql/schema-views-and-functions.sql +++ b/dao/src/main/resources/sql/schema-views-and-functions.sql @@ -23,7 +23,7 @@ SELECT d.* , COALESCE(da.bool_v, FALSE) as active FROM device d LEFT JOIN customer c ON c.id = d.customer_id - LEFT JOIN attribute_kv da ON da.entity_id = d.id and da.attribute_key = 'active'; + LEFT JOIN attribute_kv da ON da.entity_type = 'DEVICE' AND da.entity_id = d.id AND da.attribute_type = 'SERVER_SCOPE' AND da.attribute_key = 'active'; DROP VIEW IF EXISTS device_info_active_ts_view CASCADE; CREATE OR REPLACE VIEW device_info_active_ts_view AS diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts index 41468d096f..28e64738a8 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-table-config.ts @@ -86,7 +86,7 @@ export class AlarmTableConfig extends EntityTableConfig private utilsService: UtilsService, pageMode = false) { super(); - this.loadDataOnInit = false; + this.loadDataOnInit = pageMode; this.tableTitle = ''; this.useTimePageLink = true; this.forAllTimeEnabled = true; diff --git a/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.html b/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.html index 4abf910c1a..66dbbba2e3 100644 --- a/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/entity/add-entity-dialog.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+

{{ translations.add }}

diff --git a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts index 0a5e5dc3ee..ac128b3ec5 100644 --- a/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/queue/tenant-profile-queues.component.ts @@ -116,7 +116,7 @@ export class TenantProfileQueuesComponent implements ControlValueAccessor, Valid } writeValue(queues: Array | null): void { - if (queues.length === this.queuesFormArray.length) { + if (queues?.length === this.queuesFormArray.length) { this.queuesFormArray.patchValue(queues, {emitEvent: false}); } else { const queuesControls: Array = []; diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html index ce2f086d4d..c2872d4145 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html @@ -21,7 +21,7 @@ {{ 'tenant-profile.entities' | translate }} tenant-profile.unlimited
- + tenant-profile.maximum-devices {{ 'tenant-profile.maximum-devices-range' | translate}} + - + tenant-profile.maximum-dashboards {{ 'tenant-profile.maximum-dashboards-range' | translate}} +
- + tenant-profile.maximum-assets {{ 'tenant-profile.maximum-assets-range' | translate}} + - + tenant-profile.maximum-users {{ 'tenant-profile.maximum-users-range' | translate}} +
@@ -80,7 +84,7 @@
- + tenant-profile.maximum-customers {{ 'tenant-profile.maximum-customers-range' | translate}} + - + tenant-profile.maximum-rule-chains {{ 'tenant-profile.maximum-rule-chains-range' | translate}} +
@@ -114,7 +120,7 @@ {{ 'tenant-profile.rule-engine' | translate }} tenant-profile.unlimited
- + tenant-profile.max-r-e-executions {{ 'tenant-profile.max-r-e-executions-range' | translate}} + - + tenant-profile.max-transport-messages {{ 'tenant-profile.max-transport-messages-required' | translate}} +
@@ -147,7 +155,7 @@
- + tenant-profile.max-j-s-executions {{ 'tenant-profile.max-j-s-executions-range' | translate}} + - + tenant-profile.max-transport-data-points {{ 'tenant-profile.max-transport-data-points-range' | translate}} +
- + tenant-profile.max-rule-node-executions-per-message {{ 'tenant-profile.max-rule-node-executions-per-message-range' | translate}} +
@@ -196,7 +207,7 @@ {{ 'tenant-profile.time-to-live' | translate }} tenant-profile.unlimited
- + tenant-profile.max-d-p-storage-days {{ 'tenant-profile.max-d-p-storage-days-range' | translate}} + - + tenant-profile.alarms-ttl-days {{ 'tenant-profile.alarms-ttl-days-days-range' | translate}} +
- + tenant-profile.default-storage-ttl-days {{ 'tenant-profile.default-storage-ttl-days-range' | translate}} + - + tenant-profile.rpc-ttl-days {{ 'tenant-profile.rpc-ttl-days-days-range' | translate}} +
@@ -256,7 +271,8 @@ {{ 'tenant-profile.sms-enabled' | translate }} - + tenant-profile.max-sms -
- +
+ tenant-profile.max-emails {{ 'tenant-profile.max-emails-range' | translate}} + - + tenant-profile.max-created-alarms {{ 'tenant-profile.max-created-alarms-range' | translate}} +
@@ -301,7 +319,7 @@ {{ 'tenant-profile.ota-files-in-bytes' | translate }} tenant-profile.unlimited
- + tenant-profile.maximum-resources-sum-data-size {{ 'tenant-profile.maximum-resources-sum-data-size-range' | translate}} + - + tenant-profile.maximum-ota-packages-sum-data-size - {{ 'tenant-profile.maximum-ota-packages-sum-data-size-required' | translate}} + {{ 'tenant-profile.maximum-ota-package-sum-data-size-required' | translate}} - {{ 'tenant-profile.maximum-ota-packages-sum-data-size-range' | translate}} + {{ 'tenant-profile.maximum-ota-package-sum-data-size-range' | translate}} +
diff --git a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.html b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.html index 9fee72fef4..56b20d8aa8 100644 --- a/ui-ngx/src/app/modules/home/components/queue/queue-form.component.html +++ b/ui-ngx/src/app/modules/home/components/queue/queue-form.component.html @@ -37,7 +37,7 @@ -
+
@@ -75,7 +75,7 @@ -
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html index 4c83594e44..fd68f51a14 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html @@ -290,7 +290,7 @@
widgets.chart.custom-legend-settings - + diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html index 130a1b2df0..ef29248767 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html @@ -164,6 +164,8 @@ admin.jwt.security-settings + +
diff --git a/ui-ngx/src/app/shared/models/constants.ts b/ui-ngx/src/app/shared/models/constants.ts index 5d55717c07..8648973c72 100644 --- a/ui-ngx/src/app/shared/models/constants.ts +++ b/ui-ngx/src/app/shared/models/constants.ts @@ -166,6 +166,7 @@ export const HelpLinks = { templateNotifications: helpBaseUrl + '/docs/user-guide/notifications/#templates', recipientNotifications: helpBaseUrl + '/docs/user-guide/notifications/#recipients', ruleNotifications: helpBaseUrl + '/docs/user-guide/notifications/#rules', + jwtSecuritySettings: helpBaseUrl + '/docs/user-guide/ui/jwt-security-settings/', } };