Search code examples
node.jstypescriptrestnestjssanitization

How to sanitize response body in Node.js and Typescript


I have a backend server written in typescript on node.js using nest.js as framework.

I want to automatically sanitize the response body of my controllers removing undeclared properties of my DTOs.

I have the following files:

class User {
   _id: string
   name: string
   hashedPassword: string
}
class UserDTO {
   _id: string
   name: string
}
@ApiTags('users')
@Controller('users')
export class UsersController {
...
    @Get(':id')
    @UseGuards(JwtAuthGuard)
    @ApiBearerAuth()
    @ApiOperation({ summary: 'Find one user by id' })
    @ApiResponse({
        status: 200,
        type: UserDto,
    })
    async findOne(@Param('id') id: string): Promise<UserDto> {
        return await this.usersService.findById(id) as UserDto;
    }
}

When I declare user as UserDTO I thought that will remove all undeclared properties as UserDTO (in this case the 'hashedPassword') that's not what happened, it still sending the 'hashedPassword', I want to remove it automatically without calling constructores or removing it manually using const { hashedPassword, ...result } = user; return result; on e each service.

It's a pain do this conversions every time I have to send a DTO. I'm looking for something that do this conversions automatically. Does exists something in typescript or in Nest.js that do this conversions automatically for me? Maybe some decorator in the DTO or calling some middleware?

In older projects I used to do this to automatically remove unwanted properties:

const UserSchema = new Schema({
    hashedPassword: String,
    ...
}, {
    timestamps: true,
    toJSON: {
        transform: (doc, ret, options) => {
            delete ret.hashedPassword;
            return ret;
        },
        virtuals: false,
    }
});

Today I consider this a bad implementation because I adding business logic to my repository. I'm looking for something that sanitize my DTOs automatically. Is that possible?


Solution

  • Sounds like you might be looking for Serialization, which Nest has a setup with an interceptor and class-transformer calling classToPlain() to serialize the response. It sounds like you might be working with Mongo, so keep in mind you may need to do a bit extra in your services to get a true class instance that class-transformer can work with.

    As for why your above attempt didn't work, as mentioned by jonrsharpe in the comments, type information doesn't exist at runtime. It's purely there for devs during development and compile time to help us catch bugs that could be easily avoided. Also, to take it a step further x as y tells the compiler "I know that x is of type y, whether you can read that from the code I've written or not". It's essentially telling the compiler you know more than it, so it shouldn't worry.