Skip to content

Commit

Permalink
Merge pull request #3057 from threefoldtech/development_2.6_flexible_…
Browse files Browse the repository at this point in the history
…vm_name

Adding a custom validation for flexible VM naming
  • Loading branch information
maayarosama authored Jul 8, 2024
2 parents 4e4814d + 3e1248f commit d863879
Show file tree
Hide file tree
Showing 27 changed files with 95 additions and 79 deletions.
33 changes: 30 additions & 3 deletions packages/grid_client/src/helpers/validator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ValidationError } from "@threefold/types";
import { plainToInstance } from "class-transformer";
import { validateSync } from "class-validator";
import { buildMessage, registerDecorator, validateSync } from "class-validator";
import { ValidationOptions as ClassValidatorValidationOptions } from "class-validator";

function validateObject(obj) {
const errors = validateSync(obj);
Expand Down Expand Up @@ -30,7 +31,26 @@ function validateHexSeed(seed: string, length: number): boolean {
}
return true;
}

function IsAlphanumericExpectUnderscore(validationOptions?: ClassValidatorValidationOptions) {
return function (object: any, propertyName: string) {
registerDecorator({
name: "IsAlphanumericExpectUnderscore",
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [`${propertyName} must contain only letters, numbers, and underscores`],
validator: {
validate(value: any) {
return /^[a-zA-Z0-9_]*$/.test(value);
},
defaultMessage: buildMessage(
eachPrefix => eachPrefix + "$property must contain only letters, numbers, and underscores",
validationOptions,
),
},
});
};
}
interface ValidationOptions {
props?: boolean | string | string[];
methods?: boolean | string | string[];
Expand Down Expand Up @@ -178,4 +198,11 @@ function _getMethods(ctor: any, options: Required<ValidationOptions>): string[]
return [];
}

export { validateObject, validateInput, validateHexSeed, type ValidationOptions, ValidateMembers };
export {
validateObject,
validateInput,
validateHexSeed,
type ValidationOptions,
ValidateMembers,
IsAlphanumericExpectUnderscore,
};
15 changes: 8 additions & 7 deletions packages/grid_client/src/modules/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import {
ValidateNested,
} from "class-validator";

import { IsAlphanumericExpectUnderscore } from "../helpers";
import { Deployment } from "../zos/deployment";
import { ZdbModes } from "../zos/zdb";
import { blockchainType } from "./blockchainInterface";
const NameLength = 15;
const NameLength = 50;
const FarmNameLength = 40;

enum ContractStates {
Expand Down Expand Up @@ -97,11 +98,11 @@ class MyceliumNetworkModel {
}

class BaseGetDeleteModel {
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string;
@Expose() @IsString() @IsNotEmpty() @IsAlphanumericExpectUnderscore() @MaxLength(NameLength) name: string;
}

class MachineModel {
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string;
@Expose() @IsString() @IsNotEmpty() @MaxLength(NameLength) @IsAlphanumericExpectUnderscore() name: string;
@Expose() @IsInt() @Min(1) node_id: number;
@Expose() @IsOptional() @Type(() => DiskModel) @ValidateNested({ each: true }) disks?: DiskModel[];
@Expose() @IsOptional() @Type(() => QSFSDiskModel) @ValidateNested({ each: true }) qsfs_disks?: QSFSDiskModel[];
Expand All @@ -124,7 +125,7 @@ class MachineModel {
}

class MachinesModel {
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string;
@Expose() @IsString() @IsNotEmpty() @IsAlphanumericExpectUnderscore() @MaxLength(NameLength) name: string;
@Expose() @Type(() => NetworkModel) @ValidateNested() network: NetworkModel;
@Expose() @Type(() => MachineModel) @ValidateNested({ each: true }) machines: MachineModel[];
@Expose() @IsString() @IsOptional() metadata?: string;
Expand All @@ -137,7 +138,7 @@ class AddMachineModel extends MachineModel {
}

class DeleteMachineModel {
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string;
@Expose() @IsString() @IsNotEmpty() @IsAlphanumericExpectUnderscore() @MaxLength(NameLength) name: string;
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) deployment_name: string;
}

Expand Down Expand Up @@ -233,7 +234,7 @@ class QSFSZDBGetModel extends BaseGetDeleteModel {}
class QSFSZDBDeleteModel extends BaseGetDeleteModel {}

class BaseGatewayNameModel {
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength + 20) name: string;
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string;
}

class GatewayFQDNModel extends BaseGatewayNameModel {
Expand Down Expand Up @@ -340,7 +341,7 @@ class GetServiceContractModel {
@Expose() @IsInt() @Min(1) serviceId: number;
}
class NameContractGetModel {
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength + 20) name: string;
@Expose() @IsString() @IsNotEmpty() @IsAlphanumeric() @MaxLength(NameLength) name: string;
}

class NodeContractUpdateModel {
Expand Down
4 changes: 2 additions & 2 deletions packages/playground/src/components/caprover_worker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
:value="$props.modelValue.name"
#="{ props }"
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/components/k8s_worker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.isAlphanumeric('Name should consist of alphabets & numbers only.'),
validators.minLength('Name minimum length is 2 chars.', 2),
validators.maxLength('Name max length is 15 chars.', 15),
validators.maxLength('Name max length is 50 chars.', 50),
]"
#="{ props }"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
validators.isAlphanumeric('Subdomain should consist of letters and numbers only.'),
subdomain => validators.isAlpha('Subdomain must start with alphabet char.')(subdomain[0]),
validators.minLength('Subdomain must be at least 4 characters.', 4),
subdomain => validators.maxLength('Subdomain cannot exceed 30 characters.', 30)(subdomain),
subdomain => validators.maxLength('Subdomain cannot exceed 50 characters.', 50)(subdomain),
]"
:async-rules="gatewayTab === 1 ? [validateSubdomain] : []"
#="{ props }"
Expand Down
8 changes: 8 additions & 0 deletions packages/playground/src/utils/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ export function requiredTrue(msg: string) {
};
}

export function IsAlphanumericExpectUnderscore(msg: string) {
return (value: string) => {
if (!/^[a-zA-Z0-9_]*$/.test(value)) {
return { message: msg, requiredTrue: true };
}
};
}

export function isAfter(msg: string, date?: string) {
return (value: string) => {
if (!validator.isAfter(value, date)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/playground/src/weblets/freeflow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
:value="threebotName"
:rules="[
validators.required('Name is required.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
validators.minLength('Name must be at least 4 characters.', 4),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
7 changes: 3 additions & 4 deletions packages/playground/src/weblets/full_vm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down Expand Up @@ -106,7 +105,7 @@
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Disk minLength is 2 chars.', 2),
validators.isAlphanumeric('Disk name only accepts alphanumeric chars.'),
validators.maxLength('Disk maxLength is 15 chars.', 15),
validators.maxLength('Disk maxLength is 50 chars.', 50),
]"
#="{ props }"
>
Expand Down
7 changes: 3 additions & 4 deletions packages/playground/src/weblets/micro_vm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of alphabets & numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down Expand Up @@ -132,7 +131,7 @@
}),
validators.minLength('Disk minLength is 2 chars.', 2),
validators.isAlphanumeric('Disk name only accepts alphanumeric chars.'),
validators.maxLength('Disk maxLength is 15 chars.', 15),
validators.maxLength('Disk maxLength is 50 chars.', 50),
]"
#="{ props }"
>
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_algorand.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_casperlabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_discourse.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
7 changes: 3 additions & 4 deletions packages/playground/src/weblets/tf_funkwhale.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand All @@ -38,7 +37,7 @@
validators.isAlphanumeric('Username should consist of letters and numbers only.'),
username => validators.isAlpha('Username must start with alphabet char.')(username[0]),
validators.minLength('Username must be at least 2 characters.', 2),
validators.maxLength('Username cannot exceed 15 characters.', 15),
validators.maxLength('Username cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_kubernetes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.isAlphanumeric('Name should consist of alphabets & numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
validators.minLength('Name minimum length is 2 chars.', 2),
validators.maxLength('Name max length is 15 chars.', 15),
validators.maxLength('Name max length is 50 chars.', 50),
]"
#="{ props }"
>
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_mattermost.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_nextcloud.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
3 changes: 1 addition & 2 deletions packages/playground/src/weblets/tf_node_pilot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_nostr.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of alphabets & numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
6 changes: 2 additions & 4 deletions packages/playground/src/weblets/tf_owncloud.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand All @@ -42,7 +41,6 @@
:value="username"
:rules="[
validators.required('Username is required.'),
validators.isLowercase('Username should consist of lowercase letters only.'),
validators.isAlphanumeric('Username should consist of letters and numbers only.'),
username => validators.isAlpha('Username must start with alphabet char.')(username[0]),
validators.minLength('Username must be at least 2 characters.', 2),
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_peertube.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
5 changes: 2 additions & 3 deletions packages/playground/src/weblets/tf_presearch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@
:value="name"
:rules="[
validators.required('Name is required.'),
validators.isLowercase('Name should consist of lowercase letters only.'),
validators.isAlphanumeric('Name should consist of letters and numbers only.'),
validators.IsAlphanumericExpectUnderscore('Name should consist of letters ,numbers and underscores only.'),
name => validators.isAlpha('Name must start with alphabet char.')(name[0]),
validators.minLength('Name must be at least 2 characters.', 2),
validators.maxLength('Name cannot exceed 15 characters.', 15),
validators.maxLength('Name cannot exceed 50 characters.', 50),
]"
#="{ props }"
>
Expand Down
Loading

0 comments on commit d863879

Please sign in to comment.