Просмотр исходного кода

Merge pull request #5129 from weseek/imprv/gw7662-replace-express-form-to-express-validator

imprv: replace express form to express validator
Yuki Takei 4 лет назад
Родитель
Сommit
8ad5663127

+ 0 - 1
packages/app/package.json

@@ -97,7 +97,6 @@
     "escape-string-regexp": "=4.0.0",
     "express": "^4.16.1",
     "express-bunyan-logger": "^1.3.3",
-    "express-form": "~0.12.0",
     "express-mongo-sanitize": "^2.1.0",
     "express-rate-limit": "^5.3.0",
     "express-session": "^1.16.1",

+ 0 - 7
packages/app/src/server/form/admin/userGroupCreate.js

@@ -1,7 +0,0 @@
-const form = require('express-form');
-
-const field = form.field;
-
-module.exports = form(
-  field('createGroupForm[userGroupName]', 'Group name').trim().required(),
-);

+ 0 - 8
packages/app/src/server/form/index.js

@@ -1,8 +0,0 @@
-module.exports = {
-  login: require('./login'),
-  register: require('./register'),
-  invited: require('./invited'),
-  admin: {
-    userGroupCreate: require('./admin/userGroupCreate'),
-  },
-};

+ 0 - 9
packages/app/src/server/form/invited.js

@@ -1,9 +0,0 @@
-const form = require('express-form');
-
-const field = form.field;
-
-module.exports = form(
-  field('invitedForm.username').required().is(/^[\da-zA-Z\-_.]+$/),
-  field('invitedForm.name').required(),
-  field('invitedForm.password').required().is(/^[\x20-\x7F]*$/).minLength(6),
-);

+ 0 - 8
packages/app/src/server/form/login.js

@@ -1,8 +0,0 @@
-const form = require('express-form');
-
-const field = form.field;
-
-module.exports = form(
-  field('loginForm.username').required(),
-  field('loginForm.password').required(),
-);

+ 0 - 11
packages/app/src/server/form/register.js

@@ -1,11 +0,0 @@
-const form = require('express-form');
-
-const field = form.field;
-
-module.exports = form(
-  field('registerForm.username').required().is(/^[\da-zA-Z\-_.]+$/),
-  field('registerForm.name').required(),
-  field('registerForm.email').required(),
-  field('registerForm.password').required().is(/^[\x20-\x7F]*$/).minLength(6),
-  field('registerForm[app:globalLang]'),
-);

+ 85 - 0
packages/app/src/server/middlewares/login-form-validator.ts

@@ -0,0 +1,85 @@
+import { body, validationResult } from 'express-validator';
+
+// form rules
+export const inviteRules = () => {
+  return [
+    body('invitedForm.username')
+      .matches(/^[\da-zA-Z\-_.]+$/)
+      .withMessage('Username has invalid characters')
+      .not()
+      .isEmpty()
+      .withMessage('Username field is required'),
+    body('invitedForm.name').not().isEmpty().withMessage('Name field is required'),
+    body('invitedForm.password')
+      .matches(/^[\x20-\x7F]*$/)
+      .withMessage('Password has invalid character')
+      .isLength({ min: 6 })
+      .withMessage('Password minimum character should be more than 6 characters')
+      .not()
+      .isEmpty()
+      .withMessage('Password field is required'),
+  ];
+};
+
+// validation action
+export const inviteValidation = (req, res, next) => {
+  const form = req.body;
+
+  const errors = validationResult(req);
+  if (errors.isEmpty()) {
+    Object.assign(form, { isValid: true });
+    req.form = form;
+    return next();
+  }
+
+  const extractedErrors: string[] = [];
+  errors.array().map(err => extractedErrors.push(err.msg));
+
+  req.flash('errorMessages', extractedErrors);
+
+  Object.assign(form, { isValid: false });
+  req.form = form;
+
+  return next();
+};
+
+// form rules
+export const loginRules = () => {
+  return [
+    body('loginForm.username')
+      .matches(/^[\da-zA-Z\-_.@]+$/)
+      .withMessage('Username has invalid characters')
+      .not()
+      .isEmpty()
+      .withMessage('Username field is required'),
+    body('loginForm.password')
+      .matches(/^[\x20-\x7F]*$/)
+      .withMessage('Password has invalid character')
+      .isLength({ min: 6 })
+      .withMessage('Password minimum character should be more than 6 characters')
+      .not()
+      .isEmpty()
+      .withMessage('Password field is required'),
+  ];
+};
+
+// validation action
+export const loginValidation = (req, res, next) => {
+  const form = req.body;
+
+  const errors = validationResult(req);
+  if (errors.isEmpty()) {
+    Object.assign(form, { isValid: true });
+    req.form = form;
+    return next();
+  }
+
+  const extractedErrors: string[] = [];
+  errors.array().map(err => extractedErrors.push(err.msg));
+
+  req.flash('errorMessages', extractedErrors);
+  Object.assign(form, { isValid: false });
+  req.form = form;
+
+  return next();
+};

+ 51 - 0
packages/app/src/server/middlewares/register-form-validator.ts

@@ -0,0 +1,51 @@
+import { body, validationResult } from 'express-validator';
+
+// form rules
+export const registerRules = () => {
+  return [
+    body('registerForm.username')
+      .matches(/^[\da-zA-Z\-_.]+$/)
+      .withMessage('Username has invalid characters')
+      .not()
+      .isEmpty()
+      .withMessage('Username field is required'),
+    body('registerForm.name').not().isEmpty().withMessage('Name field is required'),
+    body('registerForm.email')
+      .isEmail()
+      .withMessage('Email format is invalid.')
+      .exists()
+      .withMessage('Email field is required.'),
+    body('registerForm.password')
+      .matches(/^[\x20-\x7F]*$/)
+      .withMessage('Password has invalid character')
+      .isLength({ min: 6 })
+      .withMessage('Password minimum character should be more than 6 characters')
+      .not()
+      .isEmpty()
+      .withMessage('Password field is required'),
+    body('registerForm[app:globalLang]'),
+  ];
+};
+
+// validation action
+export const registerValidation = (req, res, next) => {
+  const form = req.body;
+
+  const errors = validationResult(req);
+  if (errors.isEmpty()) {
+    Object.assign(form, { isValid: true });
+    req.form = form;
+    return next();
+  }
+
+  const extractedErrors: string[] = [];
+  errors.array().map(err => extractedErrors.push(err.msg));
+
+  Object.assign(form, {
+    isValid: false,
+    errors: extractedErrors,
+  });
+  req.form = form;
+
+  return next();
+};

+ 8 - 6
packages/app/src/server/routes/index.js

@@ -3,6 +3,9 @@ import express from 'express';
 import injectResetOrderByTokenMiddleware from '../middlewares/inject-reset-order-by-token-middleware';
 import injectUserRegistrationOrderByTokenMiddleware from '../middlewares/inject-user-registration-order-by-token-middleware';
 
+import * as loginFormValidator from '../middlewares/login-form-validator';
+import * as registerFormValidator from '../middlewares/register-form-validator';
+
 import * as forgotPassword from './forgot-password';
 import * as allInAppNotifications from './all-in-app-notifications';
 import * as userActivation from './user-activation';
@@ -33,7 +36,6 @@ module.exports = function(crowi, app) {
   const injectUserUISettings = require('../middlewares/inject-user-ui-settings-to-localvars')();
 
   const uploads = multer({ dest: `${crowi.tmpDir}uploads` });
-  const form = require('../form');
   const page = require('./page')(crowi, app);
   const login = require('./login')(crowi, app);
   const loginPassport = require('./login-passport')(crowi, app);
@@ -60,10 +62,10 @@ module.exports = function(crowi, app) {
   app.get('/login/error/:reason'      , applicationInstalled, login.error);
   app.get('/login'                    , applicationInstalled, login.preLogin, login.login);
   app.get('/login/invited'            , applicationInstalled, login.invited);
-  app.post('/login/activateInvited'   , applicationInstalled, form.invited                         , csrf, login.invited);
-  app.post('/login'                   , apiLimiter, applicationInstalled, form.login                           , csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
+  app.post('/login/activateInvited'   , apiLimiter , applicationInstalled, loginFormValidator.inviteRules(), loginFormValidator.inviteValidation, csrf, login.invited);
+  app.post('/login'                   , apiLimiter , applicationInstalled, loginFormValidator.loginRules(), loginFormValidator.loginValidation, csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
 
-  app.post('/register'                , applicationInstalled, form.register                        , csrf, login.register);
+  app.post('/register'                , apiLimiter , applicationInstalled, registerFormValidator.registerRules(), registerFormValidator.registerValidation, csrf, login.register);
   app.get('/register'                 , applicationInstalled, login.preLogin, login.register);
   app.get('/logout'                   , applicationInstalled, logout.logout);
 
@@ -74,7 +76,7 @@ module.exports = function(crowi, app) {
   if (!isInstalled) {
     const installer = require('./installer')(crowi);
     app.get('/installer'              , applicationNotInstalled , installer.index);
-    app.post('/installer'             , applicationNotInstalled , form.register , csrf, installer.install);
+    app.post('/installer'             , apiLimiter , applicationNotInstalled , registerFormValidator.registerRules(), registerFormValidator.registerValidation, csrf, installer.install);
     return;
   }
 
@@ -91,7 +93,7 @@ module.exports = function(crowi, app) {
   app.get('/passport/oidc/callback'               , loginPassport.loginPassportOidcCallback     , loginPassport.loginFailure);
   app.post('/passport/saml/callback'              , loginPassport.loginPassportSamlCallback     , loginPassport.loginFailure);
 
-  app.post('/_api/login/testLdap'    , loginRequiredStrictly , form.login , loginPassport.testLdapCredentials);
+  app.post('/_api/login/testLdap'    , apiLimiter , loginRequiredStrictly , loginFormValidator.loginRules() , loginFormValidator.loginValidation , loginPassport.testLdapCredentials);
 
   // security admin
   app.get('/admin/security'          , loginRequiredStrictly , adminRequired , admin.security.index);

+ 11 - 0
packages/app/src/server/views/invited.html

@@ -35,6 +35,17 @@
       <h1>GROWI</h1>
 
       <div id="login-form-errors">
+        {% set errorMessages = req.flash('errorMessages') %}
+        {% if errorMessages.length > 0 %}
+        <div class="alert alert-danger">
+          <ul class="mb-0">
+          {% for error in errorMessages %}
+            <li>{{ error }}</li>
+          {% endfor %}
+          </ul>
+        </div>
+        {% endif %}
+
         {% set message = req.flash('warningMessage') %}
         {% if message.length %}
         <div class="alert alert-danger">

+ 11 - 0
packages/app/src/server/views/login.html

@@ -85,6 +85,17 @@
             {% endfor %}
             {% endif %}
 
+            {% set errorMessages = req.flash('errorMessages') %}
+            {% if errorMessages.length > 0 %}
+            <div class="alert alert-danger">
+              <ul class="mb-0">
+              {% for error in errorMessages %}
+                <li>{{ error }}</li>
+              {% endfor %}
+              </ul>
+            </div>
+            {% endif %}
+
             {% if req.form.errors.length > 0 %}
             <div class="alert alert-danger">
               <ul class="mb-0">

+ 1 - 17
yarn.lock

@@ -4191,7 +4191,7 @@ async-retry@^1.3.3:
   dependencies:
     retry "0.13.1"
 
-async@0.9.x, async@^0.9.0:
+async@0.9.x:
   version "0.9.2"
   resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
 
@@ -8448,14 +8448,6 @@ express-bunyan-logger@^1.3.3:
     useragent "^2.2.1"
     uuid "^3.1.0"
 
-express-form@~0.12.0:
-  version "0.12.6"
-  resolved "https://registry.yarnpkg.com/express-form/-/express-form-0.12.6.tgz#0fb1049abecba747dbfd2e8e1b1a5a20395715ac"
-  dependencies:
-    async "^0.9.0"
-    object-additions "^0.5.1"
-    validator "^2.1.0"
-
 express-mongo-sanitize@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/express-mongo-sanitize/-/express-mongo-sanitize-2.1.0.tgz#a8c647787c25ded6e97b5e864d113e7687c5d471"
@@ -14638,10 +14630,6 @@ oauth@0.9.x:
   resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
   integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
 
-object-additions@^0.5.1:
-  version "0.5.1"
-  resolved "https://registry.yarnpkg.com/object-additions/-/object-additions-0.5.1.tgz#ac624e0995e696c94cc69b41f316462b16a3bda4"
-
 object-assign@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
@@ -21105,10 +21093,6 @@ validator@^11.0.0:
   resolved "https://registry.yarnpkg.com/validator/-/validator-11.1.0.tgz#ac18cac42e0aa5902b603d7a5d9b7827e2346ac4"
   integrity sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==
 
-validator@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/validator/-/validator-2.1.0.tgz#63276570def208adcf1c032c1f4e6a17d2bd8d8b"
-
 variable-diff@1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/variable-diff/-/variable-diff-1.1.0.tgz#d2bd5c66db76c13879d96e6a306edc989df978da"