add constraint
This commit is contained in:
parent
e0d2f7652c
commit
43d34250e2
75
src/modules/core/constraints/tree.unique.constraint.ts
Normal file
75
src/modules/core/constraints/tree.unique.constraint.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
ValidatorConstraint,
|
||||||
|
ValidatorConstraintInterface,
|
||||||
|
ValidationArguments,
|
||||||
|
registerDecorator,
|
||||||
|
ValidationOptions,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { merge, isNil } from 'lodash';
|
||||||
|
import { DataSource, ObjectType } from 'typeorm';
|
||||||
|
|
||||||
|
type Condition = {
|
||||||
|
entity: ObjectType<any>;
|
||||||
|
|
||||||
|
property?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
@ValidatorConstraint({ name: 'treeDataUnique', async: true })
|
||||||
|
@Injectable()
|
||||||
|
export class TreeUniqueConstraint implements ValidatorConstraintInterface {
|
||||||
|
constructor(private dataSource: DataSource) {}
|
||||||
|
|
||||||
|
async validate(value: any, args: ValidationArguments) {
|
||||||
|
// 获取要验证的模型和字段
|
||||||
|
const config: Omit<Condition, 'entity'> = {
|
||||||
|
property: args.property,
|
||||||
|
};
|
||||||
|
const condition = ('entity' in args.constraints[0]
|
||||||
|
? merge(config, args.constraints[0])
|
||||||
|
: {
|
||||||
|
...config,
|
||||||
|
entity: args.constraints[0],
|
||||||
|
}) as unknown as Required<Condition>;
|
||||||
|
if (!condition.entity) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 查询是否存在数据,如果已经存在则验证失败
|
||||||
|
const repo = this.dataSource.getRepository(condition.entity);
|
||||||
|
return isNil(
|
||||||
|
await repo.findOne({ where: { [condition.property]: value }, withDeleted: true }),
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
// 如果数据库操作异常则验证失败
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultMessage(args: ValidationArguments) {
|
||||||
|
const { entity, property } = args.constraints[0];
|
||||||
|
const queryProperty = property ?? args.property;
|
||||||
|
if (!(args.object as any).getManager) {
|
||||||
|
return 'getManager function not been found!';
|
||||||
|
}
|
||||||
|
if (!entity) {
|
||||||
|
return 'Model not been specified!';
|
||||||
|
}
|
||||||
|
return `${queryProperty} of ${entity.name} must been unique!`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IsUnique(
|
||||||
|
params: ObjectType<any> | Condition,
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
) {
|
||||||
|
return (object: Record<string, any>, propertyName: string) => {
|
||||||
|
registerDecorator({
|
||||||
|
target: object.constructor,
|
||||||
|
propertyName,
|
||||||
|
options: validationOptions,
|
||||||
|
constraints: [params],
|
||||||
|
validator: TreeUniqueConstraint,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
89
src/modules/core/constraints/tree.unique.exist.constraint.ts
Normal file
89
src/modules/core/constraints/tree.unique.exist.constraint.ts
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
registerDecorator,
|
||||||
|
ValidationArguments,
|
||||||
|
ValidationOptions,
|
||||||
|
ValidatorConstraint,
|
||||||
|
ValidatorConstraintInterface,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { isNil, merge } from 'lodash';
|
||||||
|
import { DataSource, Not, ObjectType } from 'typeorm';
|
||||||
|
|
||||||
|
type Condition = {
|
||||||
|
entity: ObjectType<any>;
|
||||||
|
|
||||||
|
ignore?: string;
|
||||||
|
|
||||||
|
ignoreKey?: string;
|
||||||
|
|
||||||
|
property?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
@ValidatorConstraint({ name: 'treeDataUniqueExist', async: true })
|
||||||
|
@Injectable()
|
||||||
|
export class TreeUniqueExistContraint implements ValidatorConstraintInterface {
|
||||||
|
constructor(private dataSource: DataSource) {}
|
||||||
|
|
||||||
|
async validate(value: any, args: ValidationArguments) {
|
||||||
|
const config: Omit<Condition, 'entity'> = {
|
||||||
|
ignore: 'id',
|
||||||
|
property: args.property,
|
||||||
|
};
|
||||||
|
const condition = ('entity' in args.constraints[0]
|
||||||
|
? merge(config, args.constraints[0])
|
||||||
|
: {
|
||||||
|
...config,
|
||||||
|
entity: args.constraints[0],
|
||||||
|
}) as unknown as Required<Condition>;
|
||||||
|
if (!condition.entity) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 在传入的dto数据中获取需要忽略的字段的值
|
||||||
|
const ignoreValue = (args.object as any)[
|
||||||
|
isNil(condition.ignoreKey) ? condition.ignore : condition.ignoreKey
|
||||||
|
];
|
||||||
|
// 如果忽略字段不存在则验证失败
|
||||||
|
if (ignoreValue === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 通过entity获取repository
|
||||||
|
const repo = this.dataSource.getRepository(condition.entity);
|
||||||
|
// 查询忽略字段之外的数据是否对queryProperty的值唯一
|
||||||
|
return isNil(
|
||||||
|
await repo.findOne({
|
||||||
|
where: {
|
||||||
|
[condition.property]: value,
|
||||||
|
[condition.ignore]: Not(ignoreValue),
|
||||||
|
},
|
||||||
|
withDeleted: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultMessage(args: ValidationArguments) {
|
||||||
|
const { entity, property } = args.constraints[0];
|
||||||
|
const queryProperty = property ?? args.property;
|
||||||
|
if (!(args.object as any).getManager) {
|
||||||
|
return 'getManager function not been found!';
|
||||||
|
}
|
||||||
|
if (!entity) {
|
||||||
|
return 'Model not been specified!';
|
||||||
|
}
|
||||||
|
return `${queryProperty} of ${entity.name} must been unique!`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IsUniqueExist(
|
||||||
|
params: ObjectType<any> | Condition,
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
) {
|
||||||
|
return (object: Record<string, any>, propertyName: string) => {
|
||||||
|
registerDecorator({
|
||||||
|
target: object.constructor,
|
||||||
|
propertyName,
|
||||||
|
options: validationOptions,
|
||||||
|
constraints: [params],
|
||||||
|
validator: TreeUniqueExistContraint,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
registerDecorator,
|
registerDecorator,
|
||||||
ValidationArguments,
|
ValidationArguments,
|
||||||
ValidationOptions,
|
ValidationOptions,
|
||||||
|
ValidatorConstraint,
|
||||||
ValidatorConstraintInterface,
|
ValidatorConstraintInterface,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { isNil, merge } from 'lodash';
|
import { isNil, merge } from 'lodash';
|
||||||
@ -16,7 +18,8 @@ type Condition = {
|
|||||||
|
|
||||||
property?: string;
|
property?: string;
|
||||||
};
|
};
|
||||||
|
@Injectable()
|
||||||
|
@ValidatorConstraint({ name: 'dataUniqueExist', async: true })
|
||||||
export class UniqueExistConstraint implements ValidatorConstraintInterface {
|
export class UniqueExistConstraint implements ValidatorConstraintInterface {
|
||||||
constructor(protected dataSource: DataSource) {}
|
constructor(protected dataSource: DataSource) {}
|
||||||
|
|
||||||
|
@ -6,7 +6,10 @@ import { DataSource, ObjectType } from 'typeorm';
|
|||||||
import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants';
|
import { CUSTOM_REPOSITORY_METADATA } from '@/modules/database/constants';
|
||||||
|
|
||||||
import { DataExistConstraint } from '../core/constraints/data.exist.constraint';
|
import { DataExistConstraint } from '../core/constraints/data.exist.constraint';
|
||||||
|
import { TreeUniqueConstraint } from '../core/constraints/tree.unique.constraint';
|
||||||
|
import { TreeUniqueExistContraint } from '../core/constraints/tree.unique.exist.constraint';
|
||||||
import { UniqueConstraint } from '../core/constraints/unique.constraint';
|
import { UniqueConstraint } from '../core/constraints/unique.constraint';
|
||||||
|
import { UniqueExistConstraint } from '../core/constraints/unique.exist.constraint';
|
||||||
|
|
||||||
@Module({})
|
@Module({})
|
||||||
export class DatabaseModule {
|
export class DatabaseModule {
|
||||||
@ -15,7 +18,13 @@ export class DatabaseModule {
|
|||||||
global: true,
|
global: true,
|
||||||
module: DatabaseModule,
|
module: DatabaseModule,
|
||||||
imports: [TypeOrmModule.forRoot(configRegister())],
|
imports: [TypeOrmModule.forRoot(configRegister())],
|
||||||
providers: [DataExistConstraint, UniqueConstraint],
|
providers: [
|
||||||
|
DataExistConstraint,
|
||||||
|
UniqueConstraint,
|
||||||
|
UniqueExistConstraint,
|
||||||
|
TreeUniqueConstraint,
|
||||||
|
TreeUniqueExistContraint,
|
||||||
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
static forRepository<T extends Type<any>>(
|
static forRepository<T extends Type<any>>(
|
||||||
|
Loading…
Reference in New Issue
Block a user