How to implement class-validator as a middleware?

Viewed 3158

I have been trying to use class-validator as middleware to validate some of my data.

I would love to get some advice as to

how can I also validate updates and what's a good validation

Here is the current class validator to validate the req.body sent when trying to register.

export default async (req: Request, res: Response, next: NextFunction) => {
  let user = new User();
  user.username = req.body.username;
  user.email = req.body.email;
  user.password = req.body.password;
  let fieldErrors = await validate(user);
  if (fieldErrors.length > 0) {
    let errors = ValidatorErrToFieldErr(fieldErrors);
    next(new HttpExeception({ statusCode: httpCode.BAD_REQUEST, errors }));
  } else {
    next();
  }
};

What is a good validation pattern? I controller that handles some of the logic which in turn calls the service to mutate the database.

AuthController.ts

public static Register = async (
    req: Request,
    res: Response,
    next: NextFunction
  ) => {
    try {
      req.body.password = await argon2.hash(req.body.password);
      let modelUser = await service.addUser(req.body);
      let user: IUserMe = {
        //reasign user fields
      };
      req.session.user = {
        id: user.id,
        username: user.username,
        isAdmin: user.isAdmin,
      };

      res.json({ user });
    } catch (error) {
      if (error.code === "23505") {
        next(
          new HttpExeception({
            statusCode: httpCode.BAD_REQUEST,
            errors: duplicationErrToFieldError(error.detail),
          })
        );
      } else next(new HttpExeception({ statusCode: httpCode.SERVER_ERROR }));
    }
  };

UserService.ts

async addUser(input: IRegisterInput): Promise<User> {
    return await getRepository(User).save(input);
  }
1 Answers

So most middleware it’s called inside the routes themselves. I’ll use an example with Express, Passport, and TypeScript since it’s what I know best.

Say i don’t want users to access my “/home” page without signing in. So I write a middleware function:

export default ( req: Request, res: Response, next: NextFunction): void => {
    if(req.user != undefined){
      next();
    }
   else{
      res.status(401);
   }
}

This would be analogous to your class-validator function. Now, we need to make sure that this function runs before any API calls are made to “/home”.

Thus, we write the api route as

import * as express from “express”;
import {Request, Response} from “express”;
import isAuthenticated from “isAuthenticated.ts”;

class HomeRouter{
    public path = “/”;
    public router = App.router();

    constructor(){
        this.initRoutes();
    }

    public initRoutes(){
        this.router.get(“/home”, isAuthenticated, (req: Request, res: Response) => {
            res.send(“/index.html”);
       }
    }
}

This will force isAuthenticated to run before any of the logic in the rest of route is executed. If you would like the middleware to apply to every call to the server, just put express.use(isAuthenticated); in your server.ts file. If you’re using a technology different from Express that I’ve failed to identify, I’m sure the premise is the same, and the how will be in the documentation.

Related