<commit_before>'use strict';

/**
 * Module dependencies.
 */
var _ = require('lodash'),
    path = require('path'),
    errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
    analyticsHandler = require(path.resolve('./modules/core/server/controllers/analytics.server.controller')),
    emailsHandler = require(path.resolve('./modules/core/server/controllers/emails.server.controller')),
    profileHandler = require(path.resolve('./modules/users/server/controllers/users/users.profile.server.controller')),
    config = require(path.resolve('./config/config')),
    passport = require('passport'),
    nodemailer = require('nodemailer'),
    async = require('async'),
    crypto = require('crypto'),
    mongoose = require('mongoose'),
    User = mongoose.model('User');

// Replace mailer with Stub mailer transporter
// Stub transport does not send anything, it builds the mail stream into a single Buffer and returns
// it with the sendMail callback. This is useful for testing the emails before actually sending anything.
// @link https://github.com/andris9/nodemailer-stub-transport
if (process.env.NODE_ENV === 'test') {
  var stubTransport = require('nodemailer-stub-transport');
  config.mailer.options = stubTransport();
}

/**
 * Signup
 */
exports.signup = function(req, res) {
  async.waterfall([

    // Check if we have the required data before hitting more strict validations at Mongo
    function(done) {

      if(!req.body.firstName || !req.body.lastName || !req.body.username || !req.body.password || !req.body.email) {
        return res.status(400).send({
          message: 'Please provide required fields.'
        });
      }

      done();
    },

    // Generate random token
    function(done) {
      crypto.randomBytes(20, function(err, buffer) {
        var token = buffer.toString('hex');
        done(err, token);
      });
    },

    // Save user
    function(token, done) {

      // For security measurement we remove the roles from the `req.body` object
      delete req.body.roles;

      // These shouldn't be there neither
      delete req.body.avatarUploaded;
      delete req.body.created;
      delete req.body.updated;

      // Init Variables
      var user = new User(req.body);
      var message = null;

      // Add missing user fields
      user.emailToken = token;
      user.public = false;
      user.provider = 'local';
      user.displayName = user.firstName.trim() + ' ' + user.lastName.trim();
      user.displayUsername = req.body.username;

      // Just to simplify email confirm process later
      // This field is normally needed when changing email after the signup process
      // Since we set user public=false and require initial email confirmation,
      // we'll have to have the email also at emailTemporary field
      // (from where it's then again moved to email field)
      user.emailTemporary = user.email;

      // Then save the user
      // trySave() is a method required by mongoose-beautiful-unique-validation
      // @link https://www.npmjs.com/package/mongoose-beautiful-unique-validation
      user.trySave(function(err) {
        if (!err) {
          // Remove sensitive data before login
          user.password = <PASSWORD>;
          user.salt = <PASSWORD>;
        }

        done(err, user);

      });

    },

    // Prepare HTML email
    function(user, done) {

      var url = (config.https ? 'https' : 'http') + '://' + req.headers.host,
          urlConfirm = url + '/confirm-email/' + user.emailToken + '?signup';

      var renderVars = emailsHandler.addEmailBaseTemplateParams(
        req.headers.host,
        {
          name: user.displayName,
          email: user.email,
          ourMail: config.mailer.from,
          urlConfirmPlainText: urlConfirm,
          urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, {
            source: 'transactional-email',
            medium: 'email',
            campaign: 'confirm-email'
          })
        },
        'confirm-email'
      );

      res.render(path.resolve('./modules/core/server/views/email-templates/signup'), renderVars, function(err, emailHTML) {
        done(err, emailHTML, user, renderVars, url);
      });
    },

    // Prepare TEXT email
    function(emailHTML, user, renderVars, url, done) {
      res.render(path.resolve('./modules/core/server/views/email-templates-text/signup'), renderVars, function(err, emailPlain) {
        done(err, emailHTML, emailPlain, user, url);
      });
    },

    // If valid email, send confirm email using service
    function(emailHTML, emailPlain, user, url, done) {
      var smtpTransport = nodemailer.createTransport(config.mailer.options);
      var mailOptions = {
        to: {
          name: user.displayName,
          address: user.email
        },
        from: 'Trustroots <' + config.mailer.from + '>',
        subject: 'Confirm Email',
        html: emailHTML,
        text: emailPlain
      };
      smtpTransport.sendMail(mailOptions, function(err) {
        smtpTransport.close(); // close the connection pool
        done(err, user);
      });
    },

    // Login
    function(user, done) {
      req.login(user, function(err) {
        if (!err) {
          // Remove sensitive data befor sending user
          user = profileHandler.sanitizeProfile(user);
          res.json(user);
        }
        done(err);
      });
    }

  ], function(err) {
    if (err) {
      console.log(err);
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    }
  });
};


/**
 * Signin after passport authentication
 */
exports.signin = function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err || !user) {
      res.status(400).send(info);
    } else {
      // Remove sensitive data before login
      user.password = <PASSWORD>;
      user.salt = <PASSWORD>;

      req.login(user, function(err) {
        if (err) {
          res.status(400).send(err);
        } else {
          res.json(user);
        }
      });
    }
  })(req, res, next);
};

/**
 * Signout
 */
exports.signout = function(req, res) {
  req.logout();
  res.redirect('/');
};

/**
 * OAuth callback
 */
exports.oauthCallback = function(strategy) {
  return function(req, res, next) {
    passport.authenticate(strategy, function(err, user, redirectURL) {
      if (err || !user) {
        return res.redirect('/signin');
      }
      req.login(user, function(err) {
        if (err) {
          return res.redirect('/signin');
        }
<commit_msg>Fix profile missing memberIds array after sign in<commit_after>'use strict';

/**
 * Module dependencies.
 */
var _ = require('lodash'),
    path = require('path'),
    errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
    analyticsHandler = require(path.resolve('./modules/core/server/controllers/analytics.server.controller')),
    emailsHandler = require(path.resolve('./modules/core/server/controllers/emails.server.controller')),
    profileHandler = require(path.resolve('./modules/users/server/controllers/users/users.profile.server.controller')),
    config = require(path.resolve('./config/config')),
    passport = require('passport'),
    nodemailer = require('nodemailer'),
    async = require('async'),
    crypto = require('crypto'),
    mongoose = require('mongoose'),
    User = mongoose.model('User');

// Replace mailer with Stub mailer transporter
// Stub transport does not send anything, it builds the mail stream into a single Buffer and returns
// it with the sendMail callback. This is useful for testing the emails before actually sending anything.
// @link https://github.com/andris9/nodemailer-stub-transport
if (process.env.NODE_ENV === 'test') {
  var stubTransport = require('nodemailer-stub-transport');
  config.mailer.options = stubTransport();
}

/**
 * Signup
 */
exports.signup = function(req, res) {
  async.waterfall([

    // Check if we have the required data before hitting more strict validations at Mongo
    function(done) {

      if(!req.body.firstName || !req.body.lastName || !req.body.username || !req.body.password || !req.body.email) {
        return res.status(400).send({
          message: 'Please provide required fields.'
        });
      }

      done();
    },

    // Generate random token
    function(done) {
      crypto.randomBytes(20, function(err, buffer) {
        var token = buffer.toString('hex');
        done(err, token);
      });
    },

    // Save user
    function(token, done) {

      // For security measurement we remove the roles from the `req.body` object
      delete req.body.roles;

      // These shouldn't be there neither
      delete req.body.avatarUploaded;
      delete req.body.created;
      delete req.body.updated;

      // Init Variables
      var user = new User(req.body);
      var message = null;

      // Add missing user fields
      user.emailToken = token;
      user.public = false;
      user.provider = 'local';
      user.displayName = user.firstName.trim() + ' ' + user.lastName.trim();
      user.displayUsername = req.body.username;

      // Just to simplify email confirm process later
      // This field is normally needed when changing email after the signup process
      // Since we set user public=false and require initial email confirmation,
      // we'll have to have the email also at emailTemporary field
      // (from where it's then again moved to email field)
      user.emailTemporary = user.email;

      // Then save the user
      // trySave() is a method required by mongoose-beautiful-unique-validation
      // @link https://www.npmjs.com/package/mongoose-beautiful-unique-validation
      user.trySave(function(err) {
        if (!err) {
          // Remove sensitive data before login
          user.password = <PASSWORD>;
          user.salt = <PASSWORD>;
        }

        done(err, user);

      });

    },

    // Prepare HTML email
    function(user, done) {

      var url = (config.https ? 'https' : 'http') + '://' + req.headers.host,
          urlConfirm = url + '/confirm-email/' + user.emailToken + '?signup';

      var renderVars = emailsHandler.addEmailBaseTemplateParams(
        req.headers.host,
        {
          name: user.displayName,
          email: user.email,
          ourMail: config.mailer.from,
          urlConfirmPlainText: urlConfirm,
          urlConfirm: analyticsHandler.appendUTMParams(urlConfirm, {
            source: 'transactional-email',
            medium: 'email',
            campaign: 'confirm-email'
          })
        },
        'confirm-email'
      );

      res.render(path.resolve('./modules/core/server/views/email-templates/signup'), renderVars, function(err, emailHTML) {
        done(err, emailHTML, user, renderVars, url);
      });
    },

    // Prepare TEXT email
    function(emailHTML, user, renderVars, url, done) {
      res.render(path.resolve('./modules/core/server/views/email-templates-text/signup'), renderVars, function(err, emailPlain) {
        done(err, emailHTML, emailPlain, user, url);
      });
    },

    // If valid email, send confirm email using service
    function(emailHTML, emailPlain, user, url, done) {
      var smtpTransport = nodemailer.createTransport(config.mailer.options);
      var mailOptions = {
        to: {
          name: user.displayName,
          address: user.email
        },
        from: 'Trustroots <' + config.mailer.from + '>',
        subject: 'Confirm Email',
        html: emailHTML,
        text: emailPlain
      };
      smtpTransport.sendMail(mailOptions, function(err) {
        smtpTransport.close(); // close the connection pool
        done(err, user);
      });
    },

    // Login
    function(user, done) {
      req.login(user, function(err) {
        if (!err) {
          // Remove sensitive data befor sending user
          user = profileHandler.sanitizeProfile(user);
          res.json(user);
        }
        done(err);
      });
    }

  ], function(err) {
    if (err) {
      console.log(err);
      return res.status(400).send({
        message: errorHandler.getErrorMessage(err)
      });
    }
  });
};


/**
 * Signin after passport authentication
 */
exports.signin = function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err || !user) {
      res.status(400).send(info);
    } else {
      // Remove sensitive data before login
      user.password = <PASSWORD>;
      user.salt = <PASSWORD>;

      req.login(user, function(err) {
        if (err) {
          res.status(400).send(err);
        } else {
          user = profileHandler.sanitizeProfile(user);
          res.json(user);
        }
      });
    }
  })(req, res, next);
};

/**
 * Signout
 */
exports.signout = function(req, res) {
  req.logout();
  res.redirect('/');
};

/**
 * OAuth callback
 */
exports.oauthCallback = function(strategy) {
  return function(req, res, next) {
    passport.authenticate(strategy, function(err, user, redirectURL) {
      if (err || !user) {
        return res.redirect('/signin');
      }
      req.login(user, function(err) {
        if (err) {
          return res.redirect('/signin');
        }

{'fraction_non_alphanumeric': 0.13409210823848647, 'fraction_numerical': 0.0022612497173437854, 'mean_word_length': 2.4444444444444446, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6723701', 'n_tokens_mistral': 3862, 'n_tokens_neox': 3784, 'n_words': 905}