Fixed default credentials for created Gateway and refactored gateway basic config

This commit is contained in:
mpetrov 2024-09-06 19:37:27 +03:00
parent 132eadc0d6
commit f9a64731b3
2 changed files with 259 additions and 177 deletions

View File

@ -43,7 +43,7 @@ import {
} from '@home/components/widget/lib/gateway/gateway-remote-configuration-dialog'; } from '@home/components/widget/lib/gateway/gateway-remote-configuration-dialog';
import { DeviceService } from '@core/http/device.service'; import { DeviceService } from '@core/http/device.service';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { take, takeUntil } from 'rxjs/operators';
import { DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models'; import { DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models';
import { import {
GatewayLogLevel, GatewayLogLevel,
@ -61,7 +61,9 @@ import { CommonModule } from '@angular/common';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean } from '@shared/decorators/coercion';
import { import {
GatewayConfigCommand, GatewayConfigCommand,
GatewayConfigValue, LogConfig GatewayConfigSecurity,
GatewayConfigValue,
LogConfig
} from '@home/components/widget/lib/gateway/configuration/models/gateway-configuration.models'; } from '@home/components/widget/lib/gateway/configuration/models/gateway-configuration.models';
@Component({ @Component({
@ -99,13 +101,14 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal
initialCredentialsUpdated = new EventEmitter<DeviceCredentials>(); initialCredentialsUpdated = new EventEmitter<DeviceCredentials>();
StorageTypes = StorageTypes; StorageTypes = StorageTypes;
storageTypes = Object.values(StorageTypes) as StorageTypes[]; storageTypes = Object.values(StorageTypes);
storageTypesTranslationMap = StorageTypesTranslationMap; storageTypesTranslationMap = StorageTypesTranslationMap;
logSavingPeriods = LogSavingPeriodTranslations; logSavingPeriods = LogSavingPeriodTranslations;
localLogsConfigs = Object.keys(LocalLogsConfigs) as LocalLogsConfigs[]; localLogsConfigs = Object.keys(LocalLogsConfigs) as LocalLogsConfigs[];
localLogsConfigTranslateMap = LocalLogsConfigTranslateMap; localLogsConfigTranslateMap = LocalLogsConfigTranslateMap;
securityTypes = GecurityTypesTranslationsMap; securityTypes = GecurityTypesTranslationsMap;
gatewayLogLevel = Object.values(GatewayLogLevel); gatewayLogLevel = Object.values(GatewayLogLevel);
logSelector: FormControl; logSelector: FormControl;
basicFormGroup: FormGroup; basicFormGroup: FormGroup;
@ -119,6 +122,7 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private dialog: MatDialog) { private dialog: MatDialog) {
this.initBasicFormGroup(); this.initBasicFormGroup();
this.observeFormChanges();
this.basicFormGroup.valueChanges this.basicFormGroup.valueChanges
.pipe(takeUntil(this.destroy$)) .pipe(takeUntil(this.destroy$))
.subscribe(value => { .subscribe(value => {
@ -142,14 +146,12 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal
writeValue(basicConfig: GatewayConfigValue): void { writeValue(basicConfig: GatewayConfigValue): void {
this.basicFormGroup.patchValue(basicConfig, {emitEvent: false}); this.basicFormGroup.patchValue(basicConfig, {emitEvent: false});
if (basicConfig?.thingsboard?.security) { this.checkAndFetchCredentials(basicConfig?.thingsboard?.security ?? {} as GatewayConfigSecurity);
this.checkAndFetchCredentials(basicConfig.thingsboard.security);
}
if (basicConfig?.grpc) { if (basicConfig?.grpc) {
this.toggleRpcFields(basicConfig.grpc.enabled); this.toggleRpcFields(basicConfig.grpc.enabled);
} }
const commands = basicConfig?.thingsboard?.statistics?.commands || []; const commands = basicConfig?.thingsboard?.statistics?.commands ?? [];
commands.forEach(command => this.addCommand(command, false)); commands.forEach((command: GatewayConfigCommand) => this.addCommand(command, false));
} }
validate(): ValidationErrors | null { validate(): ValidationErrors | null {
@ -251,7 +253,7 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal
data: { data: {
gatewayName: gateway.name gatewayName: gateway.name
} }
}).afterClosed().subscribe( }).afterClosed().pipe(take(1)).subscribe(
(res) => { (res) => {
if (!res) { if (!res) {
this.basicFormGroup.get('thingsboard.remoteConfiguration').setValue(true, {emitEvent: false}); this.basicFormGroup.get('thingsboard.remoteConfiguration').setValue(true, {emitEvent: false});
@ -273,115 +275,145 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal
this.commandFormArray().push(commandFormGroup, { emitEvent }); this.commandFormArray().push(commandFormGroup, { emitEvent });
} }
private initBasicFormGroup(): void { private initBasicFormGroup(): void {
this.basicFormGroup = this.fb.group({ this.basicFormGroup = this.fb.group({
thingsboard: this.fb.group({ thingsboard: this.initThingsboardFormGroup(),
storage: this.initStorageFormGroup(),
grpc: this.initGrpcFormGroup(),
connectors: this.fb.array([]),
logs: this.initLogsFormGroup(),
});
}
private initThingsboardFormGroup(): FormGroup {
return this.fb.group({
host: [window.location.hostname, [Validators.required, Validators.pattern(/^[^\s]+$/)]], host: [window.location.hostname, [Validators.required, Validators.pattern(/^[^\s]+$/)]],
port: [1883, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], port: [1883, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]],
remoteShell: [false, []], remoteShell: [false],
remoteConfiguration: [true, []], remoteConfiguration: [true],
checkConnectorsConfigurationInSeconds: [60, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], checkConnectorsConfigurationInSeconds: [60, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
statistics: this.fb.group({ statistics: this.fb.group({
enable: [true, []], enable: [true],
statsSendPeriodInSeconds: [3600, [Validators.required, Validators.min(60), Validators.pattern(/^-?[0-9]+$/)]], statsSendPeriodInSeconds: [3600, [Validators.required, Validators.min(60), Validators.pattern(/^-?[0-9]+$/)]],
commands: this.fb.array([], []) commands: this.fb.array([])
}), }),
maxPayloadSizeBytes: [8196, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], maxPayloadSizeBytes: [8196, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]],
minPackSendDelayMS: [50, [Validators.required, Validators.min(10), Validators.pattern(/^-?[0-9]+$/)]], minPackSendDelayMS: [50, [Validators.required, Validators.min(10), Validators.pattern(/^-?[0-9]+$/)]],
minPackSizeToSend: [500, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], minPackSizeToSend: [500, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]],
handleDeviceRenaming: [true, []], handleDeviceRenaming: [true],
checkingDeviceActivity: this.fb.group({ checkingDeviceActivity: this.initCheckingDeviceActivityFormGroup(),
checkDeviceInactivity: [false, []], security: this.initSecurityFormGroup(),
inactivityTimeoutSeconds: [200, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], qos: [1, [Validators.required, Validators.min(0), Validators.max(1), Validators.pattern(/^[^.\s]+$/)]]
inactivityCheckPeriodSeconds: [500, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] });
}), }
security: this.fb.group({
type: [SecurityTypes.ACCESS_TOKEN, [Validators.required]], private initStorageFormGroup(): FormGroup {
accessToken: [null, [Validators.required, Validators.pattern(/^[^.\s]+$/)]], return this.fb.group({
clientId: [null, [Validators.pattern(/^[^.\s]+$/)]],
username: [null, [Validators.pattern(/^[^.\s]+$/)]],
password: [null, [Validators.pattern(/^[^.\s]+$/)]],
caCert: [null, []],
cert: [null, []],
privateKey: [null, []],
}),
qos: [1, [Validators.min(0), Validators.max(1), Validators.required, Validators.pattern(/^[^.\s]+$/)]]
}),
storage: this.fb.group({
type: [StorageTypes.MEMORY, [Validators.required]], type: [StorageTypes.MEMORY, [Validators.required]],
read_records_count: [ read_records_count: [100, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
100, [Validators.min(1), max_records_count: [100000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
Validators.pattern(/^-?[0-9]+$/), Validators.required, Validators.pattern(/^[^.\s]+$/)]
],
max_records_count: [
100000,
[Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required, Validators.pattern(/^[^.\s]+$/)]
],
data_folder_path: ['./data/', [Validators.required]], data_folder_path: ['./data/', [Validators.required]],
max_file_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], max_file_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
max_read_records_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], max_read_records_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
max_records_per_file: [10000, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], max_records_per_file: [10000, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
data_file_path: ['./data/data.db', [Validators.required]], data_file_path: ['./data/data.db', [Validators.required]],
messages_ttl_check_in_hours: [1, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], messages_ttl_check_in_hours: [1, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
messages_ttl_in_days: [7, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], messages_ttl_in_days: [7, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]]
});
}
}), private initGrpcFormGroup(): FormGroup {
grpc: this.fb.group({ return this.fb.group({
enabled: [false, []], enabled: [false],
serverPort: [9595, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], serverPort: [9595, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]],
keepAliveTimeMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], keepAliveTimeMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
keepAliveTimeoutMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], keepAliveTimeoutMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
keepalivePermitWithoutCalls: [true, []], keepalivePermitWithoutCalls: [true],
maxPingsWithoutData: [0, [Validators.required, Validators.min(0), Validators.pattern(/^-?[0-9]+$/)]], maxPingsWithoutData: [0, [Validators.required, Validators.min(0), Validators.pattern(/^-?[0-9]+$/)]],
minTimeBetweenPingsMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], minTimeBetweenPingsMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
minPingIntervalWithoutDataMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], minPingIntervalWithoutDataMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]]
}), });
connectors: this.fb.array([]), }
logs: this.fb.group({
private initLogsFormGroup(): FormGroup {
return this.fb.group({
dateFormat: ['%Y-%m-%d %H:%M:%S', [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], dateFormat: ['%Y-%m-%d %H:%M:%S', [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]],
logFormat: ['%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s', logFormat: [
[Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], '%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s',
[Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]
],
type: ['remote', [Validators.required]], type: ['remote', [Validators.required]],
remote: this.fb.group({ remote: this.fb.group({
enabled: [false], enabled: [false],
logLevel: [GatewayLogLevel.INFO, [Validators.required]], logLevel: [GatewayLogLevel.INFO, [Validators.required]]
}), }),
local: this.fb.group({}) local: this.fb.group({})
})
}); });
this.basicFormGroup.get('thingsboard.security.password').valueChanges.subscribe(password => {
if (password && password !== '') {
this.basicFormGroup.get('thingsboard.security.username').setValidators([Validators.required]);
} else {
this.basicFormGroup.get('thingsboard.security.username').clearValidators();
} }
this.basicFormGroup.get('thingsboard.security.username').updateValueAndValidity({emitEvent: false});
private initCheckingDeviceActivityFormGroup(): FormGroup {
return this.fb.group({
checkDeviceInactivity: [false],
inactivityTimeoutSeconds: [200, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]],
inactivityCheckPeriodSeconds: [500, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]]
}); });
}
this.toggleRpcFields(false); private initSecurityFormGroup(): FormGroup {
return this.fb.group({
type: [SecurityTypes.ACCESS_TOKEN, [Validators.required]],
accessToken: [null, [Validators.required, Validators.pattern(/^[^.\s]+$/)]],
clientId: [null, [Validators.pattern(/^[^.\s]+$/)]],
username: [null, [Validators.pattern(/^[^.\s]+$/)]],
password: [null, [Validators.pattern(/^[^.\s]+$/)]],
caCert: [null],
cert: [null],
privateKey: [null]
});
}
this.basicFormGroup.get('thingsboard.remoteConfiguration').valueChanges.subscribe(enabled => { private observeFormChanges(): void {
this.observeSecurityPasswordChanges();
this.observeRemoteConfigurationChanges();
this.observeDeviceActivityChanges();
this.observeSecurityTypeChanges();
this.observeStorageTypeChanges();
}
private observeSecurityPasswordChanges(): void {
const securityUsername = this.basicFormGroup.get('thingsboard.security.username');
this.basicFormGroup.get('thingsboard.security.password').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(password => {
if (password && password !== '') {
securityUsername.setValidators([Validators.required]);
} else {
securityUsername.clearValidators();
}
securityUsername.updateValueAndValidity({ emitEvent: false });
});
}
private observeRemoteConfigurationChanges(): void {
this.basicFormGroup.get('thingsboard.remoteConfiguration').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(enabled => {
if (!enabled) { if (!enabled) {
this.openConfigurationConfirmDialog(); this.openConfigurationConfirmDialog();
} }
}); });
this.logSelector = this.fb.control(LocalLogsConfigs.service); this.logSelector = this.fb.control(LocalLogsConfigs.service);
for (const key of Object.keys(LocalLogsConfigs)) {
for (const localLogsConfigsKey of Object.keys(LocalLogsConfigs)) { this.addLocalLogConfig(key, {} as LogConfig);
this.addLocalLogConfig(localLogsConfigsKey, {} as LogConfig); }
} }
private observeDeviceActivityChanges(): void {
const checkingDeviceActivityGroup = this.basicFormGroup.get('thingsboard.checkingDeviceActivity') as FormGroup; const checkingDeviceActivityGroup = this.basicFormGroup.get('thingsboard.checkingDeviceActivity') as FormGroup;
checkingDeviceActivityGroup.get('checkDeviceInactivity').valueChanges.subscribe(enabled => { checkingDeviceActivityGroup.get('checkDeviceInactivity').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(enabled => {
checkingDeviceActivityGroup.updateValueAndValidity(); checkingDeviceActivityGroup.updateValueAndValidity();
const validators = [Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)];
if (enabled) { if (enabled) {
checkingDeviceActivityGroup.get('inactivityTimeoutSeconds') checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').setValidators(validators);
.setValidators([Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]); checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').setValidators(validators);
checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds')
.setValidators([Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]);
} else { } else {
checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').clearValidators(); checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').clearValidators();
checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').clearValidators(); checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').clearValidators();
@ -390,97 +422,147 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal
checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').updateValueAndValidity({ emitEvent: false }); checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').updateValueAndValidity({ emitEvent: false });
}); });
this.basicFormGroup.get('grpc.enabled').valueChanges.subscribe(value => { this.basicFormGroup.get('grpc.enabled').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
this.toggleRpcFields(value); this.toggleRpcFields(value);
}); });
const securityGroup = this.basicFormGroup.get('thingsboard.security') as FormGroup;
securityGroup.get('type').valueChanges.subscribe(type => {
this.removeAllSecurityValidators();
if (type === SecurityTypes.ACCESS_TOKEN) {
securityGroup.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]);
securityGroup.get('accessToken').updateValueAndValidity();
} else if (type === SecurityTypes.TLS_PRIVATE_KEY) {
securityGroup.get('caCert').addValidators([Validators.required]);
securityGroup.get('caCert').updateValueAndValidity();
securityGroup.get('privateKey').addValidators([Validators.required]);
securityGroup.get('privateKey').updateValueAndValidity();
securityGroup.get('cert').addValidators([Validators.required]);
securityGroup.get('cert').updateValueAndValidity();
} else if (type === SecurityTypes.TLS_ACCESS_TOKEN) {
securityGroup.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]);
securityGroup.get('accessToken').updateValueAndValidity();
securityGroup.get('caCert').addValidators([Validators.required]);
securityGroup.get('caCert').updateValueAndValidity();
} else if (type === SecurityTypes.USERNAME_PASSWORD) {
securityGroup.addValidators([this.atLeastOneRequired(Validators.required, ['clientId', 'username'])]);
} }
private observeSecurityTypeChanges(): void {
const securityGroup = this.basicFormGroup.get('thingsboard.security') as FormGroup;
securityGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(type => {
this.removeAllSecurityValidators();
switch (type) {
case SecurityTypes.ACCESS_TOKEN:
this.addAccessTokenValidators(securityGroup);
break;
case SecurityTypes.TLS_PRIVATE_KEY:
this.addTlsPrivateKeyValidators(securityGroup);
break;
case SecurityTypes.TLS_ACCESS_TOKEN:
this.addTlsAccessTokenValidators(securityGroup);
break;
case SecurityTypes.USERNAME_PASSWORD:
securityGroup.addValidators([this.atLeastOneRequired(Validators.required, ['clientId', 'username'])]);
break;
}
securityGroup.updateValueAndValidity(); securityGroup.updateValueAndValidity();
}); });
securityGroup.get('caCert').valueChanges.subscribe(() => this.cd.detectChanges()); ['caCert', 'privateKey', 'cert'].forEach(field => {
securityGroup.get('privateKey').valueChanges.subscribe(() => this.cd.detectChanges()); securityGroup.get(field).valueChanges.pipe(takeUntil(this.destroy$)).subscribe(() => this.cd.detectChanges());
securityGroup.get('cert').valueChanges.subscribe(() => this.cd.detectChanges()); });
}
private observeStorageTypeChanges(): void {
const storageGroup = this.basicFormGroup.get('storage') as FormGroup; const storageGroup = this.basicFormGroup.get('storage') as FormGroup;
storageGroup.get('type').valueChanges.subscribe(type => {
storageGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(type => {
this.removeAllStorageValidators(); this.removeAllStorageValidators();
if (type === StorageTypes.MEMORY) {
storageGroup.get('read_records_count').addValidators( switch (type) {
[Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); case StorageTypes.MEMORY:
storageGroup.get('max_records_count').addValidators( this.addMemoryStorageValidators(storageGroup);
[Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); break;
storageGroup.get('read_records_count').updateValueAndValidity({emitEvent: false}); case StorageTypes.FILE:
storageGroup.get('max_records_count').updateValueAndValidity({emitEvent: false}); this.addFileStorageValidators(storageGroup);
} else if (type === StorageTypes.FILE) { break;
storageGroup.get('data_folder_path').addValidators([Validators.required]); case StorageTypes.SQLITE:
storageGroup.get('max_file_count').addValidators( this.addSqliteStorageValidators(storageGroup);
[Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); break;
storageGroup.get('max_read_records_count').addValidators(
[Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]);
storageGroup.get('max_records_per_file').addValidators(
[Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]);
storageGroup.get('data_folder_path').updateValueAndValidity({emitEvent: false});
storageGroup.get('max_file_count').updateValueAndValidity({emitEvent: false});
storageGroup.get('max_read_records_count').updateValueAndValidity({emitEvent: false});
storageGroup.get('max_records_per_file').updateValueAndValidity({emitEvent: false});
} else if (type === StorageTypes.SQLITE) {
storageGroup.get('data_file_path').addValidators([Validators.required]);
storageGroup.get('messages_ttl_check_in_hours').addValidators(
[Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]);
storageGroup.get('messages_ttl_in_days').addValidators(
[Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]);
storageGroup.get('data_file_path').updateValueAndValidity({emitEvent: false});
storageGroup.get('messages_ttl_check_in_hours').updateValueAndValidity({emitEvent: false});
storageGroup.get('messages_ttl_in_days').updateValueAndValidity({emitEvent: false});
} }
}); });
} }
private checkAndFetchCredentials(security: any = {}): void { private addAccessTokenValidators(group: FormGroup): void {
if (security.type !== SecurityTypes.TLS_PRIVATE_KEY) { group.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]);
this.deviceService.getDeviceCredentials(this.device.id).subscribe(credentials => { group.get('accessToken').updateValueAndValidity();
}
private addTlsPrivateKeyValidators(group: FormGroup): void {
['caCert', 'privateKey', 'cert'].forEach(field => {
group.get(field).addValidators([Validators.required]);
group.get(field).updateValueAndValidity();
});
}
private addTlsAccessTokenValidators(group: FormGroup): void {
this.addAccessTokenValidators(group);
group.get('caCert').addValidators([Validators.required]);
group.get('caCert').updateValueAndValidity();
}
private addMemoryStorageValidators(group: FormGroup): void {
group.get('read_records_count').addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]);
group.get('max_records_count').addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]);
group.get('read_records_count').updateValueAndValidity({ emitEvent: false });
group.get('max_records_count').updateValueAndValidity({ emitEvent: false });
}
private addFileStorageValidators(group: FormGroup): void {
['data_folder_path', 'max_file_count', 'max_read_records_count', 'max_records_per_file'].forEach(field => {
group.get(field).addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]);
group.get(field).updateValueAndValidity({ emitEvent: false });
});
}
private addSqliteStorageValidators(group: FormGroup): void {
['data_file_path', 'messages_ttl_check_in_hours', 'messages_ttl_in_days'].forEach(field => {
group.get(field).addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]);
group.get(field).updateValueAndValidity({ emitEvent: false });
});
}
private checkAndFetchCredentials(security: GatewayConfigSecurity): void {
if (security.type === SecurityTypes.TLS_PRIVATE_KEY) {
return;
}
this.deviceService.getDeviceCredentials(this.device.id).pipe(takeUntil(this.destroy$)).subscribe(credentials => {
this.initialCredentialsUpdated.emit(credentials); this.initialCredentialsUpdated.emit(credentials);
if (credentials.credentialsType === DeviceCredentialsType.ACCESS_TOKEN || security.type === SecurityTypes.TLS_ACCESS_TOKEN) { this.updateSecurityType(security, credentials);
this.basicFormGroup.get('thingsboard.security.type') this.updateCredentials(credentials, security);
.setValue(security.type === SecurityTypes.TLS_ACCESS_TOKEN });
? SecurityTypes.TLS_ACCESS_TOKEN }
: SecurityTypes.ACCESS_TOKEN, {emitEvent: false});
private updateSecurityType(security, credentials: DeviceCredentials): void {
const isAccessToken = credentials.credentialsType === DeviceCredentialsType.ACCESS_TOKEN
|| security.type === SecurityTypes.TLS_ACCESS_TOKEN;
const securityType = isAccessToken
? (security.type === SecurityTypes.TLS_ACCESS_TOKEN ? SecurityTypes.TLS_ACCESS_TOKEN : SecurityTypes.ACCESS_TOKEN)
: (credentials.credentialsType === DeviceCredentialsType.MQTT_BASIC ? SecurityTypes.USERNAME_PASSWORD : null);
if (securityType) {
this.basicFormGroup.get('thingsboard.security.type').setValue(securityType, { emitEvent: false });
}
}
private updateCredentials(credentials: DeviceCredentials, security: GatewayConfigSecurity): void {
switch (credentials.credentialsType) {
case DeviceCredentialsType.ACCESS_TOKEN:
this.updateAccessTokenCredentials(credentials, security);
break;
case DeviceCredentialsType.MQTT_BASIC:
this.updateMqttBasicCredentials(credentials);
break;
case DeviceCredentialsType.X509_CERTIFICATE:
break;
}
}
private updateAccessTokenCredentials(credentials: DeviceCredentials, security: GatewayConfigSecurity): void {
this.basicFormGroup.get('thingsboard.security.accessToken').setValue(credentials.credentialsId, { emitEvent: false }); this.basicFormGroup.get('thingsboard.security.accessToken').setValue(credentials.credentialsId, { emitEvent: false });
if (security.type === SecurityTypes.TLS_ACCESS_TOKEN) { if (security.type === SecurityTypes.TLS_ACCESS_TOKEN) {
this.basicFormGroup.get('thingsboard.security.caCert').setValue(security.caCert, { emitEvent: false }); this.basicFormGroup.get('thingsboard.security.caCert').setValue(security.caCert, { emitEvent: false });
} }
} else if (credentials.credentialsType === DeviceCredentialsType.MQTT_BASIC) { }
private updateMqttBasicCredentials(credentials: DeviceCredentials): void {
const parsedValue = JSON.parse(credentials.credentialsValue); const parsedValue = JSON.parse(credentials.credentialsValue);
this.basicFormGroup.get('thingsboard.security.type').setValue(SecurityTypes.USERNAME_PASSWORD, {emitEvent: false});
this.basicFormGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId, { emitEvent: false }); this.basicFormGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId, { emitEvent: false });
this.basicFormGroup.get('thingsboard.security.username').setValue(parsedValue.userName, { emitEvent: false }); this.basicFormGroup.get('thingsboard.security.username').setValue(parsedValue.userName, { emitEvent: false });
this.basicFormGroup.get('thingsboard.security.password') this.basicFormGroup.get('thingsboard.security.password').setValue(parsedValue.password, { emitEvent: false });
.setValue(parsedValue.password, {emitEvent: false});
} else if (credentials.credentialsType === DeviceCredentialsType.X509_CERTIFICATE) {
//if sertificate is present set sertificate as present
}
});
}
} }
} }

View File

@ -69,8 +69,8 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
constructor(private fb: FormBuilder, constructor(private fb: FormBuilder,
private attributeService: AttributeService, private attributeService: AttributeService,
private deviceService: DeviceService, private deviceService: DeviceService,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef
private dialog: MatDialog) { ) {
this.gatewayConfigGroup = this.fb.group({ this.gatewayConfigGroup = this.fb.group({
basicConfig: [], basicConfig: [],
@ -361,7 +361,7 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
} }
private updateFormControls(thingsboard: GatewayGeneralConfig): void { private updateFormControls(thingsboard: GatewayGeneralConfig): void {
const { type, accessToken, ...securityConfig } = thingsboard.security || {}; const { type, accessToken, ...securityConfig } = thingsboard.security ?? {};
this.initialCredentials = { this.initialCredentials = {
deviceId: this.device as DeviceId, deviceId: this.device as DeviceId,