6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

express-validatorでユーザー登録時にバリデーション処理を行う

Node.jsでのオススメ書籍

どうもNode.js入門中のものです。

タイトルとは少しそれますが、
まずは、Node.jsを勉強する上で、非常にオススメの書籍をまずは紹介したいと思います。
それがこちらです。

入門Node.jsプログラミング

上記は翻訳版で、原書はこちらになります。

Get Programming with Node.js

Node.jsでMVCパターンを実装し、フロントはテンプレートエンジンで実装するというフロントエンド強強の方には不満な構成かもしれませんが、
基本的なアプリケーションの作り方と、特にセキュリティ関連のバックエンドの実装を学ぶことができるのでとてもオススメです。

(AmazonのレビューにあるようにGoogle翻訳すれすれの変な日本語が混ざっていますが、Google翻訳に慣れている方なら苦もなく読めると思います。原書の内容が素晴らしいので、よし)

今回はログイン時の実装でバリデーションの実装を行う際に最新バージョンだとはまってしまう箇所があったので、解説したいと思います。

そもそもバリデーションってなに?

「バリデーション」とは、「検証、実証、認可、妥当性」を意味する英単語になります。

例えば、「文書をバリデーション」といった場合には、「記述・入力されたデータが、あらかじめ規定された条件・使用に適合しているか検証・確認する。」ことを表します。
引用:(https://career-picks.com/business-yougo/validation/)

です。今回の実装では、ユーザー登録をする際に、メールアドレスが正しい形式で入力されているか?zipCodeが5ケタで正しく入力されているかをユーザー登録の前にバリデーションします。

express-validatorをインストール

このバリデーションを実装する方法は様々なアプローチがあるそうですが、本書ではexpress-validatorを用いた方法が紹介されています。
インストールします。

npm i express-validator -S

最初に本書にある方法で実装してみます。

main.js
const express = require("express"),
  app = express(),
  router = express.Router(),
  expressValidator = require("express-validator");

router.use(express.json());

router.use(expressValidator());

router.post(
  '/users/create',
  usersController.validate,
  usersController.create,
  usersController.redirectView,
);

userController.js
"use strict"
const User = require("../models/user")

// ----(中略) ----- //

module.exports = {
 create: (req, res, next) => {
  if (req.skip) next();
  let userParams = getUserParams(req.body);
  User.create(userParams)
    .then(user => {
      req.flash("success", `${user.fullName}'s account created successfully!`);
      res.locals.redirect = "/users";
      res.locals.user = user;
      next();
    })
    .catch(error => {
      console.log(`Error saving user: ${error.message}`);
      res.locals.redirect = "/users/new";
      req.flash("error", `Failed to create user account because: ${error.message}.`);
      next();
    });
},
redirectView: (req, res, next) => {
  let redirectPath = res.locals.redirect;
  if (redirectPath) res.redirect(redirectPath);
  else next();
},
validate: (req, res, next) => {
  req
    .sanitizeBody("email")
    .normalizeEmail({
      all_lowercase: true
    })
    .trim();
  req.check("email", "Email is invalid").isEmail();
  req
    .check("zipCode", "Zip code is invalid")
    .notEmpty()
    .isInt()
    .isLength({
      min: 5,
      max: 5
    })
    .equals(req.body.zipCode);
  req.check("password", "Password cannot be empty").notEmpty();

  req.getValidationResult().then(error => {
    if (!error.isEmpty()) {
      let messages = error.array().map(e => e.msg);
      req.skip = true;
      req.flash("error", messages.join(" and "));
      res.locals.redirect = "/users/new";
      next();
    } else {
      next();
    }
  });
}
};

このようなエラーが出ます。

Express Validator Error: expressValidator is not a function

解決方法

expressValidatorは関数として使えません。というエラーです。ググってみたら、v6.0.0から実装が変わっているようです。

(https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F56733975%2Fexpress-validator-error-expressvalidator-is-not-a-function%2F56734897&anno=2)

上記のリンクのように実装しても良いのですが、main.jsの処理が大きくなるので、usersControllerに実装したいと思います。

main.js
- expressValidator = require("express-validator");
- router.use(expressValidator());
userController.js
const User = require('../models/user'),
  { check, sanitizeBody, validationResult } = require('express-validator'),

module.exports = {
validate: (req, res, next) => {
    sanitizeBody('email')
      .normalizeEmail({
        all_lowercase: true,
      })
      .trim();
    check('email', 'Email is invalid').isEmail();

    check('zipCode', 'Zip code is invalid')
      .notEmpty()
      .isInt()
      .isLength({
        min: 5,
        max: 5,
      })
      .equals(req.body.zipCode);
    check('password', 'Password cannot be empty').notEmpty();

    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      let messages = error.array().map(e => e.msg);
      req.skip = true;
      req.flash('error', messages.join(' and '));

      res.locals.redirect = '/users/new';
      next();
    } else {
      next();
    }
  },
}

userController.jsでexpress-validatorをインストールする形にしました。
sanitizeBodyメソッドでメールを全て小文字にし、空白を無くしてから、
checkメソッドで正しい形式・すでに登録されているアドレスではないかをバリデーションしています。
同様に
同様にzipCode,passwordもcheckしています。notEmpty()は空白ではないかをcheckするメソッドです。

最後にvalidationResultメソッドで、それぞれの形式が正しいか。一致するかを検証し、誤りがあった場合ユーザー作成画面にリダイレクトしています。

まとめ

すごい良い本なので、Node.jsに興味のある方は読んでみてください。
実装方法やパッケージでもっと良いのがあったらコメントいただけると嬉しいです。

ありがとうございました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
6
Help us understand the problem. What are the problem?