Browse Source
* UI: Refactoring LWM2M; fixed build ui rule node * UI: Refactoring LWM2M security configpull/4525/head
committed by
GitHub
28 changed files with 925 additions and 1053 deletions
@ -0,0 +1,79 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
--> |
||||
|
<section [formGroup]="serverFormGroup" fxLayout="column"> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label translate>device.lwm2m-security-config.mode</mat-label> |
||||
|
<mat-select formControlName="securityMode"> |
||||
|
<mat-option *ngFor="let securityType of securityConfigLwM2MTypes" [value]="securityType"> |
||||
|
{{ lwm2mSecurityTypeTranslationMap.get(securityType) }} |
||||
|
</mat-option> |
||||
|
</mat-select> |
||||
|
</mat-form-field> |
||||
|
<div [fxShow]="serverFormGroup.get('securityMode').value !== securityConfigLwM2MType.NO_SEC"> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label>{{ 'device.lwm2m-security-config.client-publicKey-or-id' | translate }}</mat-label> |
||||
|
<textarea matInput |
||||
|
#clientPublicKeyOrId |
||||
|
[maxlength]="lenMaxClientPublicKeyOrId" |
||||
|
cdkTextareaAutosize |
||||
|
cdkAutosizeMinRows="1" |
||||
|
cols="1" |
||||
|
formControlName="clientPublicKeyOrId" |
||||
|
required> |
||||
|
</textarea> |
||||
|
<mat-hint align="end">{{clientPublicKeyOrId.value?.length || 0}}/{{lenMaxClientPublicKeyOrId}}</mat-hint> |
||||
|
<mat-error *ngIf="serverFormGroup.get('clientPublicKeyOrId').hasError('required')"> |
||||
|
{{ 'device.lwm2m-security-config.client-publicKey-or-id-required' | translate }} |
||||
|
</mat-error> |
||||
|
<mat-error *ngIf="serverFormGroup.get('clientPublicKeyOrId').hasError('pattern')"> |
||||
|
{{ 'device.lwm2m-security-config.client-publicKey-or-id-pattern' | translate }} |
||||
|
</mat-error> |
||||
|
<mat-error *ngIf="(serverFormGroup.get('clientPublicKeyOrId').hasError('maxlength') || |
||||
|
serverFormGroup.get('clientPublicKeyOrId').hasError('minlength'))"> |
||||
|
{{ 'device.lwm2m-security-config.client-publicKey-or-id-length' | translate: { |
||||
|
count: lenMaxClientPublicKeyOrId |
||||
|
} }} |
||||
|
</mat-error> |
||||
|
</mat-form-field> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label>{{ 'device.lwm2m-security-config.client-secret-key' | translate }}</mat-label> |
||||
|
<textarea matInput |
||||
|
#clientSecretKey |
||||
|
[maxlength]="lengthClientSecretKey" |
||||
|
cdkTextareaAutosize |
||||
|
cdkAutosizeMinRows="1" |
||||
|
cols="1" |
||||
|
formControlName="clientSecretKey" |
||||
|
required> |
||||
|
</textarea> |
||||
|
<mat-hint align="end">{{clientSecretKey.value?.length || 0}}/{{lengthClientSecretKey}}</mat-hint> |
||||
|
<mat-error *ngIf="serverFormGroup.get('clientSecretKey').hasError('required')"> |
||||
|
{{ 'device.lwm2m-security-config.client-secret-key-required' | translate }} |
||||
|
</mat-error> |
||||
|
<mat-error *ngIf="serverFormGroup.get('clientSecretKey').hasError('pattern')"> |
||||
|
{{ 'device.lwm2m-security-config.client-secret-key-pattern' | translate }} |
||||
|
</mat-error> |
||||
|
<mat-error *ngIf="(serverFormGroup.get('clientSecretKey').hasError('maxlength') || |
||||
|
serverFormGroup.get('clientSecretKey').hasError('minlength'))"> |
||||
|
{{ 'device.lwm2m-security-config.client-secret-key-length' | translate: { |
||||
|
count: lengthClientSecretKey |
||||
|
} }} |
||||
|
</mat-error> |
||||
|
</mat-form-field> |
||||
|
</div> |
||||
|
</section> |
||||
@ -0,0 +1,20 @@ |
|||||
|
/** |
||||
|
* 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. |
||||
|
*/ |
||||
|
:host ::ng-deep { |
||||
|
textarea.mat-input-element.cdk-textarea-autosize { |
||||
|
box-sizing: content-box; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,176 @@ |
|||||
|
///
|
||||
|
/// 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, OnDestroy } from '@angular/core'; |
||||
|
import { |
||||
|
ControlValueAccessor, |
||||
|
FormBuilder, |
||||
|
FormGroup, |
||||
|
NG_VALIDATORS, |
||||
|
NG_VALUE_ACCESSOR, |
||||
|
ValidationErrors, |
||||
|
Validator, |
||||
|
Validators |
||||
|
} from '@angular/forms'; |
||||
|
import { |
||||
|
KEY_REGEXP_HEX_DEC, |
||||
|
LEN_MAX_PRIVATE_KEY, |
||||
|
LEN_MAX_PSK, |
||||
|
LEN_MAX_PUBLIC_KEY_RPK, |
||||
|
LEN_MAX_PUBLIC_KEY_X509, |
||||
|
Lwm2mSecurityType, |
||||
|
Lwm2mSecurityTypeTranslationMap, |
||||
|
ServerSecurityConfig |
||||
|
} from '@shared/models/lwm2m-security-config.models'; |
||||
|
import { takeUntil } from 'rxjs/operators'; |
||||
|
import { Subject } from 'rxjs'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-security-config-lwm2m-server', |
||||
|
templateUrl: './security-config-lwm2m-server.component.html', |
||||
|
styleUrls: ['./security-config-lwm2m-server.component.scss'], |
||||
|
providers: [ |
||||
|
{ |
||||
|
provide: NG_VALUE_ACCESSOR, |
||||
|
useExisting: forwardRef(() => SecurityConfigLwm2mServerComponent), |
||||
|
multi: true |
||||
|
}, |
||||
|
{ |
||||
|
provide: NG_VALIDATORS, |
||||
|
useExisting: forwardRef(() => SecurityConfigLwm2mServerComponent), |
||||
|
multi: true |
||||
|
} |
||||
|
] |
||||
|
}) |
||||
|
|
||||
|
export class SecurityConfigLwm2mServerComponent implements OnDestroy, ControlValueAccessor, Validator { |
||||
|
|
||||
|
serverFormGroup: FormGroup; |
||||
|
securityConfigLwM2MType = Lwm2mSecurityType; |
||||
|
securityConfigLwM2MTypes = Object.values(Lwm2mSecurityType); |
||||
|
lwm2mSecurityTypeTranslationMap = Lwm2mSecurityTypeTranslationMap; |
||||
|
lenMinClientPublicKeyOrId = 0; |
||||
|
lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
||||
|
lengthClientSecretKey = LEN_MAX_PRIVATE_KEY; |
||||
|
|
||||
|
private destroy$ = new Subject(); |
||||
|
private propagateChange = (v: any) => {}; |
||||
|
|
||||
|
constructor(private fb: FormBuilder) { |
||||
|
this.serverFormGroup = this.fb.group({ |
||||
|
securityMode: [Lwm2mSecurityType.NO_SEC], |
||||
|
clientPublicKeyOrId: [''], |
||||
|
clientSecretKey: [''] |
||||
|
}); |
||||
|
this.serverFormGroup.get('securityMode').valueChanges.pipe( |
||||
|
takeUntil(this.destroy$) |
||||
|
).subscribe((securityMode) => { |
||||
|
this.updateValidate(securityMode); |
||||
|
}); |
||||
|
|
||||
|
this.serverFormGroup.valueChanges.pipe( |
||||
|
takeUntil(this.destroy$) |
||||
|
).subscribe((value) => { |
||||
|
this.propagateChange(value); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
writeValue(value: any): void { |
||||
|
if (value) { |
||||
|
this.updateValueFields(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
registerOnChange(fn: any): void { |
||||
|
this.propagateChange = fn; |
||||
|
} |
||||
|
|
||||
|
registerOnTouched(fn: any): void { |
||||
|
} |
||||
|
|
||||
|
setDisabledState(isDisabled: boolean): void { |
||||
|
if (isDisabled) { |
||||
|
this.serverFormGroup.disable({emitEvent: false}); |
||||
|
} else { |
||||
|
this.serverFormGroup.enable({emitEvent: false}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
validate(control): ValidationErrors | null { |
||||
|
return this.serverFormGroup.valid ? null : { |
||||
|
securityConfig: {valid: false} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy() { |
||||
|
this.destroy$.next(); |
||||
|
this.destroy$.complete(); |
||||
|
} |
||||
|
|
||||
|
private updateValueFields(serverData: ServerSecurityConfig): void { |
||||
|
this.serverFormGroup.patchValue(serverData, {emitEvent: false}); |
||||
|
this.updateValidate(serverData.securityMode, true); |
||||
|
} |
||||
|
|
||||
|
private updateValidate(securityMode: Lwm2mSecurityType, initValue = false): void { |
||||
|
switch (securityMode) { |
||||
|
case Lwm2mSecurityType.NO_SEC: |
||||
|
this.serverFormGroup.get('clientPublicKeyOrId').clearValidators(); |
||||
|
this.serverFormGroup.get('clientSecretKey').clearValidators(); |
||||
|
break; |
||||
|
case Lwm2mSecurityType.PSK: |
||||
|
this.lenMinClientPublicKeyOrId = 0; |
||||
|
this.lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
||||
|
this.lengthClientSecretKey = LEN_MAX_PSK; |
||||
|
this.setValidatorsSecurity(securityMode); |
||||
|
break; |
||||
|
case Lwm2mSecurityType.RPK: |
||||
|
this.lenMinClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
||||
|
this.lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
||||
|
this.lengthClientSecretKey = LEN_MAX_PRIVATE_KEY; |
||||
|
this.setValidatorsSecurity(securityMode); |
||||
|
break; |
||||
|
case Lwm2mSecurityType.X509: |
||||
|
this.lenMinClientPublicKeyOrId = 0; |
||||
|
this.lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_X509; |
||||
|
this.lengthClientSecretKey = LEN_MAX_PRIVATE_KEY; |
||||
|
this.setValidatorsSecurity(securityMode); |
||||
|
break; |
||||
|
} |
||||
|
this.serverFormGroup.get('clientPublicKeyOrId').updateValueAndValidity({emitEvent: false}); |
||||
|
this.serverFormGroup.get('clientSecretKey').updateValueAndValidity({emitEvent: !initValue}); |
||||
|
} |
||||
|
|
||||
|
private setValidatorsSecurity = (securityMode: Lwm2mSecurityType): void => { |
||||
|
if (securityMode === Lwm2mSecurityType.PSK) { |
||||
|
this.serverFormGroup.get('clientPublicKeyOrId').setValidators([Validators.required]); |
||||
|
} else { |
||||
|
this.serverFormGroup.get('clientPublicKeyOrId').setValidators([ |
||||
|
Validators.required, |
||||
|
Validators.pattern(KEY_REGEXP_HEX_DEC), |
||||
|
Validators.minLength(this.lenMinClientPublicKeyOrId), |
||||
|
Validators.maxLength(this.lenMaxClientPublicKeyOrId) |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
this.serverFormGroup.get('clientSecretKey').setValidators([ |
||||
|
Validators.required, |
||||
|
Validators.pattern(KEY_REGEXP_HEX_DEC), |
||||
|
Validators.minLength(this.lengthClientSecretKey), |
||||
|
Validators.maxLength(this.lengthClientSecretKey) |
||||
|
]); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,143 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
--> |
||||
|
<form [formGroup]="lwm2mConfigFormGroup" (ngSubmit)="save()" style="min-width: 400px;"> |
||||
|
<mat-toolbar fxLayout="row" color="primary"> |
||||
|
<h2>{{ title }}</h2> |
||||
|
<span fxFlex></span> |
||||
|
<button mat-button mat-icon-button |
||||
|
(click)="cancel()" |
||||
|
type="button"> |
||||
|
<mat-icon class="material-icons">close</mat-icon> |
||||
|
</button> |
||||
|
</mat-toolbar> |
||||
|
<div mat-dialog-content> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label translate>device.lwm2m-security-config.endpoint</mat-label> |
||||
|
<input matInput type="text" formControlName="endPoint" required> |
||||
|
<mat-error *ngIf="lwm2mConfigFormGroup.get('endPoint').hasError('required')"> |
||||
|
{{ 'device.lwm2m-security-config.endpoint-required' | translate }} |
||||
|
</mat-error> |
||||
|
</mat-form-field> |
||||
|
<mat-tab-group (selectedTabChange)="tabChanged($event)"> |
||||
|
<mat-tab label="{{ 'device.lwm2m-security-config.client-tab' | translate }}"> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label translate>device.lwm2m-security-config.mode</mat-label> |
||||
|
<mat-select formControlName="securityConfigClientMode"> |
||||
|
<mat-option *ngFor="let securityConfigClientMode of securityConfigLwM2MTypes" |
||||
|
[value]="securityConfigClientMode"> |
||||
|
{{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityConfigClientMode]) }} |
||||
|
</mat-option> |
||||
|
</mat-select> |
||||
|
</mat-form-field> |
||||
|
<div *ngIf="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.PSK"> |
||||
|
<mat-form-field class="mat-block"> |
||||
|
<mat-label>{{ 'device.lwm2m-security-config.identity' | translate }}</mat-label> |
||||
|
<input matInput type="text" formControlName="identity" required> |
||||
|
<mat-error *ngIf="lwm2mConfigFormGroup.get('identity').hasError('required')"> |
||||
|
{{ 'device.lwm2m-security-config.identity-required' | translate }} |
||||
|
</mat-error> |
||||
|
</mat-form-field> |
||||
|
</div> |
||||
|
<mat-form-field class="mat-block" *ngIf="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.RPK || |
||||
|
lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.PSK"> |
||||
|
<mat-label>{{ 'device.lwm2m-security-config.client-key' | translate }}</mat-label> |
||||
|
<textarea matInput |
||||
|
#key |
||||
|
maxlength="{{lenMaxKeyClient}}" |
||||
|
cdkTextareaAutosize |
||||
|
cdkAutosizeMinRows="1" |
||||
|
cols="1" |
||||
|
formControlName="key" |
||||
|
required> |
||||
|
</textarea> |
||||
|
<mat-hint align="end">{{key.value?.length || 0}}/{{lenMaxKeyClient}}</mat-hint> |
||||
|
<mat-error *ngIf="lwm2mConfigFormGroup.get('key').hasError('required')"> |
||||
|
{{ 'device.lwm2m-security-config.client-key-required' | translate }} |
||||
|
</mat-error> |
||||
|
<mat-error *ngIf="lwm2mConfigFormGroup.get('key').hasError('pattern')"> |
||||
|
{{ 'device.lwm2m-security-config.client-key-pattern' | translate }} |
||||
|
</mat-error> |
||||
|
<mat-error *ngIf="(lwm2mConfigFormGroup.get('key').hasError('maxlength') || |
||||
|
lwm2mConfigFormGroup.get('key').hasError('minlength'))"> |
||||
|
{{ 'device.lwm2m-security-config.client-key-length' | translate: { |
||||
|
count: lenMaxKeyClient |
||||
|
} }} |
||||
|
</mat-error> |
||||
|
</mat-form-field> |
||||
|
<mat-checkbox formControlName="x509" color="primary" |
||||
|
*ngIf="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.X509"> |
||||
|
{{ 'device.lwm2m-security-config.client-certificate' | translate }} |
||||
|
</mat-checkbox> |
||||
|
</mat-tab> |
||||
|
<mat-tab label="{{ 'device.lwm2m-security-config.bootstrap-tab' | translate }}"> |
||||
|
<div style="padding: 2px;"> |
||||
|
<mat-accordion multi="true" class="mat-body-1"> |
||||
|
<mat-expansion-panel> |
||||
|
<mat-expansion-panel-header> |
||||
|
<mat-panel-title> |
||||
|
{{ 'device.lwm2m-security-config.bootstrap-server' | translate }} |
||||
|
</mat-panel-title> |
||||
|
</mat-expansion-panel-header> |
||||
|
<ng-template matExpansionPanelContent> |
||||
|
<tb-security-config-lwm2m-server |
||||
|
formControlName="bootstrapServer"> |
||||
|
</tb-security-config-lwm2m-server> |
||||
|
</ng-template> |
||||
|
</mat-expansion-panel> |
||||
|
<mat-expansion-panel> |
||||
|
<mat-expansion-panel-header> |
||||
|
<mat-panel-title> |
||||
|
{{ 'device.lwm2m-security-config.lwm2m-server' | translate }} |
||||
|
</mat-panel-title> |
||||
|
</mat-expansion-panel-header> |
||||
|
<ng-template matExpansionPanelContent> |
||||
|
<tb-security-config-lwm2m-server |
||||
|
formControlName="lwm2mServer"> |
||||
|
</tb-security-config-lwm2m-server> |
||||
|
</ng-template> |
||||
|
</mat-expansion-panel> |
||||
|
</mat-accordion> |
||||
|
</div> |
||||
|
</mat-tab> |
||||
|
<mat-tab label="{{ 'device.lwm2m-security-config.config-json-tab' | translate }}"> |
||||
|
<ng-template matTabContent> |
||||
|
<tb-json-object-edit |
||||
|
[formControlName]="formControlNameJsonAllConfig" |
||||
|
label="{{ 'device.lwm2m-value' | translate }}" |
||||
|
readonly |
||||
|
[required]="true" |
||||
|
[fillHeight]="false"> |
||||
|
</tb-json-object-edit> |
||||
|
</ng-template> |
||||
|
</mat-tab> |
||||
|
</mat-tab-group> |
||||
|
</div> |
||||
|
<div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center"> |
||||
|
<button mat-button color="primary" |
||||
|
type="button" |
||||
|
[disabled]="(isLoading$ | async)" |
||||
|
(click)="cancel()"> |
||||
|
{{ 'action.cancel' | translate }} |
||||
|
</button> |
||||
|
<button mat-button mat-raised-button color="primary" |
||||
|
type="submit" |
||||
|
[disabled]="(isLoading$ | async) || lwm2mConfigFormGroup.invalid || !lwm2mConfigFormGroup.dirty"> |
||||
|
{{ 'action.save' | translate }} |
||||
|
</button> |
||||
|
</div> |
||||
|
</form> |
||||
@ -0,0 +1,34 @@ |
|||||
|
/** |
||||
|
* 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. |
||||
|
*/ |
||||
|
:host { |
||||
|
mat-tab-group { |
||||
|
min-height: 330px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:host ::ng-deep { |
||||
|
.mat-tab-body-wrapper { |
||||
|
min-height: 200px; |
||||
|
} |
||||
|
|
||||
|
.mat-tab-body { |
||||
|
padding: 16px 0; |
||||
|
} |
||||
|
|
||||
|
textarea.mat-input-element.cdk-textarea-autosize { |
||||
|
box-sizing: content-box; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,257 @@ |
|||||
|
///
|
||||
|
/// 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, Inject, OnDestroy, OnInit } from '@angular/core'; |
||||
|
import { DialogComponent } from '@shared/components/dialog.component'; |
||||
|
import { Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { Router } from '@angular/router'; |
||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; |
||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
|
import { TranslateService } from '@ngx-translate/core'; |
||||
|
import { |
||||
|
DeviceCredentialsDialogLwm2mData, |
||||
|
getClientSecurityConfig, |
||||
|
JSON_ALL_CONFIG, |
||||
|
KEY_REGEXP_HEX_DEC, |
||||
|
LEN_MAX_PSK, |
||||
|
LEN_MAX_PUBLIC_KEY_RPK, |
||||
|
Lwm2mSecurityConfigModels, |
||||
|
Lwm2mSecurityType, |
||||
|
Lwm2mSecurityTypeTranslationMap |
||||
|
} from '@shared/models/lwm2m-security-config.models'; |
||||
|
import { MatTabChangeEvent } from '@angular/material/tabs'; |
||||
|
import { MatTab } from '@angular/material/tabs/tab'; |
||||
|
import { Subject } from 'rxjs'; |
||||
|
import { takeUntil } from 'rxjs/operators'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'tb-security-config-lwm2m', |
||||
|
templateUrl: './security-config-lwm2m.component.html', |
||||
|
styleUrls: ['./security-config-lwm2m.component.scss'] |
||||
|
}) |
||||
|
|
||||
|
export class SecurityConfigLwm2mComponent extends DialogComponent<SecurityConfigLwm2mComponent, object> implements OnInit, OnDestroy { |
||||
|
|
||||
|
private destroy$ = new Subject(); |
||||
|
|
||||
|
lwm2mConfigFormGroup: FormGroup; |
||||
|
title: string; |
||||
|
securityConfigLwM2MType = Lwm2mSecurityType; |
||||
|
securityConfigLwM2MTypes = Object.keys(Lwm2mSecurityType); |
||||
|
credentialTypeLwM2MNamesMap = Lwm2mSecurityTypeTranslationMap; |
||||
|
formControlNameJsonAllConfig = JSON_ALL_CONFIG; |
||||
|
jsonAllConfig: Lwm2mSecurityConfigModels; |
||||
|
lenMaxKeyClient = LEN_MAX_PSK; |
||||
|
tabPrevious: MatTab; |
||||
|
tabIndexPrevious = 0; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
protected router: Router, |
||||
|
@Inject(MAT_DIALOG_DATA) public data: DeviceCredentialsDialogLwm2mData, |
||||
|
public dialogRef: MatDialogRef<SecurityConfigLwm2mComponent, object>, |
||||
|
public fb: FormBuilder, |
||||
|
public translate: TranslateService) { |
||||
|
super(store, router, dialogRef); |
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
this.jsonAllConfig = JSON.parse(JSON.stringify(this.data.jsonAllConfig)); |
||||
|
this.lwm2mConfigFormGroup = this.initLwm2mConfigFormGroup(); |
||||
|
this.title = this.translate.instant('device.lwm2m-security-info') + ': ' + this.data.endPoint; |
||||
|
this.lwm2mConfigFormGroup.get('x509').disable(); |
||||
|
this.initClientSecurityConfig(this.lwm2mConfigFormGroup.get('jsonAllConfig').value); |
||||
|
this.registerDisableOnLoadFormControl(this.lwm2mConfigFormGroup.get('securityConfigClientMode')); |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy() { |
||||
|
this.destroy$.next(); |
||||
|
this.destroy$.complete(); |
||||
|
} |
||||
|
|
||||
|
private initClientSecurityConfig = (jsonAllConfig: Lwm2mSecurityConfigModels): void => { |
||||
|
if (jsonAllConfig.client.securityConfigClientMode !== Lwm2mSecurityType.NO_SEC) { |
||||
|
this.lwm2mConfigFormGroup.patchValue(jsonAllConfig.client, {emitEvent: false}); |
||||
|
} |
||||
|
this.securityConfigClientUpdateValidators(jsonAllConfig.client.securityConfigClientMode); |
||||
|
} |
||||
|
|
||||
|
private securityConfigClientModeChanged(type: Lwm2mSecurityType): void { |
||||
|
const config = getClientSecurityConfig(type, this.lwm2mConfigFormGroup.get('endPoint').value); |
||||
|
switch (type) { |
||||
|
case Lwm2mSecurityType.PSK: |
||||
|
config.identity = this.data.endPoint; |
||||
|
config.key = this.lwm2mConfigFormGroup.get('key').value; |
||||
|
break; |
||||
|
case Lwm2mSecurityType.RPK: |
||||
|
config.key = this.lwm2mConfigFormGroup.get('key').value; |
||||
|
break; |
||||
|
} |
||||
|
this.jsonAllConfig.client = config; |
||||
|
this.lwm2mConfigFormGroup.patchValue({ |
||||
|
...config, |
||||
|
jsonAllConfig: this.jsonAllConfig |
||||
|
}, {emitEvent: false}); |
||||
|
this.securityConfigClientUpdateValidators(type); |
||||
|
} |
||||
|
|
||||
|
private securityConfigClientUpdateValidators = (mode: Lwm2mSecurityType): void => { |
||||
|
switch (mode) { |
||||
|
case Lwm2mSecurityType.NO_SEC: |
||||
|
case Lwm2mSecurityType.X509: |
||||
|
this.setValidatorsNoSecX509(); |
||||
|
break; |
||||
|
case Lwm2mSecurityType.PSK: |
||||
|
this.lenMaxKeyClient = LEN_MAX_PSK; |
||||
|
this.setValidatorsPskRpk(mode); |
||||
|
break; |
||||
|
case Lwm2mSecurityType.RPK: |
||||
|
this.lenMaxKeyClient = LEN_MAX_PUBLIC_KEY_RPK; |
||||
|
this.setValidatorsPskRpk(mode); |
||||
|
break; |
||||
|
} |
||||
|
this.lwm2mConfigFormGroup.get('identity').updateValueAndValidity({emitEvent: false}); |
||||
|
this.lwm2mConfigFormGroup.get('key').updateValueAndValidity({emitEvent: false}); |
||||
|
} |
||||
|
|
||||
|
private setValidatorsNoSecX509 = (): void => { |
||||
|
this.lwm2mConfigFormGroup.get('identity').setValidators([]); |
||||
|
this.lwm2mConfigFormGroup.get('key').setValidators([]); |
||||
|
} |
||||
|
|
||||
|
private setValidatorsPskRpk = (mode: Lwm2mSecurityType): void => { |
||||
|
if (mode === Lwm2mSecurityType.PSK) { |
||||
|
this.lwm2mConfigFormGroup.get('identity').setValidators([Validators.required]); |
||||
|
} else { |
||||
|
this.lwm2mConfigFormGroup.get('identity').setValidators([]); |
||||
|
} |
||||
|
this.lwm2mConfigFormGroup.get('key').setValidators([Validators.required, |
||||
|
Validators.pattern(KEY_REGEXP_HEX_DEC), |
||||
|
Validators.maxLength(this.lenMaxKeyClient), Validators.minLength(this.lenMaxKeyClient)]); |
||||
|
} |
||||
|
|
||||
|
tabChanged = (tabChangeEvent: MatTabChangeEvent): void => { |
||||
|
if (this.tabIndexPrevious !== tabChangeEvent.index) { |
||||
|
this.upDateValueToJson(); |
||||
|
} |
||||
|
this.tabIndexPrevious = tabChangeEvent.index; |
||||
|
} |
||||
|
|
||||
|
private upDateValueToJson(): void { |
||||
|
switch (this.tabIndexPrevious) { |
||||
|
case 0: |
||||
|
this.upDateValueToJsonTab0(); |
||||
|
break; |
||||
|
case 1: |
||||
|
this.upDateValueToJsonTab1(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private upDateValueToJsonTab0 = (): void => { |
||||
|
if (this.lwm2mConfigFormGroup.get('identity').dirty && this.lwm2mConfigFormGroup.get('identity').valid || |
||||
|
this.lwm2mConfigFormGroup.get('key').dirty && this.lwm2mConfigFormGroup.get('key').valid) { |
||||
|
this.updateBootstrapSettings(); |
||||
|
this.upDateJsonAllConfig(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private upDateValueToJsonTab1 = (): void => { |
||||
|
const bootstrap = this.lwm2mConfigFormGroup.get('bootstrapServer').value; |
||||
|
if (bootstrap !== null |
||||
|
&& this.lwm2mConfigFormGroup.get('bootstrapServer').dirty |
||||
|
&& this.lwm2mConfigFormGroup.get('bootstrapServer').valid) { |
||||
|
this.jsonAllConfig.bootstrap.bootstrapServer = bootstrap; |
||||
|
this.upDateJsonAllConfig(); |
||||
|
} |
||||
|
const serverConfig = this.lwm2mConfigFormGroup.get('lwm2mServer').value; |
||||
|
if (serverConfig !== null |
||||
|
&& this.lwm2mConfigFormGroup.get('lwm2mServer').dirty |
||||
|
&& this.lwm2mConfigFormGroup.get('lwm2mServer').valid) { |
||||
|
this.jsonAllConfig.bootstrap.lwm2mServer = serverConfig; |
||||
|
this.upDateJsonAllConfig(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private updateBootstrapSettings() { |
||||
|
const securityMode = 'securityMode'; |
||||
|
this.jsonAllConfig.client.identity = this.lwm2mConfigFormGroup.get('identity').value; |
||||
|
this.jsonAllConfig.client.key = this.lwm2mConfigFormGroup.get('key').value; |
||||
|
if (this.lwm2mConfigFormGroup.get('bootstrapServer').value[securityMode] === Lwm2mSecurityType.PSK) { |
||||
|
this.jsonAllConfig.bootstrap.bootstrapServer.clientPublicKeyOrId = this.jsonAllConfig.client.identity; |
||||
|
this.jsonAllConfig.bootstrap.bootstrapServer.clientSecretKey = this.jsonAllConfig.client.key; |
||||
|
this.lwm2mConfigFormGroup.get('bootstrapServer').patchValue(this.jsonAllConfig.bootstrap.bootstrapServer, {emitEvent: false}); |
||||
|
} |
||||
|
if (this.lwm2mConfigFormGroup.get('lwm2mServer').value[securityMode] === Lwm2mSecurityType.PSK) { |
||||
|
this.jsonAllConfig.bootstrap.lwm2mServer.clientPublicKeyOrId = this.jsonAllConfig.client.identity; |
||||
|
this.jsonAllConfig.bootstrap.lwm2mServer.clientSecretKey = this.jsonAllConfig.client.key; |
||||
|
this.lwm2mConfigFormGroup.get('lwm2mServer').patchValue(this.jsonAllConfig.bootstrap.lwm2mServer, {emitEvent: false}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private upDateJsonAllConfig = (): void => { |
||||
|
this.lwm2mConfigFormGroup.patchValue({ |
||||
|
jsonAllConfig: this.jsonAllConfig |
||||
|
}, {emitEvent: false}); |
||||
|
} |
||||
|
|
||||
|
private initLwm2mConfigFormGroup = (): FormGroup => { |
||||
|
if (this.jsonAllConfig.client.securityConfigClientMode === Lwm2mSecurityType.PSK) { |
||||
|
this.data.endPoint = this.jsonAllConfig.client.endpoint; |
||||
|
} |
||||
|
const formGroup = this.fb.group({ |
||||
|
securityConfigClientMode: [this.jsonAllConfig.client.securityConfigClientMode], |
||||
|
identity: [''], |
||||
|
key: [''], |
||||
|
x509: [false], |
||||
|
bootstrapServer: [this.jsonAllConfig.bootstrap.bootstrapServer], |
||||
|
lwm2mServer: [this.jsonAllConfig.bootstrap.lwm2mServer], |
||||
|
endPoint: [this.data.endPoint], |
||||
|
jsonAllConfig: [this.jsonAllConfig] |
||||
|
}); |
||||
|
formGroup.get('securityConfigClientMode').valueChanges.pipe( |
||||
|
takeUntil(this.destroy$) |
||||
|
).subscribe((type) => { |
||||
|
this.securityConfigClientModeChanged(type); |
||||
|
}); |
||||
|
formGroup.get('endPoint').valueChanges.pipe( |
||||
|
takeUntil(this.destroy$) |
||||
|
).subscribe((endpoint) => { |
||||
|
if (formGroup.get('securityConfigClientMode').value === Lwm2mSecurityType.PSK) { |
||||
|
this.jsonAllConfig.client.endpoint = endpoint; |
||||
|
this.upDateJsonAllConfig(); |
||||
|
} |
||||
|
}); |
||||
|
return formGroup; |
||||
|
} |
||||
|
|
||||
|
save(): void { |
||||
|
this.upDateValueToJson(); |
||||
|
this.data.endPoint = this.lwm2mConfigFormGroup.get('endPoint').value.split('\'').join(''); |
||||
|
this.data.jsonAllConfig = this.jsonAllConfig; |
||||
|
if (this.lwm2mConfigFormGroup.get('securityConfigClientMode').value === Lwm2mSecurityType.PSK) { |
||||
|
this.data.endPoint = this.data.jsonAllConfig.client.identity; |
||||
|
} |
||||
|
this.dialogRef.close(this.data); |
||||
|
} |
||||
|
|
||||
|
cancel(): void { |
||||
|
this.dialogRef.close(undefined); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -1,101 +0,0 @@ |
|||||
<!-- |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
--> |
|
||||
<section [formGroup]="serverFormGroup" style="min-width: 400px;"> |
|
||||
<div class="mat-padding"> |
|
||||
<div fxLayout="column"> |
|
||||
<div fxLayout="row" fxLayoutGap="8px"> |
|
||||
<mat-form-field class="mat-block"> |
|
||||
<mat-label translate>device.lwm2m-security-config.mode</mat-label> |
|
||||
<mat-select formControlName="securityMode" |
|
||||
(ngModelChange)="securityModeChanged($event)"> |
|
||||
<mat-option *ngFor="let securityMode of securityConfigLwM2MTypes" |
|
||||
[value]="securityMode"> |
|
||||
{{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityMode]) }} |
|
||||
</mat-option> |
|
||||
</mat-select> |
|
||||
</mat-form-field> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div fxLayout="column"> |
|
||||
<div [fxShow]="serverFormGroup.get('securityMode').value !== securityConfigLwM2MType.NO_SEC"> |
|
||||
<mat-form-field class="mat-block"> |
|
||||
<mat-label>{{ 'device.lwm2m-security-config.client-publicKey-or-id' | translate }}</mat-label> |
|
||||
<textarea matInput |
|
||||
#clientPublicKeyOrId |
|
||||
maxlength={{lenMaxClientPublicKeyOrId}} |
|
||||
cdkTextareaAutosize |
|
||||
cdkAutosizeMinRows="1" |
|
||||
style="overflow:hidden" |
|
||||
cols="1" |
|
||||
formControlName="clientPublicKeyOrId" |
|
||||
[required]="serverFormGroup.get('securityMode').value !== securityConfigLwM2MType.NO_SEC"> |
|
||||
</textarea> |
|
||||
<mat-hint align="end">{{clientPublicKeyOrId.value?.length || 0}}/{{lenMaxClientPublicKeyOrId}}</mat-hint> |
|
||||
<mat-error *ngIf="serverFormGroup.get('clientPublicKeyOrId').hasError('required')"> |
|
||||
{{ 'device.lwm2m-security-config.client-publicKey-or-id' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.required' | translate }}</strong> |
|
||||
</mat-error> |
|
||||
<mat-error *ngIf="serverFormGroup.get('clientPublicKeyOrId').hasError('pattern')"> |
|
||||
{{ 'device.lwm2m-security-config.client-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.pattern_hex_dec' | translate: { |
|
||||
count: 0 |
|
||||
} }}</strong> |
|
||||
</mat-error> |
|
||||
<mat-error *ngIf="(serverFormGroup.get('clientPublicKeyOrId').hasError('maxlength') || |
|
||||
serverFormGroup.get('clientPublicKeyOrId').hasError('minlength'))"> |
|
||||
{{ 'device.lwm2m-security-config.client-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.pattern_hex_dec' | translate: { |
|
||||
count: lenMaxClientPublicKeyOrId |
|
||||
} }}</strong> |
|
||||
</mat-error> |
|
||||
</mat-form-field> |
|
||||
<mat-form-field class="mat-block"> |
|
||||
<mat-label>{{ 'device.lwm2m-security-config.client-secret-key' | translate }}</mat-label> |
|
||||
<textarea matInput |
|
||||
#clientSecretKey |
|
||||
maxlength={{lenMaxClientSecretKey}} |
|
||||
cdkTextareaAutosize |
|
||||
cdkAutosizeMinRows="1" |
|
||||
style="overflow:hidden" |
|
||||
cols="1" |
|
||||
formControlName="clientSecretKey" |
|
||||
[required]="serverFormGroup.get('securityMode').value !== securityConfigLwM2MType.NO_SEC"> |
|
||||
</textarea> |
|
||||
<mat-hint align="end">{{clientSecretKey.value?.length || 0}}/{{lenMaxClientSecretKey}}</mat-hint> |
|
||||
<mat-error *ngIf="serverFormGroup.get('clientSecretKey').hasError('required')"> |
|
||||
{{ 'device.lwm2m-security-config.client-secret-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.required' | translate }}</strong> |
|
||||
</mat-error> |
|
||||
<mat-error *ngIf="serverFormGroup.get('clientSecretKey').hasError('pattern')"> |
|
||||
{{ 'device.lwm2m-security-config.client-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.pattern_hex_dec' | translate: { |
|
||||
count: 0 |
|
||||
} }}</strong> |
|
||||
</mat-error> |
|
||||
<mat-error *ngIf="(serverFormGroup.get('clientSecretKey').hasError('maxlength') || |
|
||||
serverFormGroup.get('clientSecretKey').hasError('minlength'))"> |
|
||||
{{ 'device.lwm2m-security-config.client-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.pattern_hex_dec' | translate: { |
|
||||
count: lenMaxClientSecretKey |
|
||||
} }}</strong> |
|
||||
</mat-error> |
|
||||
</mat-form-field> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</section> |
|
||||
@ -1,142 +0,0 @@ |
|||||
///
|
|
||||
/// 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, Inject, Input, OnInit } from '@angular/core'; |
|
||||
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; |
|
||||
import { |
|
||||
DeviceCredentialsDialogLwm2mData, |
|
||||
KEY_REGEXP_HEX_DEC, |
|
||||
LEN_MAX_PRIVATE_KEY, |
|
||||
LEN_MAX_PSK, |
|
||||
LEN_MAX_PUBLIC_KEY_RPK, |
|
||||
LEN_MAX_PUBLIC_KEY_X509, |
|
||||
SECURITY_CONFIG_MODE, |
|
||||
SECURITY_CONFIG_MODE_NAMES, |
|
||||
ServerSecurityConfig |
|
||||
} from '@home/pages/device/lwm2m/security-config.models'; |
|
||||
import { Store } from '@ngrx/store'; |
|
||||
import { AppState } from '@core/core.state'; |
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; |
|
||||
import { PageComponent } from '@shared/components/page.component'; |
|
||||
|
|
||||
@Component({ |
|
||||
selector: 'tb-security-config-server-lwm2m', |
|
||||
templateUrl: './security-config-server.component.html', |
|
||||
styleUrls: [], |
|
||||
providers: [ |
|
||||
{ |
|
||||
provide: NG_VALUE_ACCESSOR, |
|
||||
useExisting: forwardRef(() => SecurityConfigServerComponent), |
|
||||
multi: true |
|
||||
} |
|
||||
] |
|
||||
}) |
|
||||
|
|
||||
export class SecurityConfigServerComponent extends PageComponent implements OnInit, ControlValueAccessor { |
|
||||
|
|
||||
securityConfigLwM2MType = SECURITY_CONFIG_MODE; |
|
||||
securityConfigLwM2MTypes = Object.keys(SECURITY_CONFIG_MODE); |
|
||||
credentialTypeLwM2MNamesMap = SECURITY_CONFIG_MODE_NAMES; |
|
||||
lenMinClientPublicKeyOrId = 0; |
|
||||
lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
|
||||
lenMinClientSecretKey = LEN_MAX_PRIVATE_KEY; |
|
||||
lenMaxClientSecretKey = LEN_MAX_PRIVATE_KEY; |
|
||||
|
|
||||
@Input() serverFormGroup: FormGroup; |
|
||||
|
|
||||
constructor(protected store: Store<AppState>, |
|
||||
@Inject(MAT_DIALOG_DATA) public data: DeviceCredentialsDialogLwm2mData, |
|
||||
public dialogRef: MatDialogRef<SecurityConfigServerComponent, object>, |
|
||||
public fb: FormBuilder) { |
|
||||
super(store); |
|
||||
} |
|
||||
|
|
||||
ngOnInit(): void { |
|
||||
this.registerDisableOnLoadFormControl(this.serverFormGroup.get('securityMode')); |
|
||||
} |
|
||||
|
|
||||
private updateValueFields(serverData: ServerSecurityConfig): void { |
|
||||
this.serverFormGroup.patchValue(serverData, {emitEvent: false}); |
|
||||
const securityMode = this.serverFormGroup.get('securityMode').value as SECURITY_CONFIG_MODE; |
|
||||
this.updateValidate(securityMode); |
|
||||
} |
|
||||
|
|
||||
private updateValidate(securityMode: SECURITY_CONFIG_MODE): void { |
|
||||
switch (securityMode) { |
|
||||
case SECURITY_CONFIG_MODE.NO_SEC: |
|
||||
this.serverFormGroup.get('clientPublicKeyOrId').setValidators([]); |
|
||||
this.serverFormGroup.get('clientSecretKey').setValidators([]); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.PSK: |
|
||||
this.lenMinClientPublicKeyOrId = 0; |
|
||||
this.lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
|
||||
this.lenMinClientSecretKey = LEN_MAX_PSK; |
|
||||
this.lenMaxClientSecretKey = LEN_MAX_PSK; |
|
||||
this.setValidatorsSecurity(securityMode); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.RPK: |
|
||||
this.lenMinClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
|
||||
this.lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_RPK; |
|
||||
this.lenMinClientSecretKey = LEN_MAX_PRIVATE_KEY; |
|
||||
this.lenMaxClientSecretKey = LEN_MAX_PRIVATE_KEY; |
|
||||
this.setValidatorsSecurity(securityMode); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.X509: |
|
||||
this.lenMinClientPublicKeyOrId = 0; |
|
||||
this.lenMaxClientPublicKeyOrId = LEN_MAX_PUBLIC_KEY_X509; |
|
||||
this.lenMinClientSecretKey = LEN_MAX_PRIVATE_KEY; |
|
||||
this.lenMaxClientSecretKey = LEN_MAX_PRIVATE_KEY; |
|
||||
this.setValidatorsSecurity(securityMode); |
|
||||
break; |
|
||||
} |
|
||||
this.serverFormGroup.updateValueAndValidity(); |
|
||||
} |
|
||||
|
|
||||
private setValidatorsSecurity = (securityMode: SECURITY_CONFIG_MODE): void => { |
|
||||
if (securityMode === SECURITY_CONFIG_MODE.PSK) { |
|
||||
this.serverFormGroup.get('clientPublicKeyOrId').setValidators([Validators.required]); |
|
||||
} else { |
|
||||
this.serverFormGroup.get('clientPublicKeyOrId').setValidators([Validators.required, |
|
||||
Validators.pattern(KEY_REGEXP_HEX_DEC), |
|
||||
Validators.minLength(this.lenMinClientPublicKeyOrId), |
|
||||
Validators.maxLength(this.lenMaxClientPublicKeyOrId)]); |
|
||||
} |
|
||||
|
|
||||
this.serverFormGroup.get('clientSecretKey').setValidators([Validators.required, |
|
||||
Validators.pattern(KEY_REGEXP_HEX_DEC), |
|
||||
Validators.minLength(this.lenMinClientSecretKey), |
|
||||
Validators.maxLength(this.lenMaxClientSecretKey)]); |
|
||||
} |
|
||||
|
|
||||
securityModeChanged(securityMode: SECURITY_CONFIG_MODE): void { |
|
||||
this.updateValidate(securityMode); |
|
||||
} |
|
||||
|
|
||||
writeValue(value: any): void { |
|
||||
if (value) { |
|
||||
this.updateValueFields(value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
registerOnChange(fn: (value: any) => any): void { |
|
||||
} |
|
||||
|
|
||||
registerOnTouched(fn: any): void { |
|
||||
} |
|
||||
|
|
||||
setDisabledState?(isDisabled: boolean): void { |
|
||||
} |
|
||||
} |
|
||||
@ -1,180 +0,0 @@ |
|||||
<!-- |
|
||||
|
|
||||
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. |
|
||||
|
|
||||
--> |
|
||||
<form [formGroup]="lwm2mConfigFormGroup" (ngSubmit)="save()" style="min-width: 400px;"> |
|
||||
<mat-toolbar fxLayout="row" color="primary"> |
|
||||
<h2>{{ title }}</h2> |
|
||||
<span fxFlex></span> |
|
||||
<button mat-button mat-icon-button |
|
||||
(click)="cancel()" |
|
||||
type="button"> |
|
||||
<mat-icon class="material-icons">close</mat-icon> |
|
||||
</button> |
|
||||
</mat-toolbar> |
|
||||
<div mat-dialog-content> |
|
||||
<fieldset [disabled]="isLoading$ | async"> |
|
||||
<mat-form-field class="mat-block"> |
|
||||
<mat-label translate>device.lwm2m-security-config.endpoint</mat-label> |
|
||||
<input matInput type="text" formControlName="endPoint" required> |
|
||||
<mat-error *ngIf="lwm2mConfigFormGroup.get('endPoint').hasError('required')"> |
|
||||
{{ 'device.lwm2m-security-config.endpoint' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.required' | translate }}</strong> |
|
||||
</mat-error> |
|
||||
</mat-form-field> |
|
||||
<mat-tab-group dynamicHeight (selectedTabChange)="tabChanged($event)"> |
|
||||
<mat-tab label="{{ 'device.lwm2m-security-config.client-tab' | translate }}"> |
|
||||
<ng-template matTabContent> |
|
||||
<div class="mat-padding"> |
|
||||
<mat-form-field class="mat-block"> |
|
||||
<mat-label translate>device.lwm2m-security-config.mode</mat-label> |
|
||||
<mat-select formControlName="securityConfigClientMode" |
|
||||
(ngModelChange)="securityConfigClientModeChanged($event)"> |
|
||||
<mat-option *ngFor="let securityConfigClientMode of securityConfigLwM2MTypes" |
|
||||
[value]="securityConfigClientMode"> |
|
||||
{{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityConfigClientMode]) }} |
|
||||
</mat-option> |
|
||||
</mat-select> |
|
||||
</mat-form-field> |
|
||||
<div *ngIf="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.PSK"> |
|
||||
<mat-form-field class="mat-block"> |
|
||||
<mat-label>{{ 'device.lwm2m-security-config.identity' | translate }}</mat-label> |
|
||||
<input matInput type="text" formControlName="identityPSK" |
|
||||
[required]="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.PSK"> |
|
||||
<mat-error *ngIf="lwm2mConfigFormGroup.get('identityPSK').hasError('required')"> |
|
||||
{{ 'device.lwm2m-security-config.identity' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.required' | translate }}</strong> |
|
||||
</mat-error> |
|
||||
</mat-form-field> |
|
||||
</div> |
|
||||
<div *ngIf="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.RPK || |
|
||||
lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.PSK"> |
|
||||
<mat-form-field class="mat-block"> |
|
||||
<mat-label>{{ 'device.lwm2m-security-config.client-key' | translate }}</mat-label> |
|
||||
<textarea matInput |
|
||||
#clientKey |
|
||||
maxlength="{{lenMaxKeyClient}}" |
|
||||
cdkTextareaAutosize |
|
||||
cdkAutosizeMinRows="1" |
|
||||
cols="1" |
|
||||
formControlName="clientKey" |
|
||||
style="overflow:hidden" |
|
||||
[required]="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.RPK || |
|
||||
lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.PSK"> |
|
||||
</textarea> |
|
||||
<mat-hint align="end">{{clientKey.value?.length || 0}}/{{lenMaxKeyClient}}</mat-hint> |
|
||||
<mat-error *ngIf="lwm2mConfigFormGroup.get('clientKey').hasError('required')"> |
|
||||
{{ 'device.lwm2m-security-config.client-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.required' | translate }}</strong> |
|
||||
</mat-error> |
|
||||
<mat-error *ngIf="lwm2mConfigFormGroup.get('clientKey').hasError('pattern')"> |
|
||||
{{ 'device.lwm2m-security-config.client-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.pattern_hex_dec' | translate: { |
|
||||
count: 0 |
|
||||
} }}</strong> |
|
||||
</mat-error> |
|
||||
<mat-error *ngIf="(lwm2mConfigFormGroup.get('clientKey').hasError('maxlength') || |
|
||||
lwm2mConfigFormGroup.get('clientKey').hasError('minlength'))"> |
|
||||
{{ 'device.lwm2m-security-config.client-key' | translate }} |
|
||||
<strong>{{ 'device.lwm2m-security-config.pattern_hex_dec' | translate: { |
|
||||
count: lenMaxKeyClient |
|
||||
} }}</strong> |
|
||||
</mat-error> |
|
||||
</mat-form-field> |
|
||||
</div> |
|
||||
<div *ngIf="lwm2mConfigFormGroup.get('securityConfigClientMode').value === securityConfigLwM2MType.X509"> |
|
||||
<mat-checkbox formControlName="clientCertificate" color="primary"> |
|
||||
{{ 'device.lwm2m-security-config.client-certificate' | translate }} |
|
||||
</mat-checkbox> |
|
||||
</div> |
|
||||
</div> |
|
||||
</ng-template> |
|
||||
</mat-tab> |
|
||||
<mat-tab label="{{ 'device.lwm2m-security-config.bootstrap-tab' | translate }}"> |
|
||||
<ng-template matTabContent> |
|
||||
<div class="mat-padding"> |
|
||||
<mat-accordion multi="true" class="mat-body-1"> |
|
||||
<mat-expansion-panel> |
|
||||
<mat-expansion-panel-header> |
|
||||
<mat-panel-title> |
|
||||
<div |
|
||||
class="tb-panel-title">{{ 'device.lwm2m-security-config.bootstrap-server' | translate | uppercase }}</div> |
|
||||
</mat-panel-title> |
|
||||
</mat-expansion-panel-header> |
|
||||
<ng-template matExpansionPanelContent> |
|
||||
<div class="mat-padding"> |
|
||||
<tb-security-config-server-lwm2m |
|
||||
[formControlName]="bootstrapServer" |
|
||||
[serverFormGroup]="bootstrapFormGroup"> |
|
||||
</tb-security-config-server-lwm2m> |
|
||||
</div> |
|
||||
</ng-template> |
|
||||
</mat-expansion-panel> |
|
||||
</mat-accordion> |
|
||||
<mat-accordion multi="true" class="mat-body-1"> |
|
||||
<mat-expansion-panel> |
|
||||
<mat-expansion-panel-header> |
|
||||
<mat-panel-title> |
|
||||
<div |
|
||||
class="tb-panel-title">{{ 'device.lwm2m-security-config.lwm2m-server' | translate | uppercase }}</div> |
|
||||
</mat-panel-title> |
|
||||
</mat-expansion-panel-header> |
|
||||
<ng-template matExpansionPanelContent> |
|
||||
<div class="mat-padding"> |
|
||||
<tb-security-config-server-lwm2m |
|
||||
[formControlName]="lwm2mServer" |
|
||||
[serverFormGroup]="lwm2mServerFormGroup"> |
|
||||
</tb-security-config-server-lwm2m> |
|
||||
</div> |
|
||||
</ng-template> |
|
||||
</mat-expansion-panel> |
|
||||
</mat-accordion> |
|
||||
</div> |
|
||||
</ng-template> |
|
||||
</mat-tab> |
|
||||
<mat-tab label="{{ 'device.lwm2m-security-config.config-json-tab' | translate }}"> |
|
||||
<ng-template matTabContent> |
|
||||
<div class="mat-padding"> |
|
||||
<fieldset [disabled]="isLoading$ | async"> |
|
||||
<tb-json-object-edit |
|
||||
[formControlName]="formControlNameJsonAllConfig" |
|
||||
label="{{ 'device.lwm2m-value' | translate }}" |
|
||||
validateContent="true" |
|
||||
[required]="true" |
|
||||
[fillHeight]="false"> |
|
||||
</tb-json-object-edit> |
|
||||
</fieldset> |
|
||||
</div> |
|
||||
</ng-template> |
|
||||
</mat-tab> |
|
||||
</mat-tab-group> |
|
||||
</fieldset> |
|
||||
</div> |
|
||||
<div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center"> |
|
||||
<span fxFlex></span> |
|
||||
<button mat-button color="primary" |
|
||||
type="button" |
|
||||
[disabled]="(isLoading$ | async)" |
|
||||
(click)="cancel()"> |
|
||||
{{ 'action.cancel' | translate }} |
|
||||
</button> |
|
||||
<button mat-button mat-raised-button color="primary" |
|
||||
type="submit" |
|
||||
[disabled]="(isLoading$ | async) || lwm2mConfigFormGroup.invalid || !lwm2mConfigFormGroup.dirty"> |
|
||||
{{ 'action.save' | translate }} |
|
||||
</button> |
|
||||
</div> |
|
||||
</form> |
|
||||
@ -1,382 +0,0 @@ |
|||||
///
|
|
||||
/// 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, Inject, OnInit} from '@angular/core'; |
|
||||
import {DialogComponent} from '@shared/components/dialog.component'; |
|
||||
import {Store} from '@ngrx/store'; |
|
||||
import {AppState} from '@core/core.state'; |
|
||||
import {Router} from '@angular/router'; |
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; |
|
||||
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; |
|
||||
import {TranslateService} from '@ngx-translate/core'; |
|
||||
import { |
|
||||
BOOTSTRAP_SERVER, |
|
||||
BOOTSTRAP_SERVERS, |
|
||||
ClientSecurityConfig, |
|
||||
DeviceCredentialsDialogLwm2mData, |
|
||||
getClientSecurityConfig, |
|
||||
JSON_ALL_CONFIG, |
|
||||
KEY_REGEXP_HEX_DEC, |
|
||||
LEN_MAX_PSK, |
|
||||
LEN_MAX_PUBLIC_KEY_RPK, |
|
||||
LWM2M_SERVER, |
|
||||
SECURITY_CONFIG_MODE, |
|
||||
SECURITY_CONFIG_MODE_NAMES, |
|
||||
SecurityConfigModels |
|
||||
} from './security-config.models'; |
|
||||
import {WINDOW} from '@core/services/window.service'; |
|
||||
import {MatTabChangeEvent} from '@angular/material/tabs'; |
|
||||
import {MatTab} from '@angular/material/tabs/tab'; |
|
||||
|
|
||||
@Component({ |
|
||||
selector: 'tb-security-config-lwm2m', |
|
||||
templateUrl: './security-config.component.html', |
|
||||
styleUrls: [] |
|
||||
}) |
|
||||
|
|
||||
export class SecurityConfigComponent extends DialogComponent<SecurityConfigComponent, object> implements OnInit { |
|
||||
|
|
||||
lwm2mConfigFormGroup: FormGroup; |
|
||||
title: string; |
|
||||
submitted = false; |
|
||||
securityConfigLwM2MType = SECURITY_CONFIG_MODE; |
|
||||
securityConfigLwM2MTypes = Object.keys(SECURITY_CONFIG_MODE); |
|
||||
credentialTypeLwM2MNamesMap = SECURITY_CONFIG_MODE_NAMES; |
|
||||
formControlNameJsonAllConfig = JSON_ALL_CONFIG; |
|
||||
jsonAllConfig: SecurityConfigModels; |
|
||||
bootstrapServers: string; |
|
||||
bootstrapServer: string; |
|
||||
lwm2mServer: string; |
|
||||
jsonObserveData: {}; |
|
||||
lenMaxKeyClient = LEN_MAX_PSK; |
|
||||
tabPrevious: MatTab; |
|
||||
tabIndexPrevious = 0; |
|
||||
|
|
||||
constructor(protected store: Store<AppState>, |
|
||||
protected router: Router, |
|
||||
@Inject(MAT_DIALOG_DATA) public data: DeviceCredentialsDialogLwm2mData, |
|
||||
public dialogRef: MatDialogRef<SecurityConfigComponent, object>, |
|
||||
public fb: FormBuilder, |
|
||||
public translate: TranslateService, |
|
||||
@Inject(WINDOW) private window: Window) { |
|
||||
super(store, router, dialogRef); |
|
||||
} |
|
||||
|
|
||||
ngOnInit(): void { |
|
||||
this.jsonAllConfig = JSON.parse(JSON.stringify(this.data.jsonAllConfig)) as SecurityConfigModels; |
|
||||
this.initConstants(); |
|
||||
this.lwm2mConfigFormGroup = this.initLwm2mConfigFormGroup(); |
|
||||
this.title = this.translate.instant('device.lwm2m-security-info') + ': ' + this.data.endPoint; |
|
||||
this.lwm2mConfigFormGroup.get('clientCertificate').disable(); |
|
||||
this.initClientSecurityConfig(this.lwm2mConfigFormGroup.get('jsonAllConfig').value); |
|
||||
this.registerDisableOnLoadFormControl(this.lwm2mConfigFormGroup.get('securityConfigClientMode')); |
|
||||
} |
|
||||
|
|
||||
private initConstants = (): void => { |
|
||||
this.bootstrapServers = BOOTSTRAP_SERVERS; |
|
||||
this.bootstrapServer = BOOTSTRAP_SERVER; |
|
||||
this.lwm2mServer = LWM2M_SERVER; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* initChildesFormGroup |
|
||||
*/ |
|
||||
get bootstrapFormGroup(): FormGroup { |
|
||||
return this.lwm2mConfigFormGroup.get('bootstrapFormGroup') as FormGroup; |
|
||||
} |
|
||||
|
|
||||
get lwm2mServerFormGroup(): FormGroup { |
|
||||
return this.lwm2mConfigFormGroup.get('lwm2mServerFormGroup') as FormGroup; |
|
||||
} |
|
||||
|
|
||||
get observeAttrFormGroup(): FormGroup { |
|
||||
return this.lwm2mConfigFormGroup.get('observeFormGroup') as FormGroup; |
|
||||
} |
|
||||
|
|
||||
private initClientSecurityConfig = (jsonAllConfig: SecurityConfigModels): void => { |
|
||||
switch (jsonAllConfig.client.securityConfigClientMode) { |
|
||||
case SECURITY_CONFIG_MODE.NO_SEC: |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.PSK: |
|
||||
const clientSecurityConfigPSK = jsonAllConfig.client as ClientSecurityConfig; |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
identityPSK: clientSecurityConfigPSK.identity, |
|
||||
clientKey: clientSecurityConfigPSK.key, |
|
||||
}, {emitEvent: false}); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.RPK: |
|
||||
const clientSecurityConfigRPK = jsonAllConfig.client as ClientSecurityConfig; |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
clientKey: clientSecurityConfigRPK.key, |
|
||||
}, {emitEvent: false}); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.X509: |
|
||||
const clientSecurityConfigX509 = jsonAllConfig.client as ClientSecurityConfig; |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
clientCertificate: clientSecurityConfigX509.x509 |
|
||||
}, {emitEvent: false}); |
|
||||
break; |
|
||||
} |
|
||||
this.securityConfigClientUpdateValidators(this.lwm2mConfigFormGroup.get('securityConfigClientMode').value); |
|
||||
} |
|
||||
|
|
||||
securityConfigClientModeChanged = (mode: SECURITY_CONFIG_MODE): void => { |
|
||||
switch (mode) { |
|
||||
case SECURITY_CONFIG_MODE.NO_SEC: |
|
||||
const clientSecurityConfigNoSEC = getClientSecurityConfig(mode) as ClientSecurityConfig; |
|
||||
this.jsonAllConfig.client = clientSecurityConfigNoSEC; |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
jsonAllConfig: this.jsonAllConfig, |
|
||||
clientCertificate: false |
|
||||
}, {emitEvent: false}); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.PSK: |
|
||||
const clientSecurityConfigPSK = getClientSecurityConfig(mode, this.lwm2mConfigFormGroup.get('endPoint') |
|
||||
.value) as ClientSecurityConfig; |
|
||||
clientSecurityConfigPSK.identity = this.data.endPoint; |
|
||||
clientSecurityConfigPSK.key = this.lwm2mConfigFormGroup.get('clientKey').value; |
|
||||
this.jsonAllConfig.client = clientSecurityConfigPSK; |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
identityPSK: clientSecurityConfigPSK.identity, |
|
||||
clientCertificate: false |
|
||||
}, {emitEvent: false}); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.RPK: |
|
||||
const clientSecurityConfigRPK = getClientSecurityConfig(mode) as ClientSecurityConfig; |
|
||||
clientSecurityConfigRPK.key = this.lwm2mConfigFormGroup.get('clientKey').value; |
|
||||
this.jsonAllConfig.client = clientSecurityConfigRPK; |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
clientCertificate: false |
|
||||
}, {emitEvent: false}); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.X509: |
|
||||
this.jsonAllConfig.client = getClientSecurityConfig(mode) as ClientSecurityConfig; |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
clientCertificate: true |
|
||||
}, {emitEvent: false}); |
|
||||
break; |
|
||||
} |
|
||||
this.securityConfigClientUpdateValidators(mode); |
|
||||
} |
|
||||
|
|
||||
private securityConfigClientUpdateValidators = (mode: SECURITY_CONFIG_MODE): void => { |
|
||||
switch (mode) { |
|
||||
case SECURITY_CONFIG_MODE.NO_SEC: |
|
||||
this.setValidatorsNoSecX509(); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.PSK: |
|
||||
this.lenMaxKeyClient = LEN_MAX_PSK; |
|
||||
this.setValidatorsPskRpk(mode); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.RPK: |
|
||||
this.lenMaxKeyClient = LEN_MAX_PUBLIC_KEY_RPK; |
|
||||
this.setValidatorsPskRpk(mode); |
|
||||
break; |
|
||||
case SECURITY_CONFIG_MODE.X509: |
|
||||
this.lenMaxKeyClient = LEN_MAX_PUBLIC_KEY_RPK; |
|
||||
this.setValidatorsNoSecX509(); |
|
||||
break; |
|
||||
} |
|
||||
this.lwm2mConfigFormGroup.updateValueAndValidity(); |
|
||||
} |
|
||||
|
|
||||
private setValidatorsNoSecX509 = (): void => { |
|
||||
this.lwm2mConfigFormGroup.get('identityPSK').setValidators([]); |
|
||||
this.lwm2mConfigFormGroup.get('clientKey').setValidators([]); |
|
||||
} |
|
||||
|
|
||||
private setValidatorsPskRpk = (mode: SECURITY_CONFIG_MODE): void => { |
|
||||
if (mode === SECURITY_CONFIG_MODE.PSK) { |
|
||||
this.lwm2mConfigFormGroup.get('identityPSK').setValidators([Validators.required]); |
|
||||
} else { |
|
||||
this.lwm2mConfigFormGroup.get('identityPSK').setValidators([]); |
|
||||
} |
|
||||
this.lwm2mConfigFormGroup.get('clientKey').setValidators([Validators.required, |
|
||||
Validators.pattern(KEY_REGEXP_HEX_DEC), |
|
||||
Validators.maxLength(this.lenMaxKeyClient), Validators.minLength(this.lenMaxKeyClient)]); |
|
||||
} |
|
||||
|
|
||||
tabChanged = (tabChangeEvent: MatTabChangeEvent): void => { |
|
||||
if (this.tabIndexPrevious !== tabChangeEvent.index) { this.upDateValueToJson(); } |
|
||||
this.tabIndexPrevious = tabChangeEvent.index; |
|
||||
} |
|
||||
|
|
||||
private upDateValueToJson(): void { |
|
||||
switch (this.tabIndexPrevious) { |
|
||||
case 0: |
|
||||
this.upDateValueToJsonTab0(); |
|
||||
break; |
|
||||
case 1: |
|
||||
this.upDateValueToJsonTab1(); |
|
||||
break; |
|
||||
case 2: |
|
||||
this.upDateValueToJsonTab2(); |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private upDateValueToJsonTab0 = (): void => { |
|
||||
if (this.lwm2mConfigFormGroup !== null) { |
|
||||
if (!this.lwm2mConfigFormGroup.get('endPoint').pristine && this.lwm2mConfigFormGroup.get('endPoint').valid) { |
|
||||
this.data.endPoint = this.lwm2mConfigFormGroup.get('endPoint').value; |
|
||||
/** Client mode == PSK */ |
|
||||
if (this.lwm2mConfigFormGroup.get('securityConfigClientMode').value === SECURITY_CONFIG_MODE.PSK) { |
|
||||
const endPoint = 'endpoint'; |
|
||||
this.jsonAllConfig.client[endPoint] = this.data.endPoint; |
|
||||
this.lwm2mConfigFormGroup.get('endPoint').markAsPristine({ |
|
||||
onlySelf: true |
|
||||
}); |
|
||||
this.upDateJsonAllConfig(); |
|
||||
} |
|
||||
} |
|
||||
/** only Client mode == PSK */ |
|
||||
if (!this.lwm2mConfigFormGroup.get('identityPSK').pristine && this.lwm2mConfigFormGroup.get('identityPSK').valid) { |
|
||||
this.lwm2mConfigFormGroup.get('identityPSK').markAsPristine({ |
|
||||
onlySelf: true |
|
||||
}); |
|
||||
this.updateIdentityPSK(); |
|
||||
} |
|
||||
/** only Client mode == PSK (len = 64) || RPK (len = 182) */ |
|
||||
if (!this.lwm2mConfigFormGroup.get('clientKey').pristine && this.lwm2mConfigFormGroup.get('clientKey').valid) { |
|
||||
this.lwm2mConfigFormGroup.get('clientKey').markAsPristine({ |
|
||||
onlySelf: true |
|
||||
}); |
|
||||
this.updateClientKey(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private upDateValueToJsonTab1 = (): void => { |
|
||||
if (this.lwm2mConfigFormGroup !== null) { |
|
||||
if (this.bootstrapFormGroup !== null && !this.bootstrapFormGroup.pristine && this.bootstrapFormGroup.valid) { |
|
||||
this.jsonAllConfig.bootstrap.bootstrapServer = this.bootstrapFormGroup.value; |
|
||||
this.bootstrapFormGroup.markAsPristine({ |
|
||||
onlySelf: true |
|
||||
}); |
|
||||
this.upDateJsonAllConfig(); |
|
||||
} |
|
||||
|
|
||||
if (this.lwm2mServerFormGroup !== null && !this.lwm2mServerFormGroup.pristine && this.lwm2mServerFormGroup.valid) { |
|
||||
this.jsonAllConfig.bootstrap.lwm2mServer = this.lwm2mServerFormGroup.value; |
|
||||
this.lwm2mServerFormGroup.markAsPristine({ |
|
||||
onlySelf: true |
|
||||
}); |
|
||||
this.upDateJsonAllConfig(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private upDateValueToJsonTab2 = (): void => { |
|
||||
if (!this.lwm2mConfigFormGroup.get(this.formControlNameJsonAllConfig).pristine && |
|
||||
this.lwm2mConfigFormGroup.get(this.formControlNameJsonAllConfig).valid) { |
|
||||
this.jsonAllConfig = this.lwm2mConfigFormGroup.get(this.formControlNameJsonAllConfig).value; |
|
||||
this.lwm2mConfigFormGroup.get(this.formControlNameJsonAllConfig).markAsPristine({ |
|
||||
onlySelf: true |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private updateIdentityPSK = (): void => { |
|
||||
const securityMode = 'securityMode'; |
|
||||
if (this.lwm2mConfigFormGroup.get('bootstrapServer').value[securityMode] === SECURITY_CONFIG_MODE.PSK) { |
|
||||
this.lwm2mConfigFormGroup.get('bootstrapFormGroup').patchValue({ |
|
||||
clientPublicKeyOrId: this.lwm2mConfigFormGroup.get('identityPSK').value |
|
||||
}); |
|
||||
const identity = 'identity'; |
|
||||
this.jsonAllConfig.client[identity] = this.lwm2mConfigFormGroup.get('identityPSK').value; |
|
||||
this.upDateJsonAllConfig(); |
|
||||
} |
|
||||
if (this.lwm2mConfigFormGroup.get('lwm2mServer').value[securityMode] === SECURITY_CONFIG_MODE.PSK) { |
|
||||
this.lwm2mConfigFormGroup.get('lwm2mServerFormGroup').patchValue({ |
|
||||
clientPublicKeyOrId: this.lwm2mConfigFormGroup.get('identityPSK').value |
|
||||
}); |
|
||||
this.jsonAllConfig.bootstrap.lwm2mServer.clientPublicKeyOrId = this.lwm2mConfigFormGroup.get('identityPSK').value; |
|
||||
this.upDateJsonAllConfig(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private updateClientKey = (): void => { |
|
||||
const key = 'key'; |
|
||||
const securityMode = 'securityMode'; |
|
||||
this.jsonAllConfig.client[key] = this.lwm2mConfigFormGroup.get('clientKey').value; |
|
||||
if (this.lwm2mConfigFormGroup.get('bootstrapServer').value[securityMode] === SECURITY_CONFIG_MODE.PSK) { |
|
||||
this.lwm2mConfigFormGroup.get('bootstrapServer').patchValue({ |
|
||||
clientSecretKey: this.jsonAllConfig.client[key] |
|
||||
}, {emitEvent: false}); |
|
||||
this.jsonAllConfig.bootstrap.bootstrapServer.clientSecretKey = this.jsonAllConfig.client[key]; |
|
||||
} |
|
||||
if (this.lwm2mConfigFormGroup.get('lwm2mServer').value[securityMode] === SECURITY_CONFIG_MODE.PSK) { |
|
||||
this.lwm2mConfigFormGroup.get('lwm2mServer').patchValue({ |
|
||||
clientSecretKey: this.jsonAllConfig.client[key] |
|
||||
}, {emitEvent: false}); |
|
||||
this.jsonAllConfig.bootstrap.lwm2mServer.clientSecretKey = this.jsonAllConfig.client[key]; |
|
||||
} |
|
||||
this.upDateJsonAllConfig(); |
|
||||
} |
|
||||
|
|
||||
private upDateJsonAllConfig = (): void => { |
|
||||
this.data.jsonAllConfig = JSON.parse(JSON.stringify(this.jsonAllConfig)); |
|
||||
this.lwm2mConfigFormGroup.patchValue({ |
|
||||
jsonAllConfig: JSON.parse(JSON.stringify(this.jsonAllConfig)) |
|
||||
}, {emitEvent: false}); |
|
||||
this.lwm2mConfigFormGroup.markAsDirty(); |
|
||||
} |
|
||||
|
|
||||
private initLwm2mConfigFormGroup = (): FormGroup => { |
|
||||
if (SECURITY_CONFIG_MODE[this.jsonAllConfig.client.securityConfigClientMode.toString()] === SECURITY_CONFIG_MODE.PSK) { |
|
||||
const endpoint = 'endpoint'; |
|
||||
this.data.endPoint = this.jsonAllConfig.client[endpoint]; |
|
||||
} |
|
||||
return this.fb.group({ |
|
||||
securityConfigClientMode: [SECURITY_CONFIG_MODE[this.jsonAllConfig.client.securityConfigClientMode.toString()], []], |
|
||||
identityPSK: ['', []], |
|
||||
clientKey: ['', []], |
|
||||
clientCertificate: [false, []], |
|
||||
bootstrapServer: [this.jsonAllConfig.bootstrap[this.bootstrapServer], []], |
|
||||
lwm2mServer: [this.jsonAllConfig.bootstrap[this.lwm2mServer], []], |
|
||||
bootstrapFormGroup: this.getServerGroup(), |
|
||||
lwm2mServerFormGroup: this.getServerGroup(), |
|
||||
endPoint: [this.data.endPoint, []], |
|
||||
jsonAllConfig: [this.jsonAllConfig, []] |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
private getServerGroup = (): FormGroup => { |
|
||||
return this.fb.group({ |
|
||||
securityMode: [this.fb.control(SECURITY_CONFIG_MODE.NO_SEC), []], |
|
||||
clientPublicKeyOrId: ['', []], |
|
||||
clientSecretKey: ['', []] |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
save(): void { |
|
||||
this.upDateValueToJson(); |
|
||||
this.data.endPoint = this.lwm2mConfigFormGroup.get('endPoint').value.split('\'').join(''); |
|
||||
this.data.jsonAllConfig = this.jsonAllConfig; |
|
||||
if (this.lwm2mConfigFormGroup.get('securityConfigClientMode').value === SECURITY_CONFIG_MODE.PSK) { |
|
||||
const identity = 'identity'; |
|
||||
this.data.endPoint = this.data.jsonAllConfig.client[identity]; |
|
||||
} |
|
||||
this.dialogRef.close(this.data); |
|
||||
} |
|
||||
|
|
||||
cancel(): void { |
|
||||
this.dialogRef.close(undefined); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Loading…
Reference in new issue