add constraint
This commit is contained in:
parent
067ed5d40e
commit
116b92fe98
@ -35,7 +35,8 @@
|
|||||||
"rimraf": "^5.0.1",
|
"rimraf": "^5.0.1",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"sanitize-html": "^2.17.0",
|
"sanitize-html": "^2.17.0",
|
||||||
"typeorm": "^0.3.24"
|
"typeorm": "^0.3.24",
|
||||||
|
"validator": "^13.15.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/cli": "^10.0.3",
|
"@nestjs/cli": "^10.0.3",
|
||||||
@ -48,6 +49,7 @@
|
|||||||
"@types/node": "^20.3.1",
|
"@types/node": "^20.3.1",
|
||||||
"@types/sanitize-html": "^2.16.0",
|
"@types/sanitize-html": "^2.16.0",
|
||||||
"@types/supertest": "^2.0.12",
|
"@types/supertest": "^2.0.12",
|
||||||
|
"@types/validator": "^13.15.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.60.0",
|
"@typescript-eslint/eslint-plugin": "^5.60.0",
|
||||||
"@typescript-eslint/parser": "^5.60.0",
|
"@typescript-eslint/parser": "^5.60.0",
|
||||||
"eslint": "^8.43.0",
|
"eslint": "^8.43.0",
|
||||||
@ -77,7 +79,9 @@
|
|||||||
"moduleNameMapper": {
|
"moduleNameMapper": {
|
||||||
"^@/(.*)$": "<rootDir>/src/$1"
|
"^@/(.*)$": "<rootDir>/src/$1"
|
||||||
},
|
},
|
||||||
"testMatch": ["<rootDir>/test/**/*.test.ts"],
|
"testMatch": [
|
||||||
|
"<rootDir>/test/**/*.test.ts"
|
||||||
|
],
|
||||||
"transform": {
|
"transform": {
|
||||||
"^.+\\.(t|j)s$": "ts-jest"
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
},
|
},
|
||||||
|
@ -53,6 +53,9 @@ importers:
|
|||||||
typeorm:
|
typeorm:
|
||||||
specifier: ^0.3.24
|
specifier: ^0.3.24
|
||||||
version: 0.3.24(better-sqlite3@11.10.0)(reflect-metadata@0.1.14)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@20.17.46)(typescript@5.1.6))
|
version: 0.3.24(better-sqlite3@11.10.0)(reflect-metadata@0.1.14)(ts-node@10.9.2(@swc/core@1.11.24)(@types/node@20.17.46)(typescript@5.1.6))
|
||||||
|
validator:
|
||||||
|
specifier: ^13.15.0
|
||||||
|
version: 13.15.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@nestjs/cli':
|
'@nestjs/cli':
|
||||||
specifier: ^10.0.3
|
specifier: ^10.0.3
|
||||||
@ -84,6 +87,9 @@ importers:
|
|||||||
'@types/supertest':
|
'@types/supertest':
|
||||||
specifier: ^2.0.12
|
specifier: ^2.0.12
|
||||||
version: 2.0.16
|
version: 2.0.16
|
||||||
|
'@types/validator':
|
||||||
|
specifier: ^13.15.1
|
||||||
|
version: 13.15.1
|
||||||
'@typescript-eslint/eslint-plugin':
|
'@typescript-eslint/eslint-plugin':
|
||||||
specifier: ^5.60.0
|
specifier: ^5.60.0
|
||||||
version: 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.1.6))(eslint@8.57.1)(typescript@5.1.6)
|
version: 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.1.6))(eslint@8.57.1)(typescript@5.1.6)
|
||||||
@ -860,8 +866,8 @@ packages:
|
|||||||
'@types/supertest@2.0.16':
|
'@types/supertest@2.0.16':
|
||||||
resolution: {integrity: sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==}
|
resolution: {integrity: sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==}
|
||||||
|
|
||||||
'@types/validator@13.15.0':
|
'@types/validator@13.15.1':
|
||||||
resolution: {integrity: sha512-nh7nrWhLr6CBq9ldtw0wx+z9wKnnv/uTVLA9g/3/TcOYxbpOSZE+MhKPmWqU+K0NvThjhv12uD8MuqijB0WzEA==}
|
resolution: {integrity: sha512-9gG6ogYcoI2mCMLdcO0NYI0AYrbxIjv0MDmy/5Ywo6CpWWrqYayc+mmgxRsCgtcGJm9BSbXkMsmxGah1iGHAAQ==}
|
||||||
|
|
||||||
'@types/yargs-parser@21.0.3':
|
'@types/yargs-parser@21.0.3':
|
||||||
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
|
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
|
||||||
@ -4906,7 +4912,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/superagent': 8.1.9
|
'@types/superagent': 8.1.9
|
||||||
|
|
||||||
'@types/validator@13.15.0': {}
|
'@types/validator@13.15.1': {}
|
||||||
|
|
||||||
'@types/yargs-parser@21.0.3': {}
|
'@types/yargs-parser@21.0.3': {}
|
||||||
|
|
||||||
@ -5486,7 +5492,7 @@ snapshots:
|
|||||||
|
|
||||||
class-validator@0.14.2:
|
class-validator@0.14.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/validator': 13.15.0
|
'@types/validator': 13.15.1
|
||||||
libphonenumber-js: 1.12.8
|
libphonenumber-js: 1.12.8
|
||||||
validator: 13.15.0
|
validator: 13.15.0
|
||||||
|
|
||||||
|
38
src/modules/core/constraints/match.constraint.ts
Normal file
38
src/modules/core/constraints/match.constraint.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
registerDecorator,
|
||||||
|
ValidationArguments,
|
||||||
|
ValidationOptions,
|
||||||
|
ValidatorConstraint,
|
||||||
|
ValidatorConstraintInterface,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
@ValidatorConstraint({ name: 'isMatch' })
|
||||||
|
export class MatchConstraint implements ValidatorConstraintInterface {
|
||||||
|
validate(value: any, validationArguments?: ValidationArguments): Promise<boolean> | boolean {
|
||||||
|
const [relatedProperty, reverse] = validationArguments.constraints;
|
||||||
|
const relatedValue = (validationArguments.object as any)[relatedProperty];
|
||||||
|
return (value === relatedValue) !== reverse;
|
||||||
|
}
|
||||||
|
defaultMessage?(validationArguments?: ValidationArguments): string {
|
||||||
|
const [relatedProperty, reverse] = validationArguments.constraints;
|
||||||
|
return `${relatedProperty} and ${validationArguments.property} ${
|
||||||
|
reverse ? `is` : `don't`
|
||||||
|
} match`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isMatch(
|
||||||
|
relatedProperty: string,
|
||||||
|
reverse = false,
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
) {
|
||||||
|
return (object: RecordAny, propertyName: string) => {
|
||||||
|
registerDecorator({
|
||||||
|
target: object.constructor,
|
||||||
|
propertyName,
|
||||||
|
options: validationOptions,
|
||||||
|
constraints: [relatedProperty, reverse],
|
||||||
|
validator: MatchConstraint,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
48
src/modules/core/constraints/password.constraint.ts
Normal file
48
src/modules/core/constraints/password.constraint.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import {
|
||||||
|
ValidationArguments,
|
||||||
|
ValidatorConstraintInterface,
|
||||||
|
ValidationOptions,
|
||||||
|
registerDecorator,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
type ModelType = 1 | 2 | 3 | 4 | 5;
|
||||||
|
|
||||||
|
export class PasswordConstraint implements ValidatorConstraintInterface {
|
||||||
|
validate(value: any, validationArguments?: ValidationArguments): Promise<boolean> | boolean {
|
||||||
|
const validateModel: ModelType = validationArguments.constraints[0] ?? 1;
|
||||||
|
switch (validateModel) {
|
||||||
|
case 1:
|
||||||
|
return /\d/.test(value) && /[A-Za-z]/.test(value);
|
||||||
|
case 2:
|
||||||
|
return /\d/.test(value) && /[a-z]/.test(value);
|
||||||
|
case 3:
|
||||||
|
return /\d/.test(value) && /[A-Z]/.test(value);
|
||||||
|
case 4:
|
||||||
|
return /\d/.test(value) && /[A-Z]/.test(value) && /[a-z]/.test(value);
|
||||||
|
case 5:
|
||||||
|
return (
|
||||||
|
/\d/.test(value) &&
|
||||||
|
/[A-Z]/.test(value) &&
|
||||||
|
/[a-z]/.test(value) &&
|
||||||
|
/[!@#$%^&]/.test(value)
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return /\d/.test(value) && /[A-Za-z]/.test(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defaultMessage?(validationArguments?: ValidationArguments): string {
|
||||||
|
return "($value) 's format error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IsPassword(model?: ModelType, validationOptions?: ValidationOptions) {
|
||||||
|
return (object: RecordAny, propertyName: string) => {
|
||||||
|
registerDecorator({
|
||||||
|
target: object.constructor,
|
||||||
|
propertyName,
|
||||||
|
options: validationOptions,
|
||||||
|
constraints: [model],
|
||||||
|
validator: PasswordConstraint,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
39
src/modules/core/constraints/phone.number.constraint.ts
Normal file
39
src/modules/core/constraints/phone.number.constraint.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { registerDecorator, ValidationArguments, ValidationOptions } from 'class-validator';
|
||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
|
import { isMobilePhone, IsMobilePhoneOptions, MobilePhoneLocale } from 'validator';
|
||||||
|
|
||||||
|
export function isMatchPhone(
|
||||||
|
value: any,
|
||||||
|
locale: MobilePhoneLocale,
|
||||||
|
options?: IsMobilePhoneOptions,
|
||||||
|
): boolean {
|
||||||
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const phoneArr: string[] = value.split('.');
|
||||||
|
if (phoneArr.length !== 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return isMobilePhone(phoneArr.join(''), locale, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IsMatchPhone(
|
||||||
|
locales?: MobilePhoneLocale | MobilePhoneLocale[],
|
||||||
|
options?: IsMobilePhoneOptions,
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
) {
|
||||||
|
return (object: RecordAny, propertyName: string) => {
|
||||||
|
registerDecorator({
|
||||||
|
target: object.constructor,
|
||||||
|
propertyName,
|
||||||
|
options: validationOptions,
|
||||||
|
constraints: [locales || 'any', options],
|
||||||
|
validator: {
|
||||||
|
validate: (value: any, args: ValidationArguments): boolean =>
|
||||||
|
isMatchPhone(value, args.constraints[0], args.constraints[1]),
|
||||||
|
defaultMessage: (_args: ValidationArguments) =>
|
||||||
|
'$property must be a phone number,eg: +86.12345678901',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user