diff --git a/packages/grid_client/src/helpers/validator.ts b/packages/grid_client/src/helpers/validator.ts index 99f5a810ec..7101e604a2 100644 --- a/packages/grid_client/src/helpers/validator.ts +++ b/packages/grid_client/src/helpers/validator.ts @@ -51,6 +51,27 @@ function IsAlphanumericExpectUnderscore(validationOptions?: ClassValidatorValida }); }; } + +function IsAlphanumericExpectDashAndUnderscore(validationOptions?: ClassValidatorValidationOptions) { + return function (object: any, propertyName: string) { + registerDecorator({ + name: "IsAlphanumericExpectDashAndUnderscore", + target: object.constructor, + propertyName: propertyName, + options: validationOptions, + constraints: [`${propertyName} must contain only letters, numbers, dashes, and underscores`], + validator: { + validate(value: any) { + return /^[a-zA-Z0-9_-]+$/.test(value); + }, + defaultMessage: buildMessage( + eachPrefix => eachPrefix + "$property must contain only letters, numbers, dashes, and underscores", + validationOptions, + ), + }, + }); + }; +} interface ValidationOptions { props?: boolean | string | string[]; methods?: boolean | string | string[]; @@ -205,4 +226,5 @@ export { type ValidationOptions, ValidateMembers, IsAlphanumericExpectUnderscore, + IsAlphanumericExpectDashAndUnderscore, }; diff --git a/packages/grid_client/src/modules/models.ts b/packages/grid_client/src/modules/models.ts index 9e2d0d2b50..c98a962f19 100644 --- a/packages/grid_client/src/modules/models.ts +++ b/packages/grid_client/src/modules/models.ts @@ -21,7 +21,7 @@ import { ValidateNested, } from "class-validator"; -import { Features, IsAlphanumericExpectUnderscore } from "../helpers"; +import { Features, IsAlphanumericExpectDashAndUnderscore, IsAlphanumericExpectUnderscore } from "../helpers"; import { Deployment } from "../zos/deployment"; import { ZdbModes } from "../zos/zdb"; import { blockchainType } from "./blockchainInterface"; @@ -254,7 +254,7 @@ class QSFSZDBGetModel extends BaseGetDeleteModel {} class QSFSZDBDeleteModel extends BaseGetDeleteModel {} class BaseGatewayNameModel { - @Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string; + @Expose() @IsString() @IsNotEmpty() @IsAlphanumericExpectDashAndUnderscore() @MaxLength(NameLength) name: string; } class GatewayFQDNModel extends BaseGatewayNameModel { @@ -361,7 +361,7 @@ class GetServiceContractModel { @Expose() @IsInt() @Min(1) serviceId: number; } class NameContractGetModel { - @Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string; + @Expose() @IsString() @IsNotEmpty() @IsAlphanumericExpectDashAndUnderscore() @MaxLength(NameLength) name: string; } class NodeContractUpdateModel { diff --git a/packages/grid_client/src/primitives/gateway.ts b/packages/grid_client/src/primitives/gateway.ts index f4d8f9743a..3493a251d2 100644 --- a/packages/grid_client/src/primitives/gateway.ts +++ b/packages/grid_client/src/primitives/gateway.ts @@ -59,7 +59,7 @@ class GWPrimitive { const name_workload = new Workload(); name_workload.version = version; - name_workload.name = name; + name_workload.name = name.replace(/-/g, ""); name_workload.type = WorkloadTypes.gatewaynameproxy; name_workload.data = nameObj; name_workload.metadata = metadata; diff --git a/packages/playground/src/components/deployment_data_dialog.vue b/packages/playground/src/components/deployment_data_dialog.vue index 30ddb6a9a4..1c19317029 100644 --- a/packages/playground/src/components/deployment_data_dialog.vue +++ b/packages/playground/src/components/deployment_data_dialog.vue @@ -3,29 +3,12 @@ -
+
details JSON
- - - - - - - @@ -518,7 +523,7 @@ async function onDelete(k8s = false) { if (projectNameLower === ProjectName.Domains.toLowerCase()) { await deleteGatewayDeployment( updateGrid(grid, { projectName: projectNameLower }), - item[0].workloads[0].name as string, + item[0].workloads[0].data.name ? (item[0].workloads[0].data.name as string) : item[0].workloads[0].name, ); } else { await deleteDeployment(updateGrid(grid!, { projectName: item.projectName }), { diff --git a/packages/playground/src/weblets/tf_domains.vue b/packages/playground/src/weblets/tf_domains.vue index 7832d8fdc8..0b5d083591 100644 --- a/packages/playground/src/weblets/tf_domains.vue +++ b/packages/playground/src/weblets/tf_domains.vue @@ -13,10 +13,17 @@ :rules="[ validators.required('Subdomain is required.'), validators.isLowercase('Subdomain should consist of lowercase letters only.'), - validators.isAlphanumeric('Subdomain should consist of letters and numbers only.'), - subdomain => validators.isAlpha('Subdomain must start with alphabet char.')(subdomain[0]), + validators.IsAlphanumericExpectDashAndUnderscore( + 'Subdomain should consist only letters, numbers, dashes, and underscores', + ), + (subdomain: string) => + validators.isAlphanumeric('Subdomain should start of letters and numbers only.')(subdomain[0]), + (subdomain: string) => + validators.isAlphanumeric('Subdomain should end with letters and numbers only.')( + subdomain[subdomain.length - 1], + ), validators.minLength('Subdomain must be at least 4 characters.', 4), - subdomain => validators.maxLength('Subdomain cannot exceed 35 characters.', 35)(subdomain), + (subdomain: string) => validators.maxLength('Subdomain cannot exceed 35 characters.', 35)(subdomain), ]" :async-rules="[validateSubdomain]" #="{ props }" @@ -118,7 +125,9 @@ async function deploy() { layout.value.setStatus("deploy", "Preparing to deploy gateway..."); const gateway: any = await deployGatewayName(grid, selectionDetails.value?.domain, { - subdomain: subdomain.value, + subdomain: selectionDetails.value?.domain?.enabledCustomDomain + ? subdomain.value.replace(/-/g, "") + : subdomain.value, ip: ip.value, port: port.value, tlsPassthrough: passThrough.value, @@ -139,7 +148,6 @@ async function validateSubdomain() {