openmrs/openmrs-contrib-id

View on GitHub
app/routes/auth/login.js

Summary

Maintainability
C
1 day
Test Coverage
'use strict';
/**
 * This is the login logic for Dashboard
 */
const url = require('url');
const path = require('path');
const async = require('async');
const _ = require('lodash');


const common = require('../../common');
const conf = require('../../conf');
const verification = require('../../email-verification');
const validate = require('../../validate');
const mid = require('../../express-middleware');
const utils = require('../../utils');

const log = require('log4js').addLogger('express');

const User = require('../../models/user');

exports = module.exports = app => {


  app.get('/login', mid.forceLogout,
    (req, res, next) => {
      res.render('views/login');
    }
  );

  app.post('/login', mid.stripNewlines, (req, res, next) => {
    const username = req.body.loginusername || '';
    const password = req.body.loginpassword || '';
    const redirect = req.body.destination || '/';

    const checkInput = callback => {
      if (utils.isUsernameValid(username)) {
        return callback(null, {
          username: username
        });
      }
      if (utils.isEmailValid(username)) {
        return callback(null, {
          email: username
        });
      }
      const invalid = 'Please use a valid username or email to sign in';
      return callback({
        loginFail: invalid
      });
    };

    const findUser = (input, callback) => {
      const commonCallback = (err, user) => {
        if (err) {
          return callback(err);
        }
        if (_.isEmpty(user)) {
          return callback({
            loginFail: 'This user does not exist'
          });
        }
        return callback(null, user);
      };
      if (input.username) {
        return User.findByUsername(input.username, commonCallback);
      }
      if (input.email) {
        return User.findByEmail(input.email, commonCallback);
      }
      // should never got here
      return callback(new Error('Weird control flow'));
    };

    const checkLocked = (user, callback) => {
      if (user.locked) {
        return callback({
          loginFail: 'You must verify your email address before logging in. ' +
            'Check your email for verification instructions.'
        });
      }
      return callback(null, user);
    };

    const checkPassword = (user, callback) => {
      if (_.isEmpty(user.password)) {
        return callback({
          loginFail: 'Your password should be reset first'
        });
      }
      if (!utils.checkSSHA(password, user.password)) {
        return callback({
          loginFail: 'Wrong password'
        });
      }
      return callback(null, user);
    };

    async.waterfall([
        checkInput,
        findUser,
        checkLocked,
        checkPassword,
      ],
      (err, user) => {
        if (err) {
          if (_.isEmpty(err.loginFail)) {
            log.debug('login error');
            return next(err);
          }
          log.info(`authentication failed for "${username}" (${err.loginFail})`);
          req.flash('error', err.loginFail);

          _.merge(res.locals, {
            fail: {
              loginusername: false,
              loginpassword: true
            },
            values: {
              loginusername: username,
              loginpassword: password
            }
          });
          if (req.body.destination) { // redirect to the destination login page
            const dest = url.resolve(conf.site.url, `/login?destination=${encodeURIComponent(req.body.destination)}`);

            return res.redirect(dest);
          }
          // redirect to generic login page
          return res.redirect(url.resolve(conf.site.url, '/login'));
        }

        // no error
        log.info(`${username}: authenticated`);
        req.session.user = user;
        log.debug(`user ${username} stored in session`);

        res.redirect(url.resolve(conf.site.url, decodeURIComponent(redirect)));
      });
  });


};