itizawa пре 6 година
родитељ
комит
0943484bf0

+ 1 - 0
package.json

@@ -130,6 +130,7 @@
     "swig-templates": "^2.0.2",
     "swig-templates": "^2.0.2",
     "uglifycss": "^0.0.29",
     "uglifycss": "^0.0.29",
     "url-join": "^4.0.0",
     "url-join": "^4.0.0",
+    "validator": "^11.1.0",
     "xss": "^1.0.6"
     "xss": "^1.0.6"
   },
   },
   "devDependencies": {
   "devDependencies": {

+ 8 - 1
src/client/js/components/Admin/Users/UserInviteModal.jsx

@@ -32,10 +32,17 @@ class UserInviteModal extends React.Component {
   async handleSubmit() {
   async handleSubmit() {
     const { appContainer } = this.props;
     const { appContainer } = this.props;
 
 
+    const array = this.state.emailInputValue.split('\n');
+    const emailList = array.filter((element) => { return element.match(/.+@.+\..+/) });
+    const shapedEmailList = emailList.map((email) => { return email.trim() });
+
     try {
     try {
       // TODO GW-230 use emailList client side
       // TODO GW-230 use emailList client side
       // eslint-disable-next-line no-unused-vars
       // eslint-disable-next-line no-unused-vars
-      const emailList = await appContainer.apiPost('/admin/user/invite', { emailInputValue: this.state.emailInputValue, sendEmail: this.state.sendEmail });
+      const emailList = await appContainer.apiv3.post('/users/invite', {
+        shapedEmailList,
+        sendEmail: this.state.sendEmail,
+      });
       this.props.onToggleModal();
       this.props.onToggleModal();
       toastSuccess('Inviting user success');
       toastSuccess('Inviting user success');
     }
     }

+ 2 - 0
src/server/routes/apiv3/index.js

@@ -13,6 +13,8 @@ module.exports = (crowi) => {
 
 
   router.use('/healthcheck', require('./healthcheck')(crowi));
   router.use('/healthcheck', require('./healthcheck')(crowi));
 
 
+  router.use('/users', require('./users')(crowi));
+
   router.use('/user-groups', require('./user-group')(crowi));
   router.use('/user-groups', require('./user-group')(crowi));
 
 
   router.use('/user-group-relations', require('./user-group-relation')(crowi));
   router.use('/user-group-relations', require('./user-group-relation')(crowi));

+ 51 - 0
src/server/routes/apiv3/users.js

@@ -0,0 +1,51 @@
+const loggerFactory = require('@alias/logger');
+
+const logger = loggerFactory('growi:routes:apiv3:user-group'); // eslint-disable-line no-unused-vars
+
+const express = require('express');
+
+const router = express.Router();
+
+const { body } = require('express-validator/check');
+
+const { isEmail } = require('validator');
+
+const validator = {};
+
+module.exports = (crowi) => {
+  const {
+    ErrorV3,
+    User,
+  } = crowi.models;
+
+  const { ApiV3FormValidator } = crowi.middlewares;
+
+  const {
+    loginRequired,
+    adminRequired,
+    csrfVerify: csrf,
+  } = require('../../util/middlewares')(crowi);
+
+  validator.inviteEmail = [
+    // isEmail prevents line breaks, so use isString
+    body('shapedEmailList').custom((value) => {
+      const array = value.filter((value) => { return isEmail(value) });
+      if (array.length === 0) {
+        throw new Error('At least one valid email address is required');
+      }
+      return array;
+    }),
+  ];
+
+  router.post('/invite', loginRequired(), adminRequired, csrf, validator.inviteEmail, ApiV3FormValidator, async(req, res) => {
+    try {
+      const emailList = await User.createUsersByInvitation(req.body.shapedEmailList, req.body.sendEmail);
+      return res.apiv3({ emailList });
+    }
+    catch (err) {
+      return res.apiv3Err(new ErrorV3(err));
+    }
+  });
+
+  return router;
+};

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

@@ -118,7 +118,6 @@ module.exports = function(crowi, app) {
   app.post('/admin/global-notification/:id/remove', loginRequired() , adminRequired , admin.globalNotification.remove);
   app.post('/admin/global-notification/:id/remove', loginRequired() , adminRequired , admin.globalNotification.remove);
 
 
   app.get('/admin/users'                , loginRequired() , adminRequired , admin.user.index);
   app.get('/admin/users'                , loginRequired() , adminRequired , admin.user.index);
-  app.post('/_api/admin/user/invite'         , form.admin.userInvite ,  loginRequired() , adminRequired , csrf, admin.user.api.validators.inviteEmail, admin.user.invite);
   app.post('/admin/user/:id/makeAdmin'  , loginRequired() , adminRequired , csrf, admin.user.makeAdmin);
   app.post('/admin/user/:id/makeAdmin'  , loginRequired() , adminRequired , csrf, admin.user.makeAdmin);
   app.post('/admin/user/:id/removeFromAdmin', loginRequired() , adminRequired , admin.user.removeFromAdmin);
   app.post('/admin/user/:id/removeFromAdmin', loginRequired() , adminRequired , admin.user.removeFromAdmin);
   app.post('/admin/user/:id/activate'   , loginRequired() , adminRequired , csrf, admin.user.activate);
   app.post('/admin/user/:id/activate'   , loginRequired() , adminRequired , csrf, admin.user.activate);

+ 1 - 1
yarn.lock

@@ -12266,7 +12266,7 @@ validator@^10.0.0:
   resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228"
   resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228"
   integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==
   integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==
 
 
-validator@^11.0.0:
+validator@^11.0.0, validator@^11.1.0:
   version "11.1.0"
   version "11.1.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==