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

Merge pull request #4131 from weseek/imprv/7091-refactoring-middleware

Imprv/7091 refactoring middleware
cao 4 лет назад
Родитель
Сommit
04ecca4429

+ 24 - 0
packages/app/src/server/middlewares/inject-reset-order-by-token-middleware.js

@@ -0,0 +1,24 @@
+const createError = require('http-errors');
+
+module.exports = (crowi, app) => {
+  const PasswordResetOrder = crowi.model('PasswordResetOrder');
+
+  return async(req, res, next) => {
+    const token = req.params.token || req.body.token;
+
+    if (token == null) {
+      req.error = { key: 'token-not-found', message: 'Token not found' };
+    }
+
+    const passwordResetOrder = await PasswordResetOrder.findOne({ token });
+
+    // check if the token is valid
+    if (passwordResetOrder == null || passwordResetOrder.isExpired() || passwordResetOrder.isRevoked) {
+      req.error = { key: 'password-reset-order-is-not-appropriate', message: 'passwordResetOrder is null or expired or revoked' };
+    }
+
+    req.passwordResetOrder = passwordResetOrder;
+
+    return next();
+  };
+};

+ 0 - 23
packages/app/src/server/middlewares/password-reset.js

@@ -1,23 +0,0 @@
-module.exports = (crowi, app) => {
-  const PasswordResetOrder = crowi.model('PasswordResetOrder');
-
-  // need refuctoring with http-error by GW-7091
-
-  return async(req, res, next) => {
-    const { token } = req.params;
-
-    if (token == null) {
-      return res.redirect('/login');
-    }
-
-    const passwordResetOrder = await PasswordResetOrder.findOne({ token });
-    // check the oneTimeToken is valid
-    if (passwordResetOrder == null || passwordResetOrder.isExpired()) {
-      return res.redirect('/forgot-password/error/password-reset-order');
-    }
-
-    req.DataFromPasswordResetOrderMiddleware = passwordResetOrder;
-
-    return next();
-  };
-};

+ 11 - 5
packages/app/src/server/routes/apiv3/forgot-password.js

@@ -16,6 +16,7 @@ module.exports = (crowi) => {
   const path = require('path');
   const csrf = require('../../middlewares/csrf')(crowi);
   const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
+  const injectResetOrderByTokenMiddleware = require('../../middlewares/inject-reset-order-by-token-middleware')(crowi);
 
   const validator = {
     password: [
@@ -77,13 +78,17 @@ module.exports = (crowi) => {
     }
   });
 
-  router.put('/', apiLimiter, csrf, validator.password, apiV3FormValidator, async(req, res) => {
-    const grobalLang = configManager.getConfig('crowi', 'app:globalLang');
-    const i18n = req.language || grobalLang;
-    const { token, newPassword } = req.body;
+  router.put('/', apiLimiter, csrf, injectResetOrderByTokenMiddleware, validator.password, apiV3FormValidator, async(req, res) => {
+
+    if (req.error != null) {
+      return res.apiv3Err(req.error.message);
+    }
 
-    const passwordResetOrder = await PasswordResetOrder.findOne({ token });
+    const { passwordResetOrder } = req;
     const { email } = passwordResetOrder;
+    const grobalLang = configManager.getConfig('crowi', 'app:globalLang');
+    const i18n = req.language || grobalLang;
+    const { newPassword } = req.body;
 
     const user = await User.findOne({ email });
 
@@ -95,6 +100,7 @@ module.exports = (crowi) => {
     try {
       const userData = await user.updatePassword(newPassword);
       const serializedUserData = serializeUserSecurely(userData);
+      passwordResetOrder.revokeOneTimeToken();
       await sendPasswordResetEmail('passwordResetSuccessful', i18n, email);
       return res.apiv3({ userData: serializedUserData });
     }

+ 5 - 9
packages/app/src/server/routes/forgot-password.js

@@ -8,17 +8,13 @@ module.exports = function(crowi, app) {
   };
 
   actions.resetPassword = async function(req, res) {
+    const { error, passwordResetOrder } = req;
 
-    const { email } = req.DataFromPasswordResetOrderMiddleware;
-    return res.render('reset-password', { email });
-  };
-
-  actions.error = function(req, res) {
-    const { reason } = req.params;
-
-    if (reason === 'password-reset-order') {
-      return res.render('forgot-password/error', { reason });
+    if (error != null) {
+      return res.render('forgot-password/error', { key: error.key });
     }
+
+    return res.render('reset-password', { email: passwordResetOrder.email });
   };
 
   return actions;

+ 2 - 3
packages/app/src/server/routes/index.js

@@ -21,7 +21,7 @@ module.exports = function(crowi, app) {
   const adminRequired = require('../middlewares/admin-required')(crowi);
   const certifySharedFile = require('../middlewares/certify-shared-file')(crowi);
   const csrf = require('../middlewares/csrf')(crowi);
-  const passwordReset = require('../middlewares/password-reset')(crowi);
+  const injectResetOrderByTokenMiddleware = require('../middlewares/inject-reset-order-by-token-middleware')(crowi);
 
   const uploads = multer({ dest: `${crowi.tmpDir}uploads` });
   const form = require('../form');
@@ -186,8 +186,7 @@ module.exports = function(crowi, app) {
   app.post('/_api/hackmd.saveOnHackmd'   , accessTokenParser , loginRequiredStrictly , csrf, hackmd.validateForApi, hackmd.saveOnHackmd);
 
   app.get('/forgot-password', forgotPassword.forgotPassword);
-  app.get('/forgot-password/:token'      ,apiLimiter, passwordReset, forgotPassword.resetPassword);
-  app.get('/forgot-password/error/:reason'      , applicationInstalled, forgotPassword.error);
+  app.get('/forgot-password/:token'      ,apiLimiter, injectResetOrderByTokenMiddleware, forgotPassword.resetPassword);
 
   app.get('/share/:linkId', page.showSharedPage);
 

+ 1 - 1
packages/app/src/server/views/forgot-password/error.html

@@ -33,7 +33,7 @@
             <div class="text-center">
               <h1><i class="icon-lock-open large"></i></h1>
               <h2 class="text-center">{{ t('forgot_password.reset_password') }}</h2>
-                {% if reason === 'password-reset-order' %}
+                {% if key === 'password-reset-order-is-not-appropriate' %}
                 <div>
                   <div class="alert alert-warning mb-3">
                     <h2>{{ t('forgot_password.incorrect_token_or_expired_url') }}</h2>