AuthenticationManager = require ("./AuthenticationManager") LoginRateLimiter = require("../Security/LoginRateLimiter") UserGetter = require "../User/UserGetter" UserUpdater = require "../User/UserUpdater" Metrics = require('../../infrastructure/Metrics') logger = require("logger-sharelatex") querystring = require('querystring') Url = require("url") module.exports = AuthenticationController = login: (req, res, next = (error) ->) -> email = req.body?.email?.toLowerCase() password = req.body?.password redir = Url.parse(req.body?.redir or "/project").path LoginRateLimiter.processLoginRequest email, (err, isAllowed)-> if !isAllowed logger.log email:email, "too many login requests" res.statusCode = 429 return res.send message: text: 'This account has had too many login requests,
please wait 2 minutes before trying to log in again', type: 'error' AuthenticationManager.authenticate email: email, password, (error, user) -> return next(error) if error? if user? LoginRateLimiter.recordSuccessfulLogin email AuthenticationController._recordSuccessfulLogin user._id AuthenticationController._establishUserSession req, user, (error) -> return next(error) if error? logger.log email: email, user_id: user._id.toString(), "successful log in" res.send redir: redir else AuthenticationController._recordFailedLogin() logger.log email: email, "failed log in" res.send message: text: 'Your email or password were incorrect. Please try again', type: 'error' getAuthToken: (req, res, next = (error) ->) -> AuthenticationController.getLoggedInUserId req, (error, user_id) -> return next(error) if error? AuthenticationManager.getAuthToken user_id, (error, auth_token) -> return next(error) if error? res.send(auth_token) getLoggedInUserId: (req, callback = (error, user_id) ->) -> if req?.session?.user?._id? callback null, req.session.user._id.toString() else e = new Error("user is not on req session") callback e getLoggedInUser: (req, options = {allow_auth_token: false}, callback = (error, user) ->) -> if req.session?.user?._id? query = req.session.user._id else if req.query?.auth_token? and options.allow_auth_token query = { auth_token: req.query.auth_token } else return callback null, null UserGetter.getUser query, callback requireLogin: (options = {allow_auth_token: false, load_from_db: false}) -> doRequest = (req, res, next = (error) ->) -> load_from_db = options.load_from_db if req.query?.auth_token? and options.allow_auth_token load_from_db = true if load_from_db AuthenticationController.getLoggedInUser req, { allow_auth_token: options.allow_auth_token }, (error, user) -> return next(error) if error? return AuthenticationController._redirectToRegisterPage(req, res) if !user? req.user = user return next() else if !req.session.user? return AuthenticationController._redirectToRegisterPage(req, res) else req.user = req.session.user return next() return doRequest _redirectToRegisterPage: (req, res) -> logger.log url: req.url, "user not logged in so redirecting to register page" req.query.redir = req.path url = "/register?#{querystring.stringify(req.query)}" res.redirect url Metrics.inc "security.login-redirect" _recordSuccessfulLogin: (user_id, callback = (error) ->) -> UserUpdater.updateUser user_id.toString(), { $set: { "lastLoggedIn": new Date() }, $inc: { "loginCount": 1 } }, (error) -> callback(error) if error? Metrics.inc "user.login.success" callback() _recordFailedLogin: (callback = (error) ->) -> Metrics.inc "user.login.failed" callback() _establishUserSession: (req, user, callback = (error) ->) -> lightUser = _id: user._id first_name: user.first_name last_name: user.last_name isAdmin: user.isAdmin email: user.email referal_id: user.referal_id req.session.user = lightUser req.session.justLoggedIn = true req.session.save callback