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 ff07a5df5c..9f67093529 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 @@ -41,7 +41,6 @@ import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.dao.util.DeviceConnectivityUtil; -import javax.annotation.PostConstruct; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; @@ -86,18 +85,6 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService @Value("${device.connectivity.mqtts.pem_cert_file:}") private String mqttsPemCertFile; - @PostConstruct - private void init() { - DeviceConnectivityInfo mqtts = getConnectivity(MQTTS); - if (mqtts != null && mqtts.isEnabled()) { - String certFilePath = mqttsPemCertFile; - if (StringUtils.isBlank(certFilePath) || !ResourceUtils.resourceExists(this, certFilePath)) { - String error = StringUtils.isBlank(certFilePath) ? "path is empty" : "file is not exists"; - log.error("MQTTS is enabled but cert {}!", error); - } - } - } - @Override public JsonNode findDevicePublishTelemetryCommands(String baseUrl, Device device) throws URISyntaxException { DeviceId deviceId = device.getId(); @@ -189,7 +176,7 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService private DeviceConnectivityInfo getConnectivity(String protocol) { AdminSettings connectivitySettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "connectivity"); JsonNode connectivity; - if (connectivitySettings != null && (connectivity = connectivitySettings.getJsonValue()) != null) { + if (connectivitySettings != null && (connectivity = connectivitySettings.getJsonValue()) != null) { return JacksonUtil.convertValue(connectivity.get(protocol), DeviceConnectivityInfo.class); } return null; diff --git a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.html index da0e9fede3..3fbcdff24e 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.html @@ -15,39 +15,110 @@ limitations under the License. --> -
- - - -
- admin.general-settings -
-
-
- - -
- -
-
- - admin.base-url - - - {{ 'admin.base-url-required' | translate }} - - - + + + +
+ admin.general-settings +
+
+
+ + +
+ + +
+ + admin.base-url + + + {{ 'admin.base-url-required' | translate }} + + +
+ {{ 'admin.prohibit-different-url' | translate }} - -
admin.prohibit-different-url-hint
-
- + +
+
+
+ + +
+ +
+
+ + + + admin.device-connectivity.device-connectivity + + + + +
+ + + {{ "admin.device-connectivity.http-https" | translate }} + {{ 'admin.device-connectivity.mqtt-mqtts' | translate }} + {{ 'admin.device-connectivity.coap-coaps' | translate }} + +
{{ 'admin.device-connectivity.hint' | translate }}
+
+ + + + + + + + + + + + + +
+ + {{ 'admin.device-connectivity.' + protocol | translate }} + +
+ + admin.device-connectivity.host + + + + admin.device-connectivity.port + + + {{ 'admin.device-connectivity.port-pattern' | translate }} + + + {{ 'admin.device-connectivity.port-range' | translate }} + +
-
- -
-
-
+ + +
+ + +
+ + + diff --git a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss index 4b2d51d1e9..f557735eb6 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss +++ b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.scss @@ -14,10 +14,12 @@ * limitations under the License. */ :host { -} - -:host ::ng-deep { - .mat-checkbox-layout { - white-space: normal; + .settings-card { + .toggle-group { + display: block; + } + .margin-bottom { + margin-bottom: 12px; + } } } diff --git a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts index 9aee40d431..d0ec896374 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/general-settings.component.ts @@ -14,13 +14,18 @@ /// limitations under the License. /// -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { PageComponent } from '@shared/components/page.component'; import { Router } from '@angular/router'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; -import { AdminSettings, GeneralSettings } from '@shared/models/settings.models'; +import { + AdminSettings, + DeviceConnectivityProtocol, + DeviceConnectivitySettings, + GeneralSettings +} from '@shared/models/settings.models'; import { AdminService } from '@core/http/admin.service'; import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard'; @@ -29,26 +34,27 @@ import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard'; templateUrl: './general-settings.component.html', styleUrls: ['./general-settings.component.scss', './settings-card.scss'] }) -export class GeneralSettingsComponent extends PageComponent implements OnInit, HasConfirmForm { +export class GeneralSettingsComponent extends PageComponent implements HasConfirmForm { generalSettings: UntypedFormGroup; - adminSettings: AdminSettings; + private adminSettings: AdminSettings; + + deviceConnectivitySettingsForm: UntypedFormGroup; + private deviceConnectivitySettings: AdminSettings; + + protocol: DeviceConnectivityProtocol = 'http'; constructor(protected store: Store, private router: Router, private adminService: AdminService, public fb: UntypedFormBuilder) { super(store); - } - - ngOnInit() { this.buildGeneralServerSettingsForm(); - this.adminService.getAdminSettings('general').subscribe( - (adminSettings) => { - this.adminSettings = adminSettings; - this.generalSettings.reset(this.adminSettings.jsonValue); - } - ); + this.adminService.getAdminSettings('general') + .subscribe(adminSettings => this.processGeneralSettings(adminSettings)); + this.buildDeviceConnectivitySettingsForm(); + this.adminService.getAdminSettings('connectivity') + .subscribe(deviceConnectivitySettings => this.processDeviceConnectivitySettings(deviceConnectivitySettings)); } buildGeneralServerSettingsForm() { @@ -58,18 +64,73 @@ export class GeneralSettingsComponent extends PageComponent implements OnInit, H }); } + buildDeviceConnectivitySettingsForm() { + this.deviceConnectivitySettingsForm = this.fb.group({ + http: this.fb.group({ + enabled: [false, []], + host: ['', []], + port: [null, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]] + }), + https: this.fb.group({ + enabled: [false, []], + host: ['', []], + port: [null, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]] + }), + mqtt: this.fb.group({ + enabled: [false, []], + host: ['', []], + port: [null, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]] + }), + mqtts: this.fb.group({ + enabled: [false, []], + host: ['', []], + port: [null, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]] + }), + coap: this.fb.group({ + enabled: [false, []], + host: ['', []], + port: [null, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]] + }), + coaps: this.fb.group({ + enabled: [false, []], + host: ['', []], + port: [null, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]] + }), + }); + } + save(): void { this.adminSettings.jsonValue = {...this.adminSettings.jsonValue, ...this.generalSettings.value}; - this.adminService.saveAdminSettings(this.adminSettings).subscribe( - (adminSettings) => { - this.adminSettings = adminSettings; - this.generalSettings.reset(this.adminSettings.jsonValue); - } - ); + this.adminService.saveAdminSettings(this.adminSettings) + .subscribe(adminSettings => this.processGeneralSettings(adminSettings)); + } + + saveDeviceConnectivitySettings(): void { + this.deviceConnectivitySettings.jsonValue = {...this.deviceConnectivitySettings.jsonValue, ...this.deviceConnectivitySettingsForm.value}; + this.adminService.saveAdminSettings(this.deviceConnectivitySettings) + .subscribe(deviceConnectivitySettings => this.processDeviceConnectivitySettings(deviceConnectivitySettings)); + } + + discardGeneralSettings(): void { + this.generalSettings.reset(this.adminSettings.jsonValue); + } + + discardDeviceConnectivitySettings(): void { + this.deviceConnectivitySettingsForm.reset(this.deviceConnectivitySettings.jsonValue); + } + + private processGeneralSettings(generalSettings: AdminSettings): void { + this.adminSettings = generalSettings; + this.generalSettings.reset(this.adminSettings.jsonValue); + } + + private processDeviceConnectivitySettings(deviceConnectivitySettings: AdminSettings): void { + this.deviceConnectivitySettings = deviceConnectivitySettings; + this.deviceConnectivitySettingsForm.reset(this.deviceConnectivitySettings.jsonValue); } confirmForm(): UntypedFormGroup { - return this.generalSettings; + return this.generalSettings.dirty ? this.generalSettings : this.deviceConnectivitySettingsForm; } } diff --git a/ui-ngx/src/app/shared/models/settings.models.ts b/ui-ngx/src/app/shared/models/settings.models.ts index 14f601dbe4..9238dae197 100644 --- a/ui-ngx/src/app/shared/models/settings.models.ts +++ b/ui-ngx/src/app/shared/models/settings.models.ts @@ -87,6 +87,16 @@ export interface GeneralSettings { baseUrl: string; } +export type DeviceConnectivityProtocol = 'http' | 'https' | 'mqtt' | 'mqtts' | 'coap' | 'coaps'; + +export interface DeviceConnectivityInfo { + enabled: boolean; + host: string; + port: number; +} + +export type DeviceConnectivitySettings = Record; + export interface UserPasswordPolicy { minimumLength: number; minimumUppercaseLetters: number; 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 b4c0f07c85..eb797fbf58 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -105,6 +105,23 @@ "base-url-required": "Base URL is required.", "prohibit-different-url": "Prohibit to use hostname from the client request headers", "prohibit-different-url-hint": "This setting should be enabled for production environments. May cause security issues when disabled", + "device-connectivity": { + "device-connectivity": "Device connectivity", + "http-https": "HTTP/HTTPS", + "mqtt-mqtts": "MQTT/MQTTS", + "coap-coaps": "COAP/COAPS", + "http": "HTPP", + "https": "HTTPS", + "mqtt": "MQTT", + "mqtts": "MQTTS", + "coap": "COAP", + "coaps": "COAPS", + "hint": "If host or port fields are empty will be used default protocol value.", + "host": "Host", + "port": "Port", + "port-pattern": "Port must be a positive integer.", + "port-range": "Port should be in a range from 1 to 65535." + }, "mail-from": "Mail From", "mail-from-required": "Mail From is required.", "smtp-protocol": "SMTP protocol",