user-activation.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import path from 'path';
  2. import { format, subSeconds } from 'date-fns';
  3. import { body, validationResult } from 'express-validator';
  4. import UserRegistrationOrder from '../models/user-registration-order';
  5. export const form = (req, res): void => {
  6. const { userRegistrationOrder } = req;
  7. return res.render('user-activation', { userRegistrationOrder });
  8. };
  9. async function makeRegistrationEmailToken(email, crowi) {
  10. const {
  11. configManager,
  12. mailService,
  13. localeDir,
  14. appService,
  15. } = crowi;
  16. const grobalLang = configManager.getConfig('crowi', 'app:globalLang');
  17. const i18n = grobalLang;
  18. const appUrl = appService.getSiteUrl();
  19. const userRegistrationOrder = await UserRegistrationOrder.createUserRegistrationOrder(email);
  20. const grwTzoffsetSec = crowi.appService.getTzoffset() * 60;
  21. const expiredAt = subSeconds(userRegistrationOrder.expiredAt, grwTzoffsetSec);
  22. const formattedExpiredAt = format(expiredAt, 'yyyy/MM/dd HH:mm');
  23. const url = new URL(`/user-activation/${userRegistrationOrder.token}`, appUrl);
  24. const oneTimeUrl = url.href;
  25. const txtFileName = 'userActivation';
  26. return mailService.send({
  27. to: email,
  28. subject: '[GROWI] User Activation',
  29. template: path.join(localeDir, `${i18n}/notifications/${txtFileName}.txt`),
  30. vars: {
  31. appTitle: appService.getAppTitle(),
  32. email,
  33. expiredAt: formattedExpiredAt,
  34. url: oneTimeUrl,
  35. },
  36. });
  37. }
  38. export const registerAction = (crowi) => {
  39. const User = crowi.model('User');
  40. return async function(req, res) {
  41. const registerForm = req.body.registerForm || {};
  42. const email = registerForm.email;
  43. const isRegisterableEmail = await User.isRegisterableEmail(email);
  44. if (!isRegisterableEmail) {
  45. req.body.registerForm.email = email;
  46. req.flash('registerWarningMessage', req.t('message.email_address_is_already_registered'));
  47. req.flash('email', email);
  48. return res.redirect('/login#register');
  49. }
  50. makeRegistrationEmailToken(email, crowi);
  51. req.flash('successMessage', req.t('message.successfully_send_email_auth', { email }));
  52. return res.redirect('/login');
  53. };
  54. };
  55. // middleware to handle error
  56. export const tokenErrorHandlerMiddeware = (err, req, res, next) => {
  57. if (err != null) {
  58. req.flash('errorMessage', req.t('message.incorrect_token_or_expired_url'));
  59. return res.redirect('/login#register');
  60. }
  61. next();
  62. };
  63. // validation rules for registration form when email authentication enabled
  64. export const registerRules = () => {
  65. return [
  66. body('registerForm.email')
  67. .isEmail()
  68. .withMessage('Email format is invalid.')
  69. .exists()
  70. .withMessage('Email field is required.'),
  71. ];
  72. };
  73. // middleware to validate complete registration form
  74. export const validateCompleteRegistrationForm = (req, res, next) => {
  75. const errors = validationResult(req);
  76. if (errors.isEmpty()) {
  77. return next();
  78. }
  79. const extractedErrors: string[] = [];
  80. errors.array().map(err => extractedErrors.push(err.msg));
  81. req.flash('errors', extractedErrors);
  82. req.flash('inputs', req.body);
  83. const token = req.body.token;
  84. return res.redirect(`/user-activation/${token}`);
  85. };
  86. // middleware to validate register form if email authentication enabled
  87. export const validateRegisterForm = (req, res, next) => {
  88. const errors = validationResult(req);
  89. if (errors.isEmpty()) {
  90. return next();
  91. }
  92. req.form = { isValid: false };
  93. const extractedErrors: string[] = [];
  94. errors.array().map(err => extractedErrors.push(err.msg));
  95. req.flash('registerWarningMessage', extractedErrors);
  96. res.redirect('back');
  97. };