|
|
@@ -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,40 @@ 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,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ // eslint-disable-next-line no-await-in-loop
|
|
|
+ await User.updateIsInvitationEmailSended(user.user.id);
|
|
|
+ }
|
|
|
+ catch (err) {
|
|
|
+ logger.error(err);
|
|
|
+ failedToSendEmailList.push({
|
|
|
+ email: user.email,
|
|
|
+ reason: err.message,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return { failedToSendEmailList };
|
|
|
+ };
|
|
|
+
|
|
|
/**
|
|
|
* @swagger
|
|
|
*
|
|
|
@@ -355,16 +391,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));
|
|
|
+ let failedEmailList = [];
|
|
|
+
|
|
|
+ // Create users
|
|
|
+ const createUser = await User.createUsersByEmailList(emailList);
|
|
|
+ if (createUser.failedToCreateUserEmailList.length > 0) {
|
|
|
+ failedEmailList = failedEmailList.concat(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 = failedEmailList.concat(sendEmail.failedToSendEmailList);
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ return res.apiv3({
|
|
|
+ createdUserList: createUser.createdUserList,
|
|
|
+ existingEmailList: createUser.existingEmailList,
|
|
|
+ failedEmailList,
|
|
|
+ }, 201);
|
|
|
});
|
|
|
|
|
|
/**
|
|
|
@@ -761,5 +816,55 @@ module.exports = (crowi) => {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+ /**
|
|
|
+ * @swagger
|
|
|
+ *
|
|
|
+ * paths:
|
|
|
+ * /users/send-invitation-email:
|
|
|
+ * put:
|
|
|
+ * tags: [Users]
|
|
|
+ * operationId: sendInvitationEmail
|
|
|
+ * summary: /users/send-invitation-email
|
|
|
+ * description: send invitation email
|
|
|
+ * requestBody:
|
|
|
+ * content:
|
|
|
+ * application/json:
|
|
|
+ * schema:
|
|
|
+ * properties:
|
|
|
+ * id:
|
|
|
+ * type: string
|
|
|
+ * description: user id for send invitation email
|
|
|
+ * responses:
|
|
|
+ * 200:
|
|
|
+ * description: success send invitation email
|
|
|
+ * content:
|
|
|
+ * application/json:
|
|
|
+ * schema:
|
|
|
+ * properties:
|
|
|
+ * failedToSendEmail:
|
|
|
+ * type: object
|
|
|
+ * description: email and reasons for email sending failure
|
|
|
+ */
|
|
|
+ router.put('/send-invitation-email', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
|
|
|
+ const { id } = req.body;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const user = await User.findById(id);
|
|
|
+ const newPassword = await User.resetPasswordByRandomString(id);
|
|
|
+ const userList = [{
|
|
|
+ email: user.email,
|
|
|
+ password: newPassword,
|
|
|
+ user: { id },
|
|
|
+ }];
|
|
|
+ const sendEmail = await sendEmailByUserList(userList);
|
|
|
+ // return null if absent
|
|
|
+ return res.apiv3({ failedToSendEmail: sendEmail.failedToSendEmailList[0] });
|
|
|
+ }
|
|
|
+ catch (err) {
|
|
|
+ logger.error('Error', err);
|
|
|
+ return res.apiv3Err(new ErrorV3(err));
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
return router;
|
|
|
};
|