openmrs/openmrs-contrib-id

View on GitHub
app/routes/signup/index.js

Summary

Maintainability
C
1 day
Test Coverage
'use strict';
/**
 * This file handles requests related with signup operations
 */
const url = require('url');
const path = require('path');
const async = require('async');
const _ = require('lodash');
const log = require('log4js').addLogger('signup');

const conf = require('../../conf');
const mid = require('../../express-middleware');
const verification = require('../../email-verification');
const validate = require('../../validate');
const nav = require('../../user-nav');
const utils = require('../../utils');
const User = require('../../models/user');

const botproof = require('./botproof');
const emailPath = path.resolve(__dirname, '../../../templates/emails');

/*
ROUTES
======
*/

exports = module.exports = app => {


  // get signup from /signup or from / and handle accordingly
  app.get(/^\/signup\/?$|^\/$/i, botproof.generators,
    (req, res, next) => {

      if (req.session.user) {
        return next(); // pass onward if a user is signed in
      }

      // render the page
      res.locals.recaptchaPublic = conf.validation.recaptchaPublic;
      res.render('views/signup');
    });

  // prevent from getting 404'd if a logged-in user hits /signup
  app.get('/signup', mid.forceLogout);

  app.post('/signup', (req, res, next) => {
    return next();
  });

  app.post('/signup', mid.forceLogout, botproof.parsers,
    (req, res, next) => {

      if (!req.xhr) {
        return res.redirect('/');
      }
      let id = req.body.username;
      const first = req.body.firstName;
      const last = req.body.lastName;
      const email = req.body.primaryEmail;
      const pass = req.body.password;
      const confirmpass = req.body.confirmpassword;
      const captchaData = {
        response: req.body['g-recaptcha-response'],
      };

      // only lowercase
      id = id.toLowerCase();

      // perform validation
      const validation = callback => {
        const validators = {
          username: validate.chkUsernameInvalidOrDup.bind(null, id),
          primaryEmail: validate.chkEmailInvalidOrDup.bind(null, email),
          firstName: validate.chkEmpty.bind(null, first),
          lastName: validate.chkEmpty.bind(null, last),
          password: validate.chkLength.bind(null, pass, 8),
          confirmpass: validate.chkDiff.bind(null, pass, confirmpass),
          recaptcha_response_field: validate.chkRecaptcha.bind(null, captchaData),
        };
        validate.perform(validators, (err, failures) => {
          if (err) {
            return callback(err);
          }
          if (_.isEmpty(failures)) {
            return callback();
          }
          res.json({
            fail: failures
          });
        });
      };

      const saveUser = callback => {
        const newUser = new User({
          username: id,
          firstName: first,
          lastName: last,
          createdAt: Date.now(),
          displayName: `${first} ${last}`,
          primaryEmail: email,
          emailList: [email],
          password: pass,
          locked: true,
        });
        newUser.save(callback);
      };

      const sendVerificationEmail = callback => {
        const verificationOptions = {
          addr: email,
          subject: '[OpenMRS] Welcome to the OpenMRS Community',
          templatePath: path.join(emailPath, 'welcome-verify.pug'),
          username: id,
          category: 'signup',
          callback: '/signup',
          locals: {
            displayName: `${first} ${last}`,
            username: id,
          },
          timeout: 0
        };
        log.debug('Sending signup email verification');
        verification.begin(verificationOptions, callback);
      };

      async.series([
          validation,
          saveUser,
          sendVerificationEmail,
        ],
        err => {
          if (err) {
            return next(err);
          }
          res.json({
            success: true
          });
        });
    });

  app.get('/signup/verify', (req, res) => {
    res.render('views/signedup');
  });

  // verification
  app.get('/signup/:id', (req, res, next) => {
    const id = utils.urlDecode64(req.params.id);
    const INVALID_MSG = 'The requested signup verification does not exist, ' +
      'it might have expired.';

    const findUsernameByVerifyID = callback => {
      verification.check(id, (err, valid, locals) => {
        if (err) {
          return callback(err);
        }
        if (!valid) {
          return callback({
            failMessage: INVALID_MSG
          });
        }
        return callback(null, locals.username);
      });
    };

    // clear locked and expiration flag
    const updateUser = (user, callback) => {
      user.locked = false;
      user.createdAt = undefined;
      user.addGroupsAndSave(conf.user.defaultGroups, callback);
    };

    async.waterfall([
        findUsernameByVerifyID,
        User.findByUsername.bind(User),
        updateUser,
      ],
      (err, user) => {
        if (err) {
          if (err.failMessage) {
            req.flash('error', err.failMessage);
            return res.redirect('/');
          }
          return next(err);
        }
        // we don't have to wait clear
        verification.clear(id);
        log.debug(`${user.username}: account enabled`);
        req.flash('success', 'Your account was successfully created. Welcome!');

        req.session.user = user;
        res.redirect('/');
      });
  });

  // AJAX, check whether or not user exists
  app.get('/checkuser/:id', (req, res) => {
    if (!req.xhr) {
      return res.redirect('/');
    }
    const username = req.params.id;
    const isValid = conf.ldap.user.usernameRegex.test(username);

    if (!isValid) {
      return res.json({
        illegal: true
      });
    }

    User.findByUsername(username, function chkUser(err, user) {
      if (err) {
        log.error('error in checkuser');
        log.error(err);
        return;
      }
      if (user) {
        return res.json({
          exists: true
        });
      }
      return res.json({
        exists: false
      });
    });
  });

  app.get('/checkemail/:email', (req, res) => {
    if (!req.xhr) {
      return res.redirect('/');
    }
    validate.chkEmailInvalidOrDup(req.params.email, (err, errState) => {
      if (err) {
        log.error('error in checkemail');
        log.error(err);
        return;
      }
      if (true === errState) {
        return res.json({
          illegal: true
        });
      }
      if (errState) {
        return res.json({
          exists: true
        });
      }
      return res.json({
        exists: false
      });
    });
  });


};