diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.html b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.html
new file mode 100644
index 0000000000..0b798e6dbf
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.html
@@ -0,0 +1,48 @@
+
+
diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts
new file mode 100644
index 0000000000..d4c88431a9
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/device/device-credentials-mqtt-basic.component.ts
@@ -0,0 +1,133 @@
+///
+/// Copyright © 2016-2021 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.
+///
+
+import { Component, forwardRef, Input, OnDestroy } from '@angular/core';
+import {
+ ControlValueAccessor,
+ FormBuilder,
+ FormGroup,
+ NG_VALIDATORS,
+ NG_VALUE_ACCESSOR,
+ ValidationErrors,
+ Validator,
+ ValidatorFn,
+ Validators
+} from '@angular/forms';
+import { Subject } from 'rxjs';
+import { DeviceCredentialMQTTBasic } from '@shared/models/device.models';
+import { takeUntil } from 'rxjs/operators';
+import { isDefinedAndNotNull, isEmptyStr } from '@core/utils';
+
+@Component({
+ selector: 'tb-device-credentials-mqtt-basic',
+ templateUrl: './device-credentials-mqtt-basic.component.html',
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent),
+ multi: true
+ },
+ {
+ provide: NG_VALIDATORS,
+ useExisting: forwardRef(() => DeviceCredentialsMqttBasicComponent),
+ multi: true,
+ }],
+ styleUrls: []
+})
+export class DeviceCredentialsMqttBasicComponent implements ControlValueAccessor, Validator, OnDestroy {
+
+ @Input()
+ disabled: boolean;
+
+ deviceCredentialsMqttFormGroup: FormGroup;
+
+ hidePassword = true;
+
+ private destroy$ = new Subject();
+ private propagateChange = (v: any) => {};
+
+ constructor(public fb: FormBuilder) {
+ this.deviceCredentialsMqttFormGroup = this.fb.group({
+ clientId: [null, [Validators.pattern(/^[A-Za-z0-9]+$/)]],
+ userName: [null],
+ password: [null]
+ }, {validators: this.atLeastOne(Validators.required, ['clientId', 'userName'])});
+ this.deviceCredentialsMqttFormGroup.valueChanges.pipe(
+ takeUntil(this.destroy$)
+ ).subscribe((value) => {
+ this.updateView(value);
+ });
+ }
+
+ ngOnDestroy(): void {
+ this.destroy$.next();
+ this.destroy$.complete();
+ }
+
+ registerOnChange(fn: any): void {
+ this.propagateChange = fn;
+ }
+
+ registerOnTouched(fn: any): void {}
+
+ setDisabledState(isDisabled: boolean) {
+ this.disabled = isDisabled;
+ if (this.disabled) {
+ this.deviceCredentialsMqttFormGroup.disable({emitEvent: false});
+ } else {
+ this.deviceCredentialsMqttFormGroup.enable({emitEvent: false});
+ }
+ }
+
+ validate(): ValidationErrors | null {
+ return this.deviceCredentialsMqttFormGroup.valid ? null : {
+ deviceCredentialsMqttBasic: false
+ };
+ }
+
+ writeValue(mqttBasic: string) {
+ if (isDefinedAndNotNull(mqttBasic) && !isEmptyStr(mqttBasic)) {
+ const value = JSON.parse(mqttBasic);
+ this.deviceCredentialsMqttFormGroup.patchValue(value, {emitEvent: false});
+ }
+ }
+
+ updateView(value: DeviceCredentialMQTTBasic) {
+ const formValue = JSON.stringify(value);
+ this.propagateChange(formValue);
+ }
+
+ passwordChanged() {
+ const value = this.deviceCredentialsMqttFormGroup.get('password').value;
+ if (value !== '') {
+ this.deviceCredentialsMqttFormGroup.get('userName').setValidators([Validators.required]);
+ } else {
+ this.deviceCredentialsMqttFormGroup.get('userName').setValidators([]);
+ }
+ this.deviceCredentialsMqttFormGroup.get('userName').updateValueAndValidity({emitEvent: false});
+ }
+
+ private atLeastOne(validator: ValidatorFn, controls: string[] = null) {
+ return (group: FormGroup): ValidationErrors | null => {
+ if (!controls) {
+ controls = Object.keys(group.controls);
+ }
+ const hasAtLeastOne = group?.controls && controls.some(k => !validator(group.controls[k]));
+
+ return hasAtLeastOne ? null : {atLeastOne: true};
+ };
+ }
+}
diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html
index 76c1fa13bb..76a9935565 100644
--- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html
+++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.html
@@ -24,58 +24,35 @@
-
- device.access-token
-
-
- {{ 'device.access-token-required' | translate }}
-
-
- {{ 'device.access-token-invalid' | translate }}
-
-
-
- device.rsa-key
-
-
- {{ 'device.rsa-key-required' | translate }}
-
-
-
-
-
-
+
+
+
+ device.access-token
+
+
+ {{ 'device.access-token-required' | translate }}
+
+
+ {{ 'device.access-token-invalid' | translate }}
+
+
+
+
+
+ device.rsa-key
+
+
+ {{ 'device.rsa-key-required' | translate }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts
index d558213ec4..3617ecbcf4 100644
--- a/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts
+++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.component.ts
@@ -22,15 +22,12 @@ import {
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
- ValidationErrors,
Validator,
- ValidatorFn,
Validators
} from '@angular/forms';
import {
credentialTypeNames,
credentialTypesByTransportType,
- DeviceCredentialMQTTBasic,
DeviceCredentials,
DeviceCredentialsType,
DeviceTransportType
@@ -62,7 +59,7 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
private deviceTransportTypeValue = DeviceTransportType.DEFAULT;
get deviceTransportType(): DeviceTransportType {
- return this.deviceTransportTypeValue
+ return this.deviceTransportTypeValue;
}
@Input()
set deviceTransportType(type: DeviceTransportType) {
@@ -86,22 +83,14 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
credentialTypeNamesMap = credentialTypeNames;
- hidePassword = true;
-
private propagateChange = (v: any) => {};
constructor(public fb: FormBuilder) {
this.deviceCredentialsFormGroup = this.fb.group({
credentialsType: [DeviceCredentialsType.ACCESS_TOKEN],
credentialsId: [null],
- credentialsValue: [null],
- credentialsBasic: this.fb.group({
- clientId: [null, [Validators.pattern(/^[A-Za-z0-9]+$/)]],
- userName: [null],
- password: [null]
- }, {validators: this.atLeastOne(Validators.required, ['clientId', 'userName'])})
+ credentialsValue: [null]
});
- this.deviceCredentialsFormGroup.get('credentialsBasic').disable();
this.deviceCredentialsFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe(() => {
@@ -127,18 +116,11 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
writeValue(value: DeviceCredentials | null): void {
if (isDefinedAndNotNull(value)) {
- let credentialsBasic = {clientId: null, userName: null, password: null};
- let credentialsValue = null;
- if (value.credentialsType === DeviceCredentialsType.MQTT_BASIC) {
- credentialsBasic = JSON.parse(value.credentialsValue) as DeviceCredentialMQTTBasic;
- } else {
- credentialsValue = value.credentialsValue;
- }
+ const credentialsType = this.credentialsTypes.includes(value.credentialsType) ? value.credentialsType : this.credentialsTypes[0];
this.deviceCredentialsFormGroup.patchValue({
- credentialsType: value.credentialsType,
+ credentialsType,
credentialsId: value.credentialsId,
- credentialsValue,
- credentialsBasic
+ credentialsValue: value.credentialsValue
}, {emitEvent: false});
this.updateValidators();
}
@@ -146,10 +128,6 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
updateView() {
const deviceCredentialsValue = this.deviceCredentialsFormGroup.value;
- if (deviceCredentialsValue.credentialsType === DeviceCredentialsType.MQTT_BASIC) {
- deviceCredentialsValue.credentialsValue = JSON.stringify(deviceCredentialsValue.credentialsBasic);
- }
- delete deviceCredentialsValue.credentialsBasic;
this.propagateChange(deviceCredentialsValue);
}
@@ -181,14 +159,12 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
credentialsTypeChanged(): void {
this.deviceCredentialsFormGroup.patchValue({
credentialsId: null,
- credentialsValue: null,
- credentialsBasic: {clientId: '', userName: '', password: ''}
+ credentialsValue: null
});
this.updateValidators();
}
updateValidators(): void {
- this.hidePassword = true;
const credentialsType = this.deviceCredentialsFormGroup.get('credentialsType').value as DeviceCredentialsType;
switch (credentialsType) {
case DeviceCredentialsType.ACCESS_TOKEN:
@@ -196,48 +172,13 @@ export class DeviceCredentialsComponent implements ControlValueAccessor, OnInit,
this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false});
this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([]);
this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false});
- this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false});
break;
- case DeviceCredentialsType.X509_CERTIFICATE:
- case DeviceCredentialsType.LWM2M_CREDENTIALS:
+ default:
this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([Validators.required]);
this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false});
this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]);
this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false});
- this.deviceCredentialsFormGroup.get('credentialsBasic').disable({emitEvent: false});
break;
- case DeviceCredentialsType.MQTT_BASIC:
- this.deviceCredentialsFormGroup.get('credentialsBasic').enable({emitEvent: false});
- this.deviceCredentialsFormGroup.get('credentialsBasic').updateValueAndValidity({emitEvent: false});
- this.deviceCredentialsFormGroup.get('credentialsId').setValidators([]);
- this.deviceCredentialsFormGroup.get('credentialsId').updateValueAndValidity({emitEvent: false});
- this.deviceCredentialsFormGroup.get('credentialsValue').setValidators([]);
- this.deviceCredentialsFormGroup.get('credentialsValue').updateValueAndValidity({emitEvent: false});
- break;
- }
- }
-
- private atLeastOne(validator: ValidatorFn, controls: string[] = null) {
- return (group: FormGroup): ValidationErrors | null => {
- if (!controls) {
- controls = Object.keys(group.controls);
- }
- const hasAtLeastOne = group?.controls && controls.some(k => !validator(group.controls[k]));
-
- return hasAtLeastOne ? null : {atLeastOne: true};
- };
- }
-
- passwordChanged() {
- const value = this.deviceCredentialsFormGroup.get('credentialsBasic.password').value;
- if (value !== '') {
- this.deviceCredentialsFormGroup.get('credentialsBasic.userName').setValidators([Validators.required]);
- } else {
- this.deviceCredentialsFormGroup.get('credentialsBasic.userName').setValidators([]);
}
- this.deviceCredentialsFormGroup.get('credentialsBasic.userName').updateValueAndValidity({
- emitEvent: false,
- onlySelf: true
- });
}
}
diff --git a/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts b/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts
new file mode 100644
index 0000000000..c3427bba68
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/device/device-credentials.module.ts
@@ -0,0 +1,46 @@
+///
+/// Copyright © 2016-2021 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.
+///
+
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { SharedModule } from '@shared/shared.module';
+import { CopyDeviceCredentialsComponent } from './copy-device-credentials.component';
+import { DeviceCredentialsComponent } from './device-credentials.component';
+import { SecurityConfigLwm2mComponent } from './security-config-lwm2m.component';
+import { SecurityConfigLwm2mServerComponent } from './security-config-lwm2m-server.component';
+import { DeviceCredentialsMqttBasicComponent } from './device-credentials-mqtt-basic.component';
+
+@NgModule({
+ declarations: [
+ CopyDeviceCredentialsComponent,
+ DeviceCredentialsComponent,
+ SecurityConfigLwm2mComponent,
+ SecurityConfigLwm2mServerComponent,
+ DeviceCredentialsMqttBasicComponent
+ ],
+ imports: [
+ CommonModule,
+ SharedModule
+ ],
+ exports: [
+ CopyDeviceCredentialsComponent,
+ DeviceCredentialsComponent,
+ SecurityConfigLwm2mComponent,
+ SecurityConfigLwm2mServerComponent,
+ DeviceCredentialsMqttBasicComponent
+ ]
+})
+export class DeviceCredentialsModule { }
diff --git a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html
index 77b7601ed5..200cd88f74 100644
--- a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html
+++ b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.html
@@ -15,8 +15,8 @@
limitations under the License.
-->
-
-
+
+
device.lwm2m-security-config.endpoint
@@ -79,7 +79,7 @@
-
+
@@ -109,15 +109,4 @@
-
-
-
-
-
-
diff --git a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts
index eb920d6190..cbb85e305f 100644
--- a/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts
+++ b/ui-ngx/src/app/modules/home/components/device/security-config-lwm2m.component.ts
@@ -89,6 +89,7 @@ export class SecurityConfigLwm2mComponent implements ControlValueAccessor, Valid
this.lwm2mConfigFormGroup.disable({emitEvent: false});
} else {
this.lwm2mConfigFormGroup.enable({emitEvent: false});
+ this.securityConfigClientUpdateValidators(this.lwm2mConfigFormGroup.get('client.securityConfigClientMode').value);
}
}
@@ -126,21 +127,21 @@ export class SecurityConfigLwm2mComponent implements ControlValueAccessor, Valid
switch (mode) {
case Lwm2mSecurityType.NO_SEC:
this.setValidatorsNoSecX509();
- this.lwm2mConfigFormGroup.get('client.cert').disable();
+ this.lwm2mConfigFormGroup.get('client.cert').disable({emitEvent: false});
break;
case Lwm2mSecurityType.X509:
this.setValidatorsNoSecX509();
- this.lwm2mConfigFormGroup.get('client.cert').enable();
+ this.lwm2mConfigFormGroup.get('client.cert').enable({emitEvent: false});
break;
case Lwm2mSecurityType.PSK:
this.lenMaxKeyClient = LEN_MAX_PSK;
this.setValidatorsPskRpk(mode);
- this.lwm2mConfigFormGroup.get('client.identity').enable();
+ this.lwm2mConfigFormGroup.get('client.identity').enable({emitEvent: false});
break;
case Lwm2mSecurityType.RPK:
this.lenMaxKeyClient = LEN_MAX_PUBLIC_KEY_RPK;
this.setValidatorsPskRpk(mode);
- this.lwm2mConfigFormGroup.get('client.identity').disable();
+ this.lwm2mConfigFormGroup.get('client.identity').disable({emitEvent: false});
break;
}
this.lwm2mConfigFormGroup.get('client.identity').updateValueAndValidity({emitEvent: false});
diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts
index d0ad42b62e..98b50cde33 100644
--- a/ui-ngx/src/app/modules/home/components/home-components.module.ts
+++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts
@@ -110,7 +110,6 @@ import { RuleChainAutocompleteComponent } from '@home/components/rule-chain/rule
import { DeviceProfileProvisionConfigurationComponent } from '@home/components/profile/device-profile-provision-configuration.component';
import { AlarmScheduleComponent } from '@home/components/profile/alarm/alarm-schedule.component';
import { DeviceWizardDialogComponent } from '@home/components/wizard/device-wizard-dialog.component';
-import { DeviceCredentialsComponent } from '@home/components/device/device-credentials.component';
import { AlarmScheduleInfoComponent } from '@home/components/profile/alarm/alarm-schedule-info.component';
import { AlarmScheduleDialogComponent } from '@home/components/profile/alarm/alarm-schedule-dialog.component';
import { EditAlarmDetailsDialogComponent } from '@home/components/profile/alarm/edit-alarm-details-dialog.component';
@@ -120,7 +119,6 @@ import { TenantProfileConfigurationComponent } from '@home/components/profile/te
import { SmsProviderConfigurationComponent } from '@home/components/sms/sms-provider-configuration.component';
import { AwsSnsProviderConfigurationComponent } from '@home/components/sms/aws-sns-provider-configuration.component';
import { TwilioSmsProviderConfigurationComponent } from '@home/components/sms/twilio-sms-provider-configuration.component';
-import { CopyDeviceCredentialsComponent } from '@home/components/device/copy-device-credentials.component';
import { Lwm2mProfileComponentsModule } from '@home/components/profile/device/lwm2m/lwm2m-profile-components.module';
import { DashboardPageComponent } from '@home/components/dashboard-page/dashboard-page.component';
import { DashboardToolbarComponent } from '@home/components/dashboard-page/dashboard-toolbar.component';
@@ -138,11 +136,10 @@ import { EMBED_DASHBOARD_DIALOG_TOKEN } from '@home/components/widget/dialog/emb
import { EdgeDownlinkTableComponent } from '@home/components/edge/edge-downlink-table.component';
import { EdgeDownlinkTableHeaderComponent } from '@home/components/edge/edge-downlink-table-header.component';
import { DisplayWidgetTypesPanelComponent } from '@home/components/dashboard-page/widget-types-panel.component';
-import { SecurityConfigLwm2mComponent } from '@home/components/device/security-config-lwm2m.component';
-import { SecurityConfigLwm2mServerComponent } from '@home/components/device/security-config-lwm2m-server.component';
import { DashboardImageDialogComponent } from '@home/components/dashboard-page/dashboard-image-dialog.component';
import { WidgetContainerComponent } from '@home/components/widget/widget-container.component';
import { SnmpDeviceProfileTransportModule } from '@home/components/profile/device/snpm/snmp-device-profile-transport.module';
+import { DeviceCredentialsModule } from '@home/components/device/device-credentials.module';
@NgModule({
declarations:
@@ -243,10 +240,6 @@ import { SnmpDeviceProfileTransportModule } from '@home/components/profile/devic
DeviceProfileProvisionConfigurationComponent,
AlarmScheduleComponent,
DeviceWizardDialogComponent,
- DeviceCredentialsComponent,
- CopyDeviceCredentialsComponent,
- SecurityConfigLwm2mComponent,
- SecurityConfigLwm2mServerComponent,
AlarmScheduleDialogComponent,
EditAlarmDetailsDialogComponent,
SmsProviderConfigurationComponent,
@@ -272,7 +265,8 @@ import { SnmpDeviceProfileTransportModule } from '@home/components/profile/devic
SharedHomeComponentsModule,
Lwm2mProfileComponentsModule,
SnmpDeviceProfileTransportModule,
- StatesControllerModule
+ StatesControllerModule,
+ DeviceCredentialsModule
],
exports: [
EntitiesTableComponent,
@@ -351,10 +345,6 @@ import { SnmpDeviceProfileTransportModule } from '@home/components/profile/devic
AddDeviceProfileDialogComponent,
RuleChainAutocompleteComponent,
DeviceWizardDialogComponent,
- DeviceCredentialsComponent,
- CopyDeviceCredentialsComponent,
- SecurityConfigLwm2mComponent,
- SecurityConfigLwm2mServerComponent,
AlarmScheduleInfoComponent,
AlarmScheduleComponent,
AlarmScheduleDialogComponent,
diff --git a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html
index 8e1a67a8a9..c453493a2c 100644
--- a/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/pages/device/device-credentials-dialog.component.html
@@ -25,16 +25,26 @@
close
-
+
-
+
-
+
+
+
+
+
+ {{ 'device.loading-device-credentials' | translate }}
+
+
+