From 4861a06841323983294664fc8946d495d2f68997 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Thu, 14 Dec 2023 14:57:05 +0200 Subject: [PATCH 1/2] Fix for not set but enabled transports in connectivity configurations --- .../DeviceConnectivityControllerTest.java | 83 +++++++++++++++++++ .../device/DeviceConnectivityServiceImpl.java | 13 +-- .../dao/util/DeviceConnectivityUtil.java | 9 +- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java index 57ae38f096..89ecf91b28 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.After; import org.junit.Assert; @@ -693,6 +694,88 @@ public class DeviceConnectivityControllerTest extends AbstractControllerTest { "thingsboard/coap-clients coap-client-openssl -v 6 -m POST coaps://test.domain:5684/api/v1/%s/telemetry -t json -e \"{temperature:25}\"", credentials.getCredentialsId())); } + @Test + public void testFetchPublishTelemetryCommandsForHostSetToNullInSettings() throws Exception { + loginSysAdmin(); + ObjectNode config = JacksonUtil.newObjectNode(); + + ObjectNode http = JacksonUtil.newObjectNode(); + http.put("enabled", true); + http.put("host", " "); + http.put("port", 8080); + config.set("http", http); + + ObjectNode https = JacksonUtil.newObjectNode(); + https.put("enabled", true); + https.put("host", ""); + https.put("port", 443); + config.set("https", https); + + ObjectNode mqtt = JacksonUtil.newObjectNode(); + mqtt.put("enabled", true); + mqtt.put("host", NullNode.getInstance()); + mqtt.put("port", NullNode.getInstance()); + config.set("mqtt", mqtt); + + ObjectNode mqtts = JacksonUtil.newObjectNode(); + mqtts.put("enabled", true); + mqtts.put("host", ""); + mqtts.put("port", NullNode.getInstance()); + config.set("mqtts", mqtts); + + ObjectNode coap = JacksonUtil.newObjectNode(); + coap.put("enabled", true); + coap.put("host", NullNode.getInstance()); + coap.put("port", ""); + config.set("coap", coap); + + ObjectNode coaps = JacksonUtil.newObjectNode(); + coaps.put("enabled", true); + coaps.put("host", NullNode.getInstance()); + coaps.put("port", NullNode.getInstance()); + config.set("coaps", coaps); + + AdminSettings adminSettings = doGet("/api/admin/settings/connectivity", AdminSettings.class); + adminSettings.setJsonValue(config); + doPost("/api/admin/settings", adminSettings).andExpect(status().isOk()); + + + login("tenant2@thingsboard.org", "testPassword1"); + + Device device = new Device(); + device.setName("My device"); + device.setType("default"); + Device savedDevice = doPost("/api/device", device, Device.class); + JsonNode commands = + doGetTyped("/api/device-connectivity/" + savedDevice.getId().getId(), new TypeReference<>() { + }); + + DeviceCredentials credentials = + doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class); + + assertThat(commands).hasSize(3); + JsonNode httpCommands = commands.get(HTTP); + assertThat(httpCommands.get(HTTP).asText()).isEqualTo(String.format("curl -v -X POST http://localhost:8080/api/v1/%s/telemetry --header Content-Type:application/json --data \"{temperature:25}\"", credentials.getCredentialsId())); + assertThat(httpCommands.get(HTTPS).asText()).isEqualTo(String.format("curl -v -X POST https://localhost/api/v1/%s/telemetry --header Content-Type:application/json --data \"{temperature:25}\"", credentials.getCredentialsId())); + + JsonNode mqttCommands = commands.get(MQTT); + assertThat(mqttCommands.get(MQTT).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 -h localhost -t v1/devices/me/telemetry -u \"%s\" -m \"{temperature:25}\"", credentials.getCredentialsId())); + assertThat(mqttCommands.get(MQTTS).get(0).asText()).isEqualTo("curl -f -S -o ca-root.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download"); + assertThat(mqttCommands.get(MQTTS).get(1).asText()).isEqualTo(String.format("mosquitto_pub -d -q 1 --cafile ca-root.pem -h localhost -t v1/devices/me/telemetry -u \"%s\" -m \"{temperature:25}\"", credentials.getCredentialsId())); + + JsonNode dockerMqttCommands = mqttCommands.get(DOCKER); + assertThat(dockerMqttCommands.get(MQTT).asText()).isEqualTo(String.format("docker run --rm -it --add-host=host.docker.internal:host-gateway thingsboard/mosquitto-clients mosquitto_pub -d -q 1 -h host.docker.internal -t v1/devices/me/telemetry -u \"%s\" -m \"{temperature:25}\"", credentials.getCredentialsId())); + assertThat(dockerMqttCommands.get(MQTTS).asText()).isEqualTo(String.format("docker run --rm -it --add-host=host.docker.internal:host-gateway thingsboard/mosquitto-clients /bin/sh -c \"curl -f -S -o ca-root.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download && mosquitto_pub -d -q 1 --cafile ca-root.pem -h host.docker.internal -t v1/devices/me/telemetry -u \"%s\" -m \"{temperature:25}\"\"", credentials.getCredentialsId())); + + JsonNode coapCommands = commands.get(COAP); + assertThat(coapCommands.get(COAP).asText()).isEqualTo(String.format("coap-client -v 6 -m POST coap://localhost/api/v1/%s/telemetry -t json -e \"{temperature:25}\"", credentials.getCredentialsId())); + assertThat(coapCommands.get(COAPS).asText()).isEqualTo(String.format("coap-client-openssl -v 6 -m POST coaps://localhost/api/v1/%s/telemetry -t json -e \"{temperature:25}\"", credentials.getCredentialsId())); + + JsonNode dockerCoapCommands = coapCommands.get(DOCKER); + assertThat(dockerCoapCommands.get(COAP).asText()).isEqualTo(String.format("docker run --rm -it --add-host=host.docker.internal:host-gateway thingsboard/coap-clients coap-client -v 6 -m POST coap://host.docker.internal/api/v1/%s/telemetry -t json -e \"{temperature:25}\"", credentials.getCredentialsId())); + assertThat(dockerCoapCommands.get(COAPS).asText()).isEqualTo(String.format("docker run --rm -it --add-host=host.docker.internal:host-gateway thingsboard/coap-clients coap-client-openssl -v 6 -m POST coaps://host.docker.internal/api/v1/%s/telemetry -t json -e \"{temperature:25}\"", credentials.getCredentialsId())); + } + private void setConnectivityHost(String host) throws Exception { ObjectNode config = JacksonUtil.newObjectNode(); diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java index 50396c6ebc..9061f9c3d6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java @@ -64,6 +64,7 @@ import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTT; import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTTS; import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.WINDOWS; import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.getHost; +import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.getPort; @Service("DeviceConnectivityDaoService") @Slf4j @@ -280,14 +281,14 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService private String getMqttPublishCommand(String baseUrl, String deviceTelemetryTopic, DeviceCredentials deviceCredentials) throws URISyntaxException { DeviceConnectivityInfo properties = getConnectivity(MQTT); String mqttHost = getHost(baseUrl, properties, MQTT); - String mqttPort = properties.getPort().isEmpty() ? null : properties.getPort(); + String mqttPort = getPort(properties); return DeviceConnectivityUtil.getMqttPublishCommand(MQTT, mqttHost, mqttPort, deviceTelemetryTopic, deviceCredentials); } private List getMqttsPublishCommand(String baseUrl, String deviceTelemetryTopic, DeviceCredentials deviceCredentials) throws URISyntaxException { DeviceConnectivityInfo properties = getConnectivity(MQTTS); String mqttHost = getHost(baseUrl, properties, MQTTS); - String mqttPort = properties.getPort().isEmpty() ? null : properties.getPort(); + String mqttPort = getPort(properties); String pubCommand = DeviceConnectivityUtil.getMqttPublishCommand(MQTTS, mqttHost, mqttPort, deviceTelemetryTopic, deviceCredentials); ArrayList commands = new ArrayList<>(); @@ -303,7 +304,7 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService ObjectNode dockerLaunchCommands = JacksonUtil.newObjectNode(); DeviceConnectivityInfo properties = getConnectivity(mqttType); String mqttHost = getHost(baseUrl, properties, mqttType); - String mqttPort = properties.getPort().isEmpty() ? null : properties.getPort(); + String mqttPort = getPort(properties); Optional.ofNullable(DeviceConnectivityUtil.getGatewayLaunchCommand(LINUX, deviceName, mqttHost, mqttPort, deviceCredentials)) .ifPresent(v -> dockerLaunchCommands.put(LINUX, v)); Optional.ofNullable(DeviceConnectivityUtil.getGatewayLaunchCommand(WINDOWS, deviceName, mqttHost, mqttPort, deviceCredentials)) @@ -314,7 +315,7 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService private String getDockerMqttPublishCommand(String protocol, String baseUrl, String deviceTelemetryTopic, DeviceCredentials deviceCredentials) throws URISyntaxException { DeviceConnectivityInfo properties = getConnectivity(protocol); String mqttHost = getHost(baseUrl, properties, protocol); - String mqttPort = properties.getPort().isEmpty() ? null : properties.getPort(); + String mqttPort = getPort(properties); return DeviceConnectivityUtil.getDockerMqttPublishCommand(protocol, baseUrl, mqttHost, mqttPort, deviceTelemetryTopic, deviceCredentials); } @@ -354,14 +355,14 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService private String getCoapPublishCommand(String protocol, String baseUrl, DeviceCredentials deviceCredentials) throws URISyntaxException { DeviceConnectivityInfo properties = getConnectivity(protocol); String hostName = getHost(baseUrl, properties, protocol); - String port = properties.getPort().isEmpty() ? "" : ":" + properties.getPort(); + String port = properties.getPort() == null || properties.getPort().isEmpty() ? "" : ":" + properties.getPort(); return DeviceConnectivityUtil.getCoapPublishCommand(protocol, hostName, port, deviceCredentials); } private String getDockerCoapPublishCommand(String protocol, String baseUrl, DeviceCredentials deviceCredentials) throws URISyntaxException { DeviceConnectivityInfo properties = getConnectivity(protocol); String host = getHost(baseUrl, properties, protocol); - String port = properties.getPort().isEmpty() ? "" : ":" + properties.getPort(); + String port = properties.getPort() == null || properties.getPort().isEmpty() ? "" : ":" + properties.getPort(); return DeviceConnectivityUtil.getDockerCoapPublishCommand(protocol, host, port, deviceCredentials); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java b/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java index 63ddba1c14..e82fdd11cf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java +++ b/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.util; -import org.apache.commons.lang3.StringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; import org.thingsboard.server.common.data.security.DeviceCredentials; @@ -62,7 +61,7 @@ public class DeviceConnectivityUtil { if (MQTTS.equals(protocol)) { command.append(" --cafile ").append(CA_ROOT_CERT_PEM); } - command.append(" -h ").append(host).append(port == null ? "" : " -p " + port); + command.append(" -h ").append(host).append(port.isBlank() ? "" : " -p " + port); command.append(" -t ").append(deviceTelemetryTopic); switch (deviceCredentials.getCredentialsType()) { @@ -193,7 +192,7 @@ public class DeviceConnectivityUtil { } public static String getHost(String baseUrl, DeviceConnectivityInfo properties, String protocol) throws URISyntaxException { - String initialHost = properties.getHost().isEmpty() ? baseUrl : properties.getHost(); + String initialHost = properties.getHost() == null || properties.getHost().isBlank() ? baseUrl : properties.getHost(); InetAddress inetAddress; String host = null; if (VALID_URL_PATTERN.matcher(initialHost).matches()) { @@ -217,6 +216,10 @@ public class DeviceConnectivityUtil { return host; } + public static String getPort(DeviceConnectivityInfo properties) { + return properties.getPort() == null || properties.getPort().isBlank() ? "" : properties.getPort(); + } + public static boolean isLocalhost(String host) { try { InetAddress inetAddress = InetAddress.getByName(host); From ac4f8758139c299f6809941058dcb7dbfe135ed3 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Mon, 18 Dec 2023 13:27:00 +0200 Subject: [PATCH 2/2] Changed check for blank string and added minor improvements --- .../DeviceConnectivityControllerTest.java | 14 +++++++------- .../dao/device/DeviceConnectivityServiceImpl.java | 4 ++-- .../server/dao/util/DeviceConnectivityUtil.java | 7 ++++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java index 0bd03d2e57..867cba53bb 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DeviceConnectivityControllerTest.java @@ -724,7 +724,7 @@ public class DeviceConnectivityControllerTest extends AbstractControllerTest { } @Test - public void testFetchPublishTelemetryCommandsForHostSetToNullInSettings() throws Exception { + public void testFetchPublishTelemetryCommandsForDeviceWhenHostSetToNullInSettings() throws Exception { loginSysAdmin(); ObjectNode config = JacksonUtil.newObjectNode(); @@ -742,26 +742,26 @@ public class DeviceConnectivityControllerTest extends AbstractControllerTest { ObjectNode mqtt = JacksonUtil.newObjectNode(); mqtt.put("enabled", true); - mqtt.put("host", NullNode.getInstance()); - mqtt.put("port", NullNode.getInstance()); + mqtt.set("host", NullNode.getInstance()); + mqtt.set("port", NullNode.getInstance()); config.set("mqtt", mqtt); ObjectNode mqtts = JacksonUtil.newObjectNode(); mqtts.put("enabled", true); mqtts.put("host", ""); - mqtts.put("port", NullNode.getInstance()); + mqtts.set("port", NullNode.getInstance()); config.set("mqtts", mqtts); ObjectNode coap = JacksonUtil.newObjectNode(); coap.put("enabled", true); - coap.put("host", NullNode.getInstance()); + coap.set("host", NullNode.getInstance()); coap.put("port", ""); config.set("coap", coap); ObjectNode coaps = JacksonUtil.newObjectNode(); coaps.put("enabled", true); - coaps.put("host", NullNode.getInstance()); - coaps.put("port", NullNode.getInstance()); + coaps.set("host", NullNode.getInstance()); + coaps.set("port", NullNode.getInstance()); config.set("coaps", coaps); AdminSettings adminSettings = doGet("/api/admin/settings/connectivity", AdminSettings.class); diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java index fff7e2591c..dfdd9f1796 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceConnectivityServiceImpl.java @@ -328,14 +328,14 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService private String getCoapPublishCommand(String protocol, String baseUrl, DeviceCredentials deviceCredentials) throws URISyntaxException { DeviceConnectivityInfo properties = getConnectivity(protocol); String hostName = getHost(baseUrl, properties, protocol); - String port = properties.getPort() == null || properties.getPort().isEmpty() ? "" : ":" + properties.getPort(); + String port = StringUtils.isBlank(properties.getPort()) ? "" : ":" + properties.getPort(); return DeviceConnectivityUtil.getCoapPublishCommand(protocol, hostName, port, deviceCredentials); } private String getDockerCoapPublishCommand(String protocol, String baseUrl, DeviceCredentials deviceCredentials) throws URISyntaxException { DeviceConnectivityInfo properties = getConnectivity(protocol); String host = getHost(baseUrl, properties, protocol); - String port = properties.getPort() == null || properties.getPort().isEmpty() ? "" : ":" + properties.getPort(); + String port = StringUtils.isBlank(properties.getPort()) ? "" : ":" + properties.getPort(); return DeviceConnectivityUtil.getDockerCoapPublishCommand(protocol, host, port, deviceCredentials); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java b/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java index d9cc996cfc..662b59bbab 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java +++ b/dao/src/main/java/org/thingsboard/server/dao/util/DeviceConnectivityUtil.java @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.util; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.dao.device.DeviceConnectivityInfo; @@ -63,7 +64,7 @@ public class DeviceConnectivityUtil { if (MQTTS.equals(protocol)) { command.append(" --cafile ").append(CA_ROOT_CERT_PEM); } - command.append(" -h ").append(host).append(port.isBlank() ? "" : " -p " + port); + command.append(" -h ").append(host).append(StringUtils.isBlank(port) ? "" : " -p " + port); command.append(" -t ").append(deviceTelemetryTopic); switch (deviceCredentials.getCredentialsType()) { @@ -219,7 +220,7 @@ public class DeviceConnectivityUtil { } public static String getHost(String baseUrl, DeviceConnectivityInfo properties, String protocol) throws URISyntaxException { - String initialHost = properties.getHost() == null || properties.getHost().isBlank() ? baseUrl : properties.getHost(); + String initialHost = StringUtils.isBlank(properties.getHost()) ? baseUrl : properties.getHost(); InetAddress inetAddress; String host = null; if (VALID_URL_PATTERN.matcher(initialHost).matches()) { @@ -244,7 +245,7 @@ public class DeviceConnectivityUtil { } public static String getPort(DeviceConnectivityInfo properties) { - return properties.getPort() == null || properties.getPort().isBlank() ? "" : properties.getPort(); + return StringUtils.isBlank(properties.getPort()) ? "" : properties.getPort(); } public static boolean isLocalhost(String host) {