login.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. // disable all of linting
  2. // because this file is a deprecated legacy of Crowi
  3. /* eslint-disable */
  4. module.exports = function(crowi, app) {
  5. const debug = require('debug')('growi:routes:login');
  6. const logger = require('@alias/logger')('growi:routes:login');
  7. const path = require('path');
  8. const async = require('async');
  9. const config = crowi.getConfig();
  10. const mailer = crowi.getMailer();
  11. const User = crowi.model('User');
  12. const Config = crowi.model('Config');
  13. const actions = {};
  14. const clearGoogleSession = function(req) {
  15. req.session.googleAuthCode = req.session.googleId = req.session.googleEmail = req.session.googleName = req.session.googleImage = null;
  16. };
  17. const loginSuccess = function(req, res, userData) {
  18. req.user = req.session.user = userData;
  19. // update lastLoginAt
  20. userData.updateLastLoginAt(new Date(), (err, uData) => {
  21. if (err) {
  22. logger.error(`updateLastLoginAt dumps error: ${err}`);
  23. }
  24. });
  25. if (!userData.password) {
  26. return res.redirect('/me/password');
  27. }
  28. clearGoogleSession(req);
  29. const jumpTo = req.session.jumpTo;
  30. if (jumpTo) {
  31. req.session.jumpTo = null;
  32. return res.redirect(jumpTo);
  33. }
  34. return res.redirect('/');
  35. };
  36. const loginFailure = function(req, res) {
  37. req.flash('warningMessage', 'Sign in failure.');
  38. return res.redirect('/login');
  39. };
  40. actions.googleCallback = function(req, res) {
  41. const nextAction = req.session.googleCallbackAction || '/login';
  42. debug('googleCallback.nextAction', nextAction);
  43. req.session.googleAuthCode = req.query.code || '';
  44. debug('google auth code', req.query.code);
  45. return res.redirect(nextAction);
  46. };
  47. actions.error = function(req, res) {
  48. const reason = req.params.reason;
  49. let reasonMessage = '';
  50. if (reason === 'suspended') {
  51. reasonMessage = 'This account is suspended.';
  52. }
  53. else if (reason === 'registered') {
  54. reasonMessage = 'Wait for approved by administrators.';
  55. }
  56. return res.render('login/error', {
  57. reason,
  58. reasonMessage,
  59. });
  60. };
  61. actions.login = function(req, res) {
  62. const loginForm = req.body.loginForm;
  63. if (req.method == 'POST' && req.form.isValid) {
  64. const username = loginForm.username;
  65. const password = loginForm.password;
  66. // find user
  67. User.findUserByUsernameOrEmail(username, password, (err, user) => {
  68. if (err) { return loginFailure(req, res) }
  69. // check existence and password
  70. if (!user || !user.isPasswordValid(password)) {
  71. return loginFailure(req, res);
  72. }
  73. return loginSuccess(req, res, user);
  74. });
  75. }
  76. else { // method GET
  77. if (req.form) {
  78. debug(req.form.errors);
  79. }
  80. return res.render('login', {
  81. });
  82. }
  83. };
  84. actions.loginGoogle = function(req, res) {
  85. const googleAuth = require('../util/googleAuth')(crowi);
  86. const code = req.session.googleAuthCode || null;
  87. if (!code) {
  88. googleAuth.createAuthUrl(req, (err, redirectUrl) => {
  89. if (err) {
  90. // TODO
  91. }
  92. req.session.googleCallbackAction = '/login/google';
  93. return res.redirect(redirectUrl);
  94. });
  95. }
  96. else {
  97. googleAuth.handleCallback(req, (err, tokenInfo) => {
  98. debug('handleCallback', err, tokenInfo);
  99. if (err) {
  100. return loginFailure(req, res);
  101. }
  102. const googleId = tokenInfo.user_id;
  103. User.findUserByGoogleId(googleId, (err, userData) => {
  104. debug('findUserByGoogleId', err, userData);
  105. if (!userData) {
  106. clearGoogleSession(req);
  107. return loginFailure(req, res);
  108. }
  109. return loginSuccess(req, res, userData);
  110. });
  111. });
  112. }
  113. };
  114. actions.register = function(req, res) {
  115. const googleAuth = require('../util/googleAuth')(crowi);
  116. // ログイン済みならさようなら
  117. if (req.user) {
  118. return res.redirect('/');
  119. }
  120. // config で closed ならさよなら
  121. if (config.crowi['security:registrationMode'] == Config.SECURITY_REGISTRATION_MODE_CLOSED) {
  122. return res.redirect('/');
  123. }
  124. if (req.method == 'POST' && req.form.isValid) {
  125. const registerForm = req.form.registerForm || {};
  126. const name = registerForm.name;
  127. const username = registerForm.username;
  128. const email = registerForm.email;
  129. const password = registerForm.password;
  130. var googleId = registerForm.googleId || null;
  131. var googleImage = registerForm.googleImage || null;
  132. // email と username の unique チェックする
  133. User.isRegisterable(email, username, (isRegisterable, errOn) => {
  134. let isError = false;
  135. if (!User.isEmailValid(email)) {
  136. isError = true;
  137. req.flash('registerWarningMessage', 'This email address could not be used. (Make sure the allowed email address)');
  138. }
  139. if (!isRegisterable) {
  140. if (!errOn.username) {
  141. isError = true;
  142. req.flash('registerWarningMessage', 'This User ID is not available.');
  143. }
  144. if (!errOn.email) {
  145. isError = true;
  146. req.flash('registerWarningMessage', 'This email address is already registered.');
  147. }
  148. }
  149. if (isError) {
  150. debug('isError user register error', errOn);
  151. return res.redirect('/register');
  152. }
  153. User.createUserByEmailAndPassword(name, username, email, password, undefined, (err, userData) => {
  154. if (err) {
  155. if (err.name === 'UserUpperLimitException') {
  156. req.flash('registerWarningMessage', 'Can not register more than the maximum number of users.');
  157. }
  158. else {
  159. req.flash('registerWarningMessage', 'Failed to register.');
  160. }
  161. return res.redirect('/register');
  162. }
  163. // 作成後、承認が必要なモードなら、管理者に通知する
  164. const appTitle = Config.appTitle(config);
  165. if (config.crowi['security:registrationMode'] === Config.SECURITY_REGISTRATION_MODE_RESTRICTED) {
  166. // TODO send mail
  167. User.findAdmins((err, admins) => {
  168. async.each(
  169. admins,
  170. (adminUser, next) => {
  171. mailer.send({
  172. to: adminUser.email,
  173. subject: `[${appTitle}:admin] A New User Created and Waiting for Activation`,
  174. template: path.join(crowi.localeDir, 'en-US/admin/userWaitingActivation.txt'),
  175. vars: {
  176. createdUser: userData,
  177. adminUser,
  178. url: crowi.configManager.getSiteUrl(),
  179. appTitle,
  180. },
  181. },
  182. (err, s) => {
  183. debug('completed to send email: ', err, s);
  184. next();
  185. });
  186. },
  187. (err) => {
  188. debug('Sending invitation email completed.', err);
  189. },
  190. );
  191. });
  192. }
  193. if (googleId) {
  194. userData.updateGoogleId(googleId, (err, userData) => {
  195. if (err) { // TODO
  196. }
  197. return loginSuccess(req, res, userData);
  198. });
  199. }
  200. else {
  201. // add a flash message to inform the user that processing was successful -- 2017.09.23 Yuki Takei
  202. // cz. loginSuccess method doesn't work on it's own when using passport
  203. // because `req.login()` prepared by passport is not called.
  204. req.flash('successMessage', `The user '${userData.username}' is successfully created.`);
  205. return loginSuccess(req, res, userData);
  206. }
  207. });
  208. });
  209. }
  210. else { // method GET of form is not valid
  211. debug('session is', req.session);
  212. const isRegistering = true;
  213. // google callback を受ける可能性もある
  214. const code = req.session.googleAuthCode || null;
  215. var googleId = req.session.googleId || null;
  216. let googleEmail = req.session.googleEmail || null;
  217. let googleName = req.session.googleName || null;
  218. var googleImage = req.session.googleImage || null;
  219. debug('register. if code', code);
  220. // callback 経由で reigster にアクセスしてきた時最初だけこの if に入る
  221. // code から email などを取得したらそれを session にいれて code は消去
  222. if (code) {
  223. googleAuth.handleCallback(req, (err, tokenInfo) => {
  224. debug('tokenInfo on register GET', tokenInfo);
  225. req.session.googleAuthCode = null;
  226. if (err) {
  227. req.flash('registerWarningMessage', 'Error on connectiong Google');
  228. return res.redirect('/login?register=1'); // TODO Handling
  229. }
  230. req.session.googleId = googleId = tokenInfo.user_id;
  231. req.session.googleEmail = googleEmail = tokenInfo.email;
  232. req.session.googleName = googleName = tokenInfo.name;
  233. req.session.googleImage = googleImage = tokenInfo.picture;
  234. if (!User.isEmailValid(googleEmail)) {
  235. req.flash('registerWarningMessage', 'このメールアドレスのGoogleアカウントはコネクトできません。');
  236. return res.redirect('/login?register=1');
  237. }
  238. return res.render('login', {
  239. isRegistering, googleId, googleEmail, googleName, googleImage,
  240. });
  241. });
  242. }
  243. else {
  244. return res.render('login', {
  245. isRegistering, googleId, googleEmail, googleName, googleImage,
  246. });
  247. }
  248. }
  249. };
  250. actions.registerGoogle = function(req, res) {
  251. const googleAuth = require('../util/googleAuth')(crowi);
  252. googleAuth.createAuthUrl(req, (err, redirectUrl) => {
  253. if (err) {
  254. // TODO
  255. }
  256. req.session.googleCallbackAction = '/register';
  257. return res.redirect(redirectUrl);
  258. });
  259. };
  260. actions.invited = async function(req, res) {
  261. if (!req.user) {
  262. return res.redirect('/login');
  263. }
  264. if (req.method == 'POST' && req.form.isValid) {
  265. const user = req.user;
  266. const invitedForm = req.form.invitedForm || {};
  267. const username = invitedForm.username;
  268. const name = invitedForm.name;
  269. const password = invitedForm.password;
  270. // check user upper limit
  271. const isUserCountExceedsUpperLimit = await User.isUserCountExceedsUpperLimit();
  272. if (isUserCountExceedsUpperLimit) {
  273. req.flash('warningMessage', 'ユーザーが上限に達したためアクティベートできません。');
  274. return res.redirect('/invited');
  275. }
  276. const creatable = await User.isRegisterableUsername(username);
  277. if (creatable) {
  278. try {
  279. await user.activateInvitedUser(username, name, password);
  280. return res.redirect('/');
  281. }
  282. catch (err) {
  283. req.flash('warningMessage', 'アクティベートに失敗しました。');
  284. return res.render('invited');
  285. }
  286. }
  287. else {
  288. req.flash('warningMessage', '利用できないユーザーIDです。');
  289. debug('username', username);
  290. return res.render('invited');
  291. }
  292. }
  293. else {
  294. return res.render('invited', {
  295. });
  296. }
  297. };
  298. actions.updateInvitedUser = function(req, res) {
  299. return res.redirect('/');
  300. };
  301. return actions;
  302. };