login.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import { SupportedAction } from '~/interfaces/activity';
  2. import loggerFactory from '~/utils/logger';
  3. // disable all of linting
  4. // because this file is a deprecated legacy of Crowi
  5. module.exports = function(crowi, app) {
  6. const debug = require('debug')('growi:routes:login');
  7. const logger = loggerFactory('growi:routes:login');
  8. const path = require('path');
  9. const User = crowi.model('User');
  10. const {
  11. configManager, appService, aclService, mailService,
  12. } = crowi;
  13. const activityEvent = crowi.event('activity');
  14. const actions = {};
  15. const registerSuccessHandler = function(req, res, userData) {
  16. req.login(userData, (err) => {
  17. if (err) {
  18. logger.debug(err);
  19. }
  20. else {
  21. // update lastLoginAt
  22. userData.updateLastLoginAt(new Date(), (err) => {
  23. if (err) {
  24. logger.error(`updateLastLoginAt dumps error: ${err}`);
  25. }
  26. });
  27. }
  28. // userData.password cann't be empty but, prepare redirect because password property in User Model is optional
  29. // https://github.com/weseek/growi/pull/6670
  30. const redirectTo = userData.password ? req.session.redirectTo : '/me#password';
  31. // remove session.redirectTo
  32. delete req.session.redirectTo;
  33. const parameters = { action: SupportedAction.ACTION_USER_REGISTRATION_SUCCESS };
  34. activityEvent.emit('update', res.locals.activity._id, parameters);
  35. return res.apiv3({ redirectTo });
  36. });
  37. };
  38. async function sendEmailToAllAdmins(userData) {
  39. // send mails to all admin users (derived from crowi) -- 2020.06.18 Yuki Takei
  40. const admins = await User.findAdmins();
  41. const appTitle = appService.getAppTitle();
  42. const promises = admins.map((admin) => {
  43. return mailService.send({
  44. to: admin.email,
  45. subject: `[${appTitle}:admin] A New User Created and Waiting for Activation`,
  46. template: path.join(crowi.localeDir, 'en_US/admin/userWaitingActivation.txt'),
  47. vars: {
  48. createdUser: userData,
  49. admin,
  50. url: appService.getSiteUrl(),
  51. appTitle,
  52. },
  53. });
  54. });
  55. const results = await Promise.allSettled(promises);
  56. results
  57. .filter(result => result.status === 'rejected')
  58. .forEach(result => logger.error(result.reason));
  59. }
  60. actions.error = function(req, res) {
  61. const reason = req.params.reason;
  62. let reasonMessage = '';
  63. if (reason === 'suspended') {
  64. reasonMessage = 'This account is suspended.';
  65. }
  66. else if (reason === 'registered') {
  67. reasonMessage = 'Wait for approved by administrators.';
  68. }
  69. return res.render('login/error', {
  70. reason,
  71. reasonMessage,
  72. });
  73. };
  74. actions.preLogin = function(req, res, next) {
  75. // user has already logged in
  76. // const { user } = req;
  77. // if (user != null && user.status === User.STATUS_ACTIVE) {
  78. // const { redirectTo } = req.session;
  79. // // remove session.redirectTo
  80. // delete req.session.redirectTo;
  81. // return res.safeRedirect(redirectTo);
  82. // }
  83. // // set referer to 'redirectTo'
  84. // if (req.session.redirectTo == null && req.headers.referer != null) {
  85. // req.session.redirectTo = req.headers.referer;
  86. // }
  87. next();
  88. };
  89. actions.register = function(req, res) {
  90. if (req.user != null) {
  91. return res.apiv3Err('user_already_logged_in', 403);
  92. }
  93. // config で closed ならさよなら
  94. if (configManager.getConfig('crowi', 'security:registrationMode') === aclService.labels.SECURITY_REGISTRATION_MODE_CLOSED) {
  95. return res.apiv3Err('registration_closed', 403);
  96. }
  97. if (!req.form.isValid) {
  98. const errors = req.form.errors;
  99. return res.apiv3Err(errors, 400);
  100. }
  101. const registerForm = req.form.registerForm || {};
  102. const name = registerForm.name;
  103. const username = registerForm.username;
  104. const email = registerForm.email;
  105. const password = registerForm.password;
  106. // email と username の unique チェックする
  107. User.isRegisterable(email, username, (isRegisterable, errOn) => {
  108. const errors = [];
  109. if (!User.isEmailValid(email)) {
  110. errors.push('email_address_could_not_be_used');
  111. }
  112. if (!isRegisterable) {
  113. if (!errOn.username) {
  114. errors.push('user_id_is_not_available');
  115. }
  116. if (!errOn.email) {
  117. errors.push('email_address_is_already_registered');
  118. }
  119. }
  120. if (errors.length > 0) {
  121. debug('isError user register error', errOn);
  122. return res.apiv3Err(errors, 400);
  123. }
  124. User.createUserByEmailAndPassword(name, username, email, password, undefined, async(err, userData) => {
  125. if (err) {
  126. const errors = [];
  127. if (err.name === 'UserUpperLimitException') {
  128. errors.push('can_not_register_maximum_number_of_users');
  129. }
  130. else {
  131. errors.push('failed_to_register');
  132. }
  133. return res.apiv3Err(errors, 405);
  134. }
  135. if (configManager.getConfig('crowi', 'security:registrationMode') !== aclService.labels.SECURITY_REGISTRATION_MODE_RESTRICTED) {
  136. // send mail asynchronous
  137. sendEmailToAllAdmins(userData);
  138. }
  139. return registerSuccessHandler(req, res, userData);
  140. });
  141. });
  142. };
  143. actions.invited = async function(req, res) {
  144. if (!req.user) {
  145. return res.redirect('/login');
  146. }
  147. if (req.method === 'POST' && req.form.isValid) {
  148. const user = req.user;
  149. const invitedForm = req.form.invitedForm || {};
  150. const username = invitedForm.username;
  151. const name = invitedForm.name;
  152. const password = invitedForm.password;
  153. // check user upper limit
  154. const isUserCountExceedsUpperLimit = await User.isUserCountExceedsUpperLimit();
  155. if (isUserCountExceedsUpperLimit) {
  156. req.flash('warningMessage', req.t('message.can_not_activate_maximum_number_of_users'));
  157. return res.redirect('/invited');
  158. }
  159. const creatable = await User.isRegisterableUsername(username);
  160. if (creatable) {
  161. try {
  162. await user.activateInvitedUser(username, name, password);
  163. return res.redirect('/');
  164. }
  165. catch (err) {
  166. req.flash('warningMessage', req.t('message.failed_to_activate'));
  167. return res.render('invited');
  168. }
  169. }
  170. else {
  171. req.flash('warningMessage', req.t('message.unable_to_use_this_user'));
  172. debug('username', username);
  173. return res.render('invited');
  174. }
  175. }
  176. else {
  177. return res.render('invited');
  178. }
  179. };
  180. actions.updateInvitedUser = function(req, res) {
  181. return res.redirect('/');
  182. };
  183. return actions;
  184. };