login.js 5.8 KB

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