diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.html
new file mode 100644
index 0000000000..afabe53499
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.html
@@ -0,0 +1,65 @@
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.scss
new file mode 100644
index 0000000000..f014f56588
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.scss
@@ -0,0 +1,29 @@
+/**
+ * Copyright © 2016-2024 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 {
+ width: 100%;
+ height: 100%;
+ display: block;
+ margin-bottom: 10px;
+
+ .fields-label {
+ font-weight: 500;
+ }
+
+ .hide-toggle {
+ display: none;
+ }
+}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.ts
new file mode 100644
index 0000000000..65b3620ac7
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component.ts
@@ -0,0 +1,132 @@
+///
+/// Copyright © 2016-2024 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 {
+ ChangeDetectionStrategy,
+ Component,
+ forwardRef,
+ OnDestroy,
+} from '@angular/core';
+import { Subject } from 'rxjs';
+import {
+ ControlValueAccessor,
+ FormBuilder,
+ NG_VALIDATORS,
+ NG_VALUE_ACCESSOR,
+ UntypedFormGroup,
+ ValidationErrors,
+ Validator,
+ Validators
+} from '@angular/forms';
+import { takeUntil } from 'rxjs/operators';
+import {
+ noLeadTrailSpacesRegex,
+ RestSecurityType,
+ RestSecurityTypeTranslationsMap
+} from '@home/components/widget/lib/gateway/gateway-widget.models';
+import { SharedModule } from '@shared/shared.module';
+import { CommonModule } from '@angular/common';
+
+@Component({
+ selector: 'tb-rest-connector-security',
+ templateUrl: './rest-connector-security.component.html',
+ styleUrls: ['./rest-connector-security.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => RestConnectorSecurityComponent),
+ multi: true
+ },
+ {
+ provide: NG_VALIDATORS,
+ useExisting: forwardRef(() => RestConnectorSecurityComponent),
+ multi: true
+ }
+ ],
+ standalone: true,
+ imports: [
+ SharedModule,
+ CommonModule,
+ ]
+})
+export class RestConnectorSecurityComponent implements ControlValueAccessor, Validator, OnDestroy {
+ BrokerSecurityType = RestSecurityType;
+ securityTypes: RestSecurityType[] = Object.values(RestSecurityType);
+ SecurityTypeTranslationsMap = RestSecurityTypeTranslationsMap;
+ securityFormGroup: UntypedFormGroup;
+
+ private destroy$ = new Subject();
+ private propagateChange = (_: any) => {};
+
+ constructor(private fb: FormBuilder) {
+ this.securityFormGroup = this.fb.group({
+ type: [RestSecurityType.ANONYMOUS, []],
+ username: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
+ password: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
+ });
+ this.observeSecurityForm();
+ }
+
+ ngOnDestroy(): void {
+ this.destroy$.next();
+ this.destroy$.complete();
+ }
+
+ registerOnChange(fn: any): void {
+ this.propagateChange = fn;
+ }
+
+ registerOnTouched(fn: any): void {}
+
+ writeValue(deviceInfo: any): void {
+ if (!deviceInfo.type) {
+ deviceInfo.type = RestSecurityType.ANONYMOUS;
+ }
+ this.securityFormGroup.reset(deviceInfo);
+ this.updateView(deviceInfo);
+ }
+
+ validate(): ValidationErrors | null {
+ return this.securityFormGroup.valid ? null : {
+ securityForm: { valid: false }
+ };
+ }
+
+ updateView(value: any): void {
+ this.propagateChange(value);
+ }
+
+ private updateValidators(type: RestSecurityType): void {
+ if (type === RestSecurityType.BASIC) {
+ this.securityFormGroup.get('username').enable({emitEvent: false});
+ this.securityFormGroup.get('password').enable({emitEvent: false});
+ } else {
+ this.securityFormGroup.get('username').disable({emitEvent: false});
+ this.securityFormGroup.get('password').disable({emitEvent: false});
+ }
+ }
+
+ private observeSecurityForm(): void {
+ this.securityFormGroup.valueChanges
+ .pipe(takeUntil(this.destroy$))
+ .subscribe(value => this.updateView(value));
+
+ this.securityFormGroup.get('type').valueChanges
+ .pipe(takeUntil(this.destroy$))
+ .subscribe(type => this.updateValidators(type));
+ }
+}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html
index 2d992187f6..b3d38d6655 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html
@@ -368,38 +368,7 @@
{{ 'gateway.rpc.add-header' | translate }}
-
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts
index 9838fd2df2..96380d3108 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts
@@ -114,17 +114,12 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
this.commandForm = this.connectorParamsFormGroupByType(this.connectorType);
this.commandForm.valueChanges.subscribe(value => {
const httpHeaders = {};
- const security = {};
switch (this.connectorType) {
case ConnectorType.REST:
value.httpHeaders.forEach(data => {
httpHeaders[data.headerName] = data.value;
})
value.httpHeaders = httpHeaders;
- value.security.forEach(data => {
- security[data.securityName] = data.value;
- })
- value.security = security;
break;
case ConnectorType.REQUEST:
value.httpHeaders.forEach(data => {
@@ -252,7 +247,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
tries: [null, [Validators.required, Validators.min(1), Validators.pattern(this.numbersOnlyPattern)]],
valueExpression: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
httpHeaders: this.fb.array([]),
- security: this.fb.array([])
+ security: [{}, [Validators.required]]
})
break;
case ConnectorType.REQUEST:
@@ -312,22 +307,6 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
oidsFA.removeAt(index);
}
- addHTTPSecurity(value: { securityName: string, value: string } = {securityName: null, value: null}) {
- const securityFA = this.commandForm.get('security') as FormArray;
- const formGroup = this.fb.group({
- securityName: [value.securityName, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
- value: [value.value, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]]
- })
- if (securityFA) {
- securityFA.push(formGroup, {emitEvent: false});
- }
- }
-
- removeHTTPSecurity(index: number) {
- const oidsFA = this.commandForm.get('security') as FormArray;
- oidsFA.removeAt(index);
- }
-
getFormArrayControls(path: string) {
return (this.commandForm.get(path) as FormArray).controls as FormControl[];
}
@@ -402,11 +381,6 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue
break;
case ConnectorType.REST:
this.clearFromArrayByName("httpHeaders");
- this.clearFromArrayByName("security");
- value.security && Object.entries(value.security).forEach(securityHeader => {
- this.addHTTPSecurity({securityName: securityHeader[0], value: securityHeader[1] as string})
- })
- delete value.security;
value.httpHeaders && Object.entries(value.httpHeaders).forEach(httpHeader => {
this.addHTTPHeader({headerName: httpHeader[0], value: httpHeader[1] as string})
})
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
index 0e143cff36..2bf55275c2 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
@@ -360,6 +360,18 @@ export const BrokerSecurityTypeTranslationsMap = new Map(
+ [
+ [RestSecurityType.ANONYMOUS, 'gateway.broker.security-types.anonymous'],
+ [RestSecurityType.BASIC, 'gateway.broker.security-types.basic'],
+ ]
+);
+
export const MqttVersions = [
{ name: 3.1, value: 3 },
{ name: 3.11, value: 4 },
diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts
index d345f5954f..6d2cfb6fe3 100644
--- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts
@@ -100,6 +100,7 @@ import { BarChartWidgetComponent } from '@home/components/widget/lib/chart/bar-c
import { PolarAreaWidgetComponent } from '@home/components/widget/lib/chart/polar-area-widget.component';
import { RadarChartWidgetComponent } from '@home/components/widget/lib/chart/radar-chart-widget.component';
import { MobileAppQrcodeWidgetComponent } from '@home/components/widget/lib/mobile-app-qrcode-widget.component';
+import { RestConnectorSecurityComponent } from '@home/components/widget/lib/gateway/connectors-configuration/rest-connector-secuirity/rest-connector-security.component';
@NgModule({
declarations:
@@ -168,13 +169,14 @@ import { MobileAppQrcodeWidgetComponent } from '@home/components/widget/lib/mobi
PolarAreaWidgetComponent,
RadarChartWidgetComponent
],
- imports: [
- CommonModule,
- SharedModule,
- RpcWidgetsModule,
- HomePageWidgetsModule,
- SharedHomeComponentsModule
- ],
+ imports: [
+ CommonModule,
+ SharedModule,
+ RpcWidgetsModule,
+ HomePageWidgetsModule,
+ SharedHomeComponentsModule,
+ RestConnectorSecurityComponent
+ ],
exports: [
EntitiesTableWidgetComponent,
AlarmsTableWidgetComponent,