0

I need to check if some datas (which can be optional in db(typeorm entity) level) is not empty using class-validator dto for user activation after reading these data from user db .

Controller level validations for body, query and all using class-validator is working fine for me

DTO file

export class UserActiveDTO {
    @IsNotEmpty()
    @IsString()
    readonly id: string;
  
    @IsNotEmpty()
    @IsString()
    readonly name: string;
  
    @IsNotEmpty()
    @IsString()
    readonly role: string;

    //.. other data validations
}

Service File

// after reading user form findOne (typeorm)
let userCanBeActive: boolean = false;
try {
    const canActiveUser: UserActiveDTO = user;

    // tried to validate user using validate form class-validator
    const vErrors = await validate(canActiveUser, {});
    if (vErrors.length > 0) throw vErrors;
    
    userCanBeActive = true;
  } catch (error) {
    userCanBeActive = false;
}

My above code always gives userCanBeActive true, even if the user is missing some of the property I mensioned in DTO file. What is best practice of validating these type of scenarios in nest js ?

2 Answers 2

0

I would be willing to bet that user is not an instance of UserActiveDTO and it just satisfies the interface. class-validator does not work on plain objects so you must convert the object into a class instance for validate to work

Sign up to request clarification or add additional context in comments.

4 Comments

user is an instance of User entity, I mapped it to canActiveUser by specifying the type UserActiveDTO, so canActivateUser should be an instance of UserActiveDTO. Isn't that how it works.
You specified a type for Typescript. You didn't change the instance though. If you were to log user you'd still get the class type of User. Or in other words, if you tried user instanceof UserActiveDTO you'd get false. That would need to be true for validate to work
what about canActiveUser, it should be the type of UserActiveDTO and am validating with canActiveUser not User. Or Is there any other method to do that?
Typescript is structurally typed. All you did with the :UserActiveDTO is told Typescript that canActiveUser should match the interface of UserActiveDTO. To actually make it an instance (what class-validator needs) you need to use the UserActiveDTO constructor (new UserActiveDTO())
0

To validate an object returned from the database using class-validator in NestJS, there are a few things to adjust and ensure:

Transform the Plain Object to a DTO: The object retrieved from the database (user in this case) is a plain JavaScript object. To enable validation, you need to transform it into an instance of the DTO class (UserActiveDTO).

Use plainToInstance from class-transformer: This ensures that the object is converted to an instance of the DTO class and can then be validated.

Ensure Validation Errors Are Handled Properly: Validate the transformed instance and check for validation errors.

import { validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';
import { UserActiveDTO } from './dto/user-active.dto';

async function checkUserActivation(user: any): Promise<boolean> {
  try {
    // Transform the plain object to an instance of the DTO
    const canActiveUser = plainToInstance(UserActiveDTO, user, {
      excludeExtraneousValues: true, // Only include validated properties
    });

    // Validate the transformed DTO instance
    const vErrors = await validate(canActiveUser, { whitelist: true });

    if (vErrors.length > 0) {
      console.error('Validation errors:', vErrors);
      return false;
    }

    return true;
  } catch (error) {
    console.error('Error during validation:', error);
    return false;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.