login.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import loggerFactory from '~/utils/logger';
  2. // disable all of linting
  3. // because this file is a deprecated legacy of Crowi
  4. /* eslint-disable */
  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 { configManager, appService, aclService, mailService } = crowi;
  11. const actions = {};
  12. const loginSuccess = function(req, res, userData) {
  13. // transforming attributes
  14. // see User model
  15. req.user = req.session.user = userData.toObject();
  16. // update lastLoginAt
  17. userData.updateLastLoginAt(new Date(), (err, uData) => {
  18. if (err) {
  19. logger.error(`updateLastLoginAt dumps error: ${err}`);
  20. }
  21. });
  22. if (!userData.password) {
  23. return res.redirect('/me/password');
  24. }
  25. const { redirectTo } = req.session;
  26. // remove session.redirectTo
  27. delete req.session.redirectTo;
  28. return res.safeRedirect(redirectTo);
  29. };
  30. actions.error = function(req, res) {
  31. const reason = req.params.reason;
  32. let reasonMessage = '';
  33. if (reason === 'suspended') {
  34. reasonMessage = 'This account is suspended.';
  35. }
  36. else if (reason === 'registered') {
  37. reasonMessage = 'Wait for approved by administrators.';
  38. }
  39. return res.render('login/error', {
  40. reason,
  41. reasonMessage,
  42. });
  43. };
  44. actions.preLogin = function(req, res, next) {
  45. // user has already logged in
  46. const { user } = req;
  47. if (user != null && user.status === User.STATUS_ACTIVE) {
  48. const { redirectTo } = req.session;
  49. // remove session.redirectTo
  50. delete req.session.redirectTo;
  51. return res.safeRedirect(redirectTo);
  52. }
  53. // set referer to 'redirectTo'
  54. if (req.session.redirectTo == null && req.headers.referer != null) {
  55. req.session.redirectTo = req.headers.referer;
  56. }
  57. next();
  58. }
  59. actions.login = function(req, res) {
  60. if (req.form) {
  61. debug(req.form.errors);
  62. }
  63. return res.render('login', {});
  64. };
  65. actions.register = function(req, res) {
  66. if (req.user != null) {
  67. return res.redirect('/');
  68. }
  69. // config で closed ならさよなら
  70. if (configManager.getConfig('crowi', 'security:registrationMode') == aclService.labels.SECURITY_REGISTRATION_MODE_CLOSED) {
  71. return res.redirect('/');
  72. }
  73. if (req.method == 'POST' && req.form.isValid) {
  74. const registerForm = req.form.registerForm || {};
  75. const name = registerForm.name;
  76. const username = registerForm.username;
  77. const email = registerForm.email;
  78. const password = registerForm.password;
  79. // email と username の unique チェックする
  80. User.isRegisterable(email, username, (isRegisterable, errOn) => {
  81. let isError = false;
  82. if (!User.isEmailValid(email)) {
  83. isError = true;
  84. req.flash('registerWarningMessage', req.t('message.email_address_could_not_be_used'));
  85. }
  86. if (!isRegisterable) {
  87. if (!errOn.username) {
  88. isError = true;
  89. req.flash('registerWarningMessage', req.t('message.user_id_is_not_available'));
  90. }
  91. if (!errOn.email) {
  92. isError = true;
  93. req.flash('registerWarningMessage', req.t('message.email_address_is_already_registered'));
  94. }
  95. }
  96. if (isError) {
  97. debug('isError user register error', errOn);
  98. return res.redirect('/register');
  99. }
  100. User.createUserByEmailAndPassword(name, username, email, password, undefined, async(err, userData) => {
  101. if (err) {
  102. if (err.name === 'UserUpperLimitException') {
  103. req.flash('registerWarningMessage', req.t('message.can_not_register_maximum_number_of_users'));
  104. }
  105. else {
  106. req.flash('registerWarningMessage', req.t('message.failed_to_register'));
  107. }
  108. return res.redirect('/register');
  109. }
  110. if (configManager.getConfig('crowi', 'security:registrationMode') !== aclService.labels.SECURITY_REGISTRATION_MODE_RESTRICTED) {
  111. // send mail asynchronous
  112. sendEmailToAllAdmins(userData);
  113. }
  114. // add a flash message to inform the user that processing was successful -- 2017.09.23 Yuki Takei
  115. // cz. loginSuccess method doesn't work on it's own when using passport
  116. // because `req.login()` prepared by passport is not called.
  117. req.flash('successMessage', req.t('message.successfully_created',{ username: userData.username }));
  118. return loginSuccess(req, res, userData);
  119. });
  120. });
  121. }
  122. else { // method GET of form is not valid
  123. debug('session is', req.session);
  124. const isRegistering = true;
  125. return res.render('login', { isRegistering });
  126. }
  127. };
  128. async function sendEmailToAllAdmins(userData) {
  129. // send mails to all admin users (derived from crowi) -- 2020.06.18 Yuki Takei
  130. const admins = await User.findAdmins();
  131. const appTitle = appService.getAppTitle();
  132. const promises = admins.map((admin) => {
  133. return mailService.send({
  134. to: admin.email,
  135. subject: `[${appTitle}:admin] A New User Created and Waiting for Activation`,
  136. template: path.join(crowi.localeDir, 'en_US/admin/userWaitingActivation.txt'),
  137. vars: {
  138. createdUser: userData,
  139. admin,
  140. url: appService.getSiteUrl(),
  141. appTitle,
  142. },
  143. });
  144. })
  145. const results = await Promise.allSettled(promises);
  146. results
  147. .filter(result => result.status === 'rejected')
  148. .forEach(result => logger.error(result.reason));
  149. }
  150. actions.invited = async function(req, res) {
  151. if (!req.user) {
  152. return res.redirect('/login');
  153. }
  154. if (req.method == 'POST' && req.form.isValid) {
  155. const user = req.user;
  156. const invitedForm = req.form.invitedForm || {};
  157. const username = invitedForm.username;
  158. const name = invitedForm.name;
  159. const password = invitedForm.password;
  160. // check user upper limit
  161. const isUserCountExceedsUpperLimit = await User.isUserCountExceedsUpperLimit();
  162. if (isUserCountExceedsUpperLimit) {
  163. req.flash('warningMessage', req.t('message.can_not_activate_maximum_number_of_users'));
  164. return res.redirect('/invited');
  165. }
  166. const creatable = await User.isRegisterableUsername(username);
  167. if (creatable) {
  168. try {
  169. await user.activateInvitedUser(username, name, password);
  170. return res.redirect('/');
  171. }
  172. catch (err) {
  173. req.flash('warningMessage', req.t('message.failed_to_activate'));
  174. return res.render('invited');
  175. }
  176. }
  177. else {
  178. req.flash('warningMessage', req.t('message.unable_to_use_this_user'));
  179. debug('username', username);
  180. return res.render('invited');
  181. }
  182. }
  183. else {
  184. return res.render('invited', {
  185. });
  186. }
  187. };
  188. actions.updateInvitedUser = function(req, res) {
  189. return res.redirect('/');
  190. };
  191. return actions;
  192. };