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

Merge pull request #4038 from weseek/imprv/gw6802-generate-unique-token

Imprv/gw6802 generate unique token
Yuki Takei 4 лет назад
Родитель
Сommit
52fce7780b

+ 1 - 0
src/server/models/index.js

@@ -19,4 +19,5 @@ module.exports = {
   GlobalNotificationSlackSetting: require('./GlobalNotificationSetting/GlobalNotificationSlackSetting'),
   ShareLink: require('./share-link'),
   SlackAppIntegration: require('./slack-app-integration'),
+  PasswordResetOrder: require('./password-reset-order'),
 };

+ 23 - 4
src/server/models/password-reset-order.js

@@ -1,5 +1,6 @@
 const mongoose = require('mongoose');
 const uniqueValidator = require('mongoose-unique-validator');
+const crypto = require('crypto');
 
 const ObjectId = mongoose.Schema.Types.ObjectId;
 
@@ -8,18 +9,36 @@ const schema = new mongoose.Schema({
   email: { type: String, required: true },
   relatedUser: { type: ObjectId, ref: 'User' },
   createdAt: { type: Date, default: Date.now, required: true },
-  expiredAt: { type: Date, default: Date.now + 600000, required: true },
+  expiredAt: { type: Date, default: Date.now() + 600000, required: true },
 });
 schema.plugin(uniqueValidator);
 
 class PasswordResetOrder {
 
   static generateOneTimeToken() {
-    // TODO: generate unique token by GW-6802
+    const buf = crypto.randomBytes(256);
+    const token = buf.toString('base64');
+
+    return token;
+  }
+
+  static async createPasswordResetOrder(email) {
+    let token;
+    let duplicateToken;
+
+    do {
+      token = this.generateOneTimeToken();
+      // eslint-disable-next-line no-await-in-loop
+      duplicateToken = await this.findOne({ token });
+    } while (duplicateToken != null);
+
+    const passwordResetOrderData = await this.create({ token, email });
+
+    return passwordResetOrderData;
   }
 
-  static isExpired() {
-    return this.expiredAt.getTime() < new Date().getTime();
+  isExpired() {
+    return this.expiredAt.getTime() < Date.now();
   }
 
 }

+ 17 - 1
src/server/routes/forgot-password.js

@@ -1,4 +1,8 @@
+const logger = require('@alias/logger')('growi:routes:forgot-password');
+const ApiResponse = require('../util/apiResponse');
+
 module.exports = function(crowi, app) {
+  const PasswordResetOrder = crowi.model('PasswordResetOrder');
   const { /* appService, */ mailService, configManager } = crowi;
   const path = require('path');
   const actions = {};
@@ -17,7 +21,7 @@ module.exports = function(crowi, app) {
   async function sendPasswordResetEmail(i18n) {
 
     return mailService.send({
-      to: 'hoge@gmail.com',
+      to: 'hoge@example.com',
       subject: 'forgotPasswordMailTest',
       template: path.join(crowi.localeDir, `${i18n}/notifications/passwordReset.txt`),
       // TODO: need to set appropriate values by GW-6828
@@ -30,6 +34,18 @@ module.exports = function(crowi, app) {
   }
 
   api.post = async function(req, res) {
+    // TODO: using email getting by password reset request form by GW-6828
+    const email = 'foo@example.com';
+    try {
+      const passwordResetOrderData = await PasswordResetOrder.createPasswordResetOrder(email);
+      res.send(ApiResponse.success({ passwordResetOrderData }));
+    }
+    catch (err) {
+      const msg = 'Error occurred during password reset request procedure';
+      logger.error(err);
+      return res.json(ApiResponse.error(msg));
+    }
+
     const grobalLang = configManager.getConfig('crowi', 'app:globalLang');
     const i18n = req.language || grobalLang;