Преглед изворни кода

Merge pull request #3928 from weseek/imprv/GW-6474-6431-update-endpoints

Imprv/gw 6474 6431 6532 update endpoints
Yuki Takei пре 4 година
родитељ
комит
dbb2c008cd
6 измењених фајлова са 77 додато и 57 уклоњено
  1. 1 0
      CHANGES.md
  2. 1 1
      package.json
  3. 1 2
      src/client/js/services/AdminUsersContainer.js
  4. 11 45
      src/server/models/user.js
  5. 59 6
      src/server/routes/apiv3/users.js
  6. 4 3
      yarn.lock

+ 1 - 0
CHANGES.md

@@ -11,6 +11,7 @@
     * stream-to-promise
     * validator
     * ws
+    * nodemailer
 
 ## v4.2.20
 

+ 1 - 1
package.json

@@ -133,7 +133,7 @@
     "mongoose-unique-validator": "^2.0.3",
     "multer": "~1.4.0",
     "multer-autoreap": "^1.0.3",
-    "nodemailer": "^6.0.0",
+    "nodemailer": "^6.6.2",
     "nodemailer-ses-transport": "~1.5.0",
     "npm-run-all": "^4.1.2",
     "openid-client": "=2.5.0",

+ 1 - 2
src/client/js/services/AdminUsersContainer.js

@@ -164,8 +164,7 @@ export default class AdminUsersContainer extends Container {
       sendEmail,
     });
     await this.retrieveUsersByPagingNum(this.state.activePage);
-    const { invitedUserList } = response.data;
-    return invitedUserList;
+    return response.data;
   }
 
   /**

+ 11 - 45
src/server/models/user.js

@@ -4,7 +4,6 @@ const debug = require('debug')('growi:models:user');
 const logger = require('@alias/logger')('growi:models:user');
 const mongoose = require('mongoose');
 const mongoosePaginate = require('mongoose-paginate-v2');
-const path = require('path');
 const uniqueValidator = require('mongoose-unique-validator');
 const md5 = require('md5');
 
@@ -573,57 +572,24 @@ module.exports = function(crowi) {
     const creationEmailList = emailList.filter((email) => { return existingEmailList.indexOf(email) === -1 });
 
     const createdUserList = [];
-    await Promise.all(creationEmailList.map(async(email) => {
-      const createdEmail = await this.createUserByEmail(email);
-      createdUserList.push(createdEmail);
-    }));
-
-    return { existingEmailList, createdUserList };
-  };
-
-  userSchema.statics.sendEmailbyUserList = async function(userList) {
-    const { appService, mailService } = crowi;
-    const appTitle = appService.getAppTitle();
-
-    await Promise.all(userList.map(async(user) => {
-      if (user.password == null) {
-        return;
-      }
+    const failedToCreateUserEmailList = [];
 
+    for (const email of creationEmailList) {
       try {
-        return mailService.send({
-          to: user.email,
-          subject: `Invitation to ${appTitle}`,
-          template: path.join(crowi.localeDir, 'en_US/admin/userInvitation.txt'),
-          vars: {
-            email: user.email,
-            password: user.password,
-            url: crowi.appService.getSiteUrl(),
-            appTitle,
-          },
-        });
+        // eslint-disable-next-line no-await-in-loop
+        const createdUser = await this.createUserByEmail(email);
+        createdUserList.push(createdUser);
       }
       catch (err) {
-        return debug('fail to send email: ', err);
+        logger.error(err);
+        failedToCreateUserEmailList.push({
+          email,
+          reason: err.message,
+        });
       }
-    }));
-
-  };
-
-  userSchema.statics.createUsersByInvitation = async function(emailList, toSendEmail) {
-    validateCrowi();
-
-    if (!Array.isArray(emailList)) {
-      debug('emailList is not array');
-    }
-
-    const afterWorkEmailList = await this.createUsersByEmailList(emailList);
-
-    if (toSendEmail) {
-      await this.sendEmailbyUserList(afterWorkEmailList.createdUserList);
     }
 
-    return afterWorkEmailList;
+    return { createdUserList, existingEmailList, failedToCreateUserEmailList };
   };
 
   userSchema.statics.createUserByEmailAndPasswordAndStatus = async function(name, username, email, password, lang, status, callback) {

+ 59 - 6
src/server/routes/apiv3/users.js

@@ -6,6 +6,8 @@ const express = require('express');
 
 const router = express.Router();
 
+const path = require('path');
+
 const { body, query } = require('express-validator');
 const { isEmail } = require('validator');
 const { serializeUserSecurely } = require('../../models/serializers/user-serializer');
@@ -116,6 +118,38 @@ module.exports = (crowi) => {
     query('limit').if(value => value != null).isInt({ max: 300 }).withMessage('You should set less than 300 or not to set limit.'),
   ];
 
+  const sendEmailByUserList = async(userList) => {
+    const { appService, mailService } = crowi;
+    const appTitle = appService.getAppTitle();
+    const failedToSendEmailList = [];
+
+    for (const user of userList) {
+      try {
+        // eslint-disable-next-line no-await-in-loop
+        await mailService.send({
+          to: user.email,
+          subject: `Invitation to ${appTitle}`,
+          template: path.join(crowi.localeDir, 'en_US/admin/userInvitation.txt'),
+          vars: {
+            email: user.email,
+            password: user.password,
+            url: crowi.appService.getSiteUrl(),
+            appTitle,
+          },
+        });
+      }
+      catch (err) {
+        logger.error(err);
+        failedToSendEmailList.push({
+          email: user.email,
+          reason: err.message,
+        });
+      }
+    }
+
+    return { failedToSendEmailList };
+  };
+
   /**
    * @swagger
    *
@@ -355,16 +389,35 @@ module.exports = (crowi) => {
    *                    existingEmailList:
    *                      type: object
    *                      description: Users email that already exists
+   *                    failedEmailList:
+   *                      type: object
+   *                      description: Users email that failed to create or send email
    */
   router.post('/invite', loginRequiredStrictly, adminRequired, csrf, validator.inviteEmail, apiV3FormValidator, async(req, res) => {
-    try {
-      const invitedUserList = await User.createUsersByInvitation(req.body.shapedEmailList, req.body.sendEmail);
-      return res.apiv3({ invitedUserList }, 201);
+
+    // Delete duplicate email addresses
+    const emailList = Array.from(new Set(req.body.shapedEmailList));
+    const failedEmailList = [];
+
+    // Create users
+    const createUser = await User.createUsersByEmailList(emailList);
+    if (createUser.failedToCreateUserEmailList.length > 0) {
+      failedEmailList.push(createUser.failedToCreateUserEmailList);
     }
-    catch (err) {
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(err));
+
+    // Send email
+    if (req.body.sendEmail) {
+      const sendEmail = await sendEmailByUserList(createUser.createdUserList);
+      if (sendEmail.failedToSendEmailList.length > 0) {
+        failedEmailList.push(sendEmail.failedToSendEmailList);
+      }
     }
+
+    return res.apiv3({
+      createdUserList: createUser.createdUserList,
+      existingEmailList: createUser.existingEmailList,
+      failedEmailList,
+    }, 201);
   });
 
   /**

+ 4 - 3
yarn.lock

@@ -10404,9 +10404,10 @@ nodemailer-ses-transport@~1.5.0:
   dependencies:
     aws-sdk "^2.2.36"
 
-nodemailer@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.0.0.tgz#d9761128771739dc87c1fdd747f569b7f135cb02"
+nodemailer@^6.6.2:
+  version "6.6.2"
+  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.6.2.tgz#e184c9ed5bee245a3e0bcabc7255866385757114"
+  integrity sha512-YSzu7TLbI+bsjCis/TZlAXBoM4y93HhlIgo0P5oiA2ua9Z4k+E2Fod//ybIzdJxOlXGRcHIh/WaeCBehvxZb/Q==
 
 noop6@^1.0.1:
   version "1.0.8"