Răsfoiți Sursa

- Implement action return on login form
- Implement middleware action on register form
- Implement middleware action on invited form
- Adjust login client error handler
- Adjust register error handler
- Adjust invited error handler

LuqmanHakim-Grune 4 ani în urmă
părinte
comite
9de596aff8

+ 23 - 12
packages/app/src/server/middlewares/login-form-validator.ts

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

+ 13 - 6
packages/app/src/server/middlewares/register-form-validator.ts

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

+ 5 - 5
packages/app/src/server/routes/index.js

@@ -62,10 +62,10 @@ module.exports = function(crowi, app) {
   app.get('/login/error/:reason'      , applicationInstalled, login.error);
   app.get('/login/error/:reason'      , applicationInstalled, login.error);
   app.get('/login'                    , applicationInstalled, login.preLogin, login.login);
   app.get('/login'                    , applicationInstalled, login.preLogin, login.login);
   app.get('/login/invited'            , applicationInstalled, login.invited);
   app.get('/login/invited'            , applicationInstalled, login.invited);
-  app.post('/login/activateInvited'   , applicationInstalled, loginFormValidator.inviteRules(), loginFormValidator.inviteValidation(), csrf, login.invited);
-  app.post('/login'                   , applicationInstalled, loginFormValidator.loginRules(), loginFormValidator.loginValidation(), csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
+  app.post('/login/activateInvited'   , applicationInstalled, loginFormValidator.inviteRules(), loginFormValidator.inviteValidation, csrf, login.invited);
+  app.post('/login'                   , applicationInstalled, loginFormValidator.loginRules(), loginFormValidator.loginValidation, csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
 
 
-  app.post('/register'                , applicationInstalled, registerFormValidator.registerRules(), registerFormValidator.registerValidation(), csrf, login.register);
+  app.post('/register'                , applicationInstalled, registerFormValidator.registerRules(), registerFormValidator.registerValidation, csrf, login.register);
   app.get('/register'                 , applicationInstalled, login.preLogin, login.register);
   app.get('/register'                 , applicationInstalled, login.preLogin, login.register);
   app.get('/logout'                   , applicationInstalled, logout.logout);
   app.get('/logout'                   , applicationInstalled, logout.logout);
 
 
@@ -76,7 +76,7 @@ module.exports = function(crowi, app) {
   if (!isInstalled) {
   if (!isInstalled) {
     const installer = require('./installer')(crowi);
     const installer = require('./installer')(crowi);
     app.get('/installer'              , applicationNotInstalled , installer.index);
     app.get('/installer'              , applicationNotInstalled , installer.index);
-    app.post('/installer'             , applicationNotInstalled , registerFormValidator.registerRules(), registerFormValidator.registerValidation(), csrf, installer.install);
+    app.post('/installer'             , applicationNotInstalled , registerFormValidator.registerRules(), registerFormValidator.registerValidation, csrf, installer.install);
     return;
     return;
   }
   }
 
 
@@ -93,7 +93,7 @@ module.exports = function(crowi, app) {
   app.get('/passport/oidc/callback'               , loginPassport.loginPassportOidcCallback     , loginPassport.loginFailure);
   app.get('/passport/oidc/callback'               , loginPassport.loginPassportOidcCallback     , loginPassport.loginFailure);
   app.post('/passport/saml/callback'              , loginPassport.loginPassportSamlCallback     , loginPassport.loginFailure);
   app.post('/passport/saml/callback'              , loginPassport.loginPassportSamlCallback     , loginPassport.loginFailure);
 
 
-  app.post('/_api/login/testLdap'    , loginRequiredStrictly , loginFormValidator.loginRules() , loginFormValidator.loginValidation() , loginPassport.testLdapCredentials);
+  app.post('/_api/login/testLdap'    , loginRequiredStrictly , loginFormValidator.loginRules() , loginFormValidator.loginValidation , loginPassport.testLdapCredentials);
 
 
   // security admin
   // security admin
   app.get('/admin/security'          , loginRequiredStrictly , adminRequired , admin.security.index);
   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>
       <h1>GROWI</h1>
 
 
       <div id="login-form-errors">
       <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') %}
         {% set message = req.flash('warningMessage') %}
         {% if message.length %}
         {% if message.length %}
         <div class="alert alert-danger">
         <div class="alert alert-danger">

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

@@ -85,6 +85,17 @@
             {% endfor %}
             {% endfor %}
             {% endif %}
             {% 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 %}
             {% if req.form.errors.length > 0 %}
             <div class="alert alert-danger">
             <div class="alert alert-danger">
               <ul class="mb-0">
               <ul class="mb-0">

+ 1 - 17
yarn.lock

@@ -3971,7 +3971,7 @@ async-retry@^1.3.3:
   dependencies:
   dependencies:
     retry "0.13.1"
     retry "0.13.1"
 
 
-async@0.9.x, async@^0.9.0:
+async@0.9.x:
   version "0.9.2"
   version "0.9.2"
   resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
   resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
 
 
@@ -7968,14 +7968,6 @@ express-bunyan-logger@^1.3.3:
     useragent "^2.2.1"
     useragent "^2.2.1"
     uuid "^3.1.0"
     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:
 express-mongo-sanitize@^2.1.0:
   version "2.1.0"
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/express-mongo-sanitize/-/express-mongo-sanitize-2.1.0.tgz#a8c647787c25ded6e97b5e864d113e7687c5d471"
   resolved "https://registry.yarnpkg.com/express-mongo-sanitize/-/express-mongo-sanitize-2.1.0.tgz#a8c647787c25ded6e97b5e864d113e7687c5d471"
@@ -13779,10 +13771,6 @@ oauth@0.9.x:
   resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
   resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
   integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
   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:
 object-assign@^3.0.0:
   version "3.0.0"
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
@@ -19892,10 +19880,6 @@ validator@^11.0.0:
   resolved "https://registry.yarnpkg.com/validator/-/validator-11.1.0.tgz#ac18cac42e0aa5902b603d7a5d9b7827e2346ac4"
   resolved "https://registry.yarnpkg.com/validator/-/validator-11.1.0.tgz#ac18cac42e0aa5902b603d7a5d9b7827e2346ac4"
   integrity sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==
   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:
 variable-diff@1.1.0:
   version "1.1.0"
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/variable-diff/-/variable-diff-1.1.0.tgz#d2bd5c66db76c13879d96e6a306edc989df978da"
   resolved "https://registry.yarnpkg.com/variable-diff/-/variable-diff-1.1.0.tgz#d2bd5c66db76c13879d96e6a306edc989df978da"