From 03fbc698f2a04f76f0e482936fc20885ca080e51 Mon Sep 17 00:00:00 2001 From: kulgg <75735874+kulgg@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:58:58 +0100 Subject: [PATCH] . --- .../services/http-params-mapper.service.ts | 57 ++++++++++++++----- src/app/core/validators/valid-query-param.ts | 18 ++++++ .../core/validators/validation-messages.ts | 1 + .../asset-edit-dialog.component.html | 15 +++++ .../form/asset-datasource-form-builder.ts | 5 +- 5 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 src/app/core/validators/valid-query-param.ts diff --git a/src/app/core/services/http-params-mapper.service.ts b/src/app/core/services/http-params-mapper.service.ts index 84337cdc4..86f144034 100644 --- a/src/app/core/services/http-params-mapper.service.ts +++ b/src/app/core/services/http-params-mapper.service.ts @@ -26,7 +26,8 @@ export class HttpRequestParamsMapper { value: ContractAgreementTransferDialogFormValue, ): Record { const method = value.httpProxiedMethod?.trim() ?? ''; - const {url: pathSegments, queryParams} = this.getUrlAndQueryParams( + const pathSegments = this.getUrl(value.httpProxiedPath); + const queryParams = this.getQueryParams( value.httpProxiedPath, value.httpProxiedQueryParams, ); @@ -98,7 +99,8 @@ export class HttpRequestParamsMapper { method = null; } - const {url: baseUrl, queryParams} = this.getUrlAndQueryParams( + const baseUrl = this.getUrl(formValue?.httpUrl); + const queryParams = this.getRawQueryParams( formValue?.httpUrl, formValue?.httpQueryParams, ); @@ -141,34 +143,59 @@ export class HttpRequestParamsMapper { return {authHeaderName, authHeaderValue, authHeaderSecretName}; } - getUrlAndQueryParams( + getUrl(rawUrl: string | null | undefined): string | null { + return everythingBefore('?', this.trimOrEmpty(rawUrl)); + } + + getQueryParams( rawUrl: string | null | undefined, rawQueryParams: HttpDatasourceQueryParamFormValue[] | null | undefined, - ): { - url: string | null; - queryParams: string | null; - } { - let rawUrlTrimmed = rawUrl?.trim() ?? ''; + ): string | null { + const queryParamSegments = (rawQueryParams ?? []).map((param) => + this.encodeQueryParam(param), + ); + const queryParams = [ + everythingAfter('?', this.trimOrEmpty(rawUrl)), + ...queryParamSegments, + ] + .filter((it) => !!it) + .join('&'); - const url = everythingBefore('?', rawUrlTrimmed); + return queryParams; + } + getRawQueryParams( + rawUrl: string | null | undefined, + rawQueryParams: HttpDatasourceQueryParamFormValue[] | null | undefined, + ): string | null { const queryParamSegments = (rawQueryParams ?? []).map((param) => - this.encodeQueryParam(param), + this.buildQueryParam( + this.trimOrEmpty(param.paramName), + this.trimOrEmpty(param.paramValue), + ), ); const queryParams = [ - everythingAfter('?', rawUrlTrimmed), + everythingAfter('?', this.trimOrEmpty(rawUrl)), ...queryParamSegments, ] .filter((it) => !!it) .join('&'); - return {url: url || null, queryParams: queryParams || null}; + return queryParams; } private encodeQueryParam(param: HttpDatasourceQueryParamFormValue): string { - const k = param.paramName?.trim() ?? ''; - const v = param.paramValue?.trim() ?? ''; - return `${encodeURIComponent(k)}=${encodeURIComponent(v)}`; + const k = encodeURIComponent(this.trimOrEmpty(param.paramName)); + const v = encodeURIComponent(this.trimOrEmpty(param.paramValue)); + return this.buildQueryParam(k, v); + } + + private trimOrEmpty(s: string | null | undefined): string { + return s?.trim() ?? ''; + } + + private buildQueryParam(name: string, value: string) { + return `${name}=${value}`; } private buildHttpHeaders( diff --git a/src/app/core/validators/valid-query-param.ts b/src/app/core/validators/valid-query-param.ts new file mode 100644 index 000000000..3eea2a134 --- /dev/null +++ b/src/app/core/validators/valid-query-param.ts @@ -0,0 +1,18 @@ +import {AbstractControl, ValidationErrors, ValidatorFn} from '@angular/forms'; + +/** + * Validates that param string does not contain "=" or "&" characters + * Temporary solution until EDC double encoding issue is resolved + * See https://github.com/sovity/edc-extensions/issues/582 + * @param control control + */ +export const validQueryParam: ValidatorFn = ( + control: AbstractControl, +): ValidationErrors | null => { + const value: string = control.value; + if (value?.includes('=') || value?.includes('&')) { + return {invalidQueryParam: true}; + } + + return null; +}; diff --git a/src/app/core/validators/validation-messages.ts b/src/app/core/validators/validation-messages.ts index 6402d1930..6d1a5f554 100644 --- a/src/app/core/validators/validation-messages.ts +++ b/src/app/core/validators/validation-messages.ts @@ -9,4 +9,5 @@ export class ValidationMessages { `${field} must start with "${prefix}".`; invalidDateRangeMessage = 'Need valid date range.'; idExistsErrorMessage = 'ID already exists.'; + invalidQueryParam = "Must not contain '=' or '&' characters."; } diff --git a/src/app/routes/connector-ui/asset-page/asset-edit-dialog/asset-edit-dialog.component.html b/src/app/routes/connector-ui/asset-page/asset-edit-dialog/asset-edit-dialog.component.html index 3d8604159..4ed9c83d3 100644 --- a/src/app/routes/connector-ui/asset-page/asset-edit-dialog/asset-edit-dialog.component.html +++ b/src/app/routes/connector-ui/asset-page/asset-edit-dialog/asset-edit-dialog.component.html @@ -490,6 +490,14 @@

required autocomplete="new-query-param-name" [formControl]="header.controls.paramName" /> + {{ header.errors }} + {{ validationMessages.invalidQueryParam }} @@ -500,6 +508,13 @@

placeholder="..." autocomplete="new-query-param-value" [formControl]="header.controls.paramValue" /> + {{ validationMessages.invalidQueryParam }} diff --git a/src/app/routes/connector-ui/asset-page/asset-edit-dialog/form/asset-datasource-form-builder.ts b/src/app/routes/connector-ui/asset-page/asset-edit-dialog/form/asset-datasource-form-builder.ts index 4a75e3a34..9cf7b953b 100644 --- a/src/app/routes/connector-ui/asset-page/asset-edit-dialog/form/asset-datasource-form-builder.ts +++ b/src/app/routes/connector-ui/asset-page/asset-edit-dialog/form/asset-datasource-form-builder.ts @@ -1,5 +1,6 @@ import {Injectable} from '@angular/core'; import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {validQueryParam} from 'src/app/core/validators/valid-query-param'; import {switchDisabledControls} from '../../../../../core/utils/form-group-utils'; import {jsonValidator} from '../../../../../core/validators/json-validator'; import {urlValidator} from '../../../../../core/validators/url-validator'; @@ -120,8 +121,8 @@ export class AssetDatasourceFormBuilder { initial: HttpDatasourceQueryParamFormValue, ): FormGroup { return this.formBuilder.nonNullable.group({ - paramName: [initial.paramName!, Validators.required], - paramValue: [initial.paramValue!], + paramName: [initial.paramName!, [Validators.required, validQueryParam]], + paramValue: [initial.paramValue!, [validQueryParam]], }); } }