4

我想用 TypeORM 和 MongoDB 创建一个 NestJs API。我的实体 id 字段的类型为ObjectID. 控制器路由应该在将传入的 id 传递给服务之前验证它们。我知道 Nest 附带 ParseIntPipe 和 ParseUUIDPipe 但据我所知,我没有什么可以用于 MongoDBs ObjectID

因此,我为这些字段创建了自己的管道,如此处所述https://docs.nestjs.com/pipes#transformation-use-case

import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
import { ObjectID } from 'typeorm';

@Injectable()
export class ParseObjectIdPipe implements PipeTransform<any, ObjectID> {
  transform(value: any): ObjectID {
    const validObjectId: boolean = ObjectID.isValid(value);

    if (validObjectId) {
      throw new BadRequestException('Invalid ObjectId');
    }

    const objectId: ObjectID = ObjectID.createFromHexString(value);
    return objectId;
  }
}

并希望这能解决问题,即使是边缘情况。我可以将它用于我的路线参数,例如

  @Get(':id')
  public getUserById(@Param('id', ParseObjectIdPipe) id: ObjectID): Promise<User> {
    return this.usersService.getUserById(id);
  }

我遇到的问题是某些路线需要Body验证。我使用这里描述的类验证器包

https://docs.nestjs.com/techniques/validation

似乎我必须为这些ObjectID字段创建自己的类验证器装饰器,但这应该没问题。也许我会在这里找到一些关于如何做到这一点的东西https://github.com/typestack/class-validator#custom-validation-classes。但是如何将这些字段转换为类型ObjectID?我以后也可以使用自定义管道吗?


更新:

我还尝试通过 class-transformer 包转换值。所以这个代码是

import { ObjectID } from 'typeorm';
import { Type, Transform } from 'class-transformer';
import { BadRequestException } from '@nestjs/common';

export class FooDTO {
  @Type(() => ObjectID)
  @Transform(bar => {
    if (ObjectID.isValid(bar)) {
      throw new BadRequestException('Invalid ObjectId');
    }

    return ObjectID.createFromHexString(bar);
  })
  public bar: ObjectID;
}

不幸的是,价值bar总是undefined。但也许这段代码可能有助于验证和转换目的......

4

5 回答 5

5

我拿走了你的代码并改变了一些部分。我测试了它,它工作正常。

import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
import { Types } from 'mongoose';

@Injectable()
export class ParseObjectIdPipe implements PipeTransform<any, Types.ObjectId> {
    transform(value: any): Types.ObjectId {
        const validObjectId = Types.ObjectId.isValid(value);

        if (!validObjectId) {
            throw new BadRequestException('Invalid ObjectId');
        }

        return Types.ObjectId.createFromHexString(value);
    }
}
于 2020-12-24T12:01:08.457 回答
3

对于类转换器方法,这对我有用

import { IsNotEmpty } from "class-validator";
import { Type, Transform } from 'class-transformer';
import { Types } from "mongoose"

export class CreateCommentDto {

    @IsNotEmpty()
    @Type(() => Types.ObjectId)
    @Transform(toMongoObjectId)
    articleId: Types.ObjectId

使用“toMongoObjectId”的定义:

export function toMongoObjectId({ value, key }): Types.ObjectId {
    if ( Types.ObjectId.isValid(value) && ( Types.ObjectId(value).toString() === value)) {
        return Types.ObjectId(value);
    } else {
        throw new BadRequestException(`${key} is not a valid MongoId`);
    }
}
于 2021-06-25T03:41:33.610 回答
2

所以为了Body验证我可以IsMongoId()从这里使用装饰器

https://github.com/typestack/class-validator#manual-validation

验证看起来像

import { IsMongoId } from 'class-validator';
import { ObjectID } from 'typeorm';

export class FooDTO {
  @IsMongoId()
  public bar: ObjectID;
}
于 2020-02-20T07:25:58.910 回答
0

你得到未定义,因为你从错误的库中导入。你需要改变这个:

import { ObjectID } from 'typeorm';

为了这:

import { ObjectID } from 'mongodb';
于 2020-08-10T22:20:08.833 回答
0

只需使用以下代码在代码中创建对象 id 的管道:

import { PipeTransform, Injectable, BadRequestException } from 
'@nestjs/common';
import { ObjectID } from 'mongodb';

@Injectable()
export class ParseObjectIdPipe implements PipeTransform<any, ObjectID> {

public transform(value: any): ObjectID {
try {
  const transformedObjectId: ObjectID = ObjectID.createFromHexString(value);
  return transformedObjectId;
} catch (error) {
  throw new BadRequestException('Validation failed (ObjectId is expected)');
}
}
}

并在控制器方法中添加 piple:

@Post('cat/:id')
async cat(
@Param('id', ParseObjectIdPipe) id: ObjectId,
@Res() res,
@Body() cat: catDTO[],)
于 2021-08-17T12:48:18.907 回答