<commit_before>var _und = require('underscore');
var serviceNames = require('../serviceNames');
var thirdpartyConfig = require('./3dpartyconfig');
var FacebookStrategy = require('passport-facebook').Strategy;
var GitHubStrategy = require('passport-github').Strategy;
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var LinkedInStrategy = require('passport-linkedin-oauth2').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;

var logger = require('../../../utils/logger');
var util = require('../../../utils/util');

//----------experimental---
var authExperimentalFeatures = require('../common/auth-experimental-collapse-db.js');
//-------------------------

function updateUser (user, accessToken, profile, serviceName) {
  if(util.isNotSimpleCustomObjectOrDate(user)) {
    logger.error("impossible to update because user must be an object");
    throw 'impossible to update because user must be an object';
  }

  if(util.isNotSimpleCustomObjectOrDate(profile)) {
    logger.error("impossible to update because profile must be an object");
    throw 'impossible to update because profile must be an objects';
  }

  if(!_und.isString(serviceName) || !_und.isString(accessToken)) {
    logger.error("impossible to update because both serviceName and accessToken must be strings");
    throw 'impossible to update because both serviceName and accessToken must be strings';
  }

  const whitelistServices = _und.without(serviceNames, 'local', 'profile');
  if(whitelistServices.indexOf(serviceName) === -1) {
    logger.error("impossible to update because serviceName is not recognized");
    throw 'impossible to update because serviceName is not recognized';
  }

  // warning: if you are not able to set a value in user[serviceName]
  // go to models/users.js and add the missing property there.
  // common
  user[serviceName].id = profile.id;
  user[serviceName].token = accessToken;
  // other cases
  switch(serviceName) {
    case 'facebook':
      user[serviceName].name  = profile.name.givenName + ' ' + profile.name.familyName;
      user[serviceName].profileUrl = profile.profileUrl;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'github':
      user[serviceName].name  = profile.displayName;
      user[serviceName].username = profile.username;
      user[serviceName].profileUrl = profile.profileUrl;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'google':
      user[serviceName].name  = profile.displayName;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'linkedin':
      user[serviceName].name  = profile.name.givenName + ' ' + profile.name.familyName;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'twitter':
      user[serviceName].name  = profile.displayName ? profile.displayName : profile.username;
      user[serviceName].username  = profile.username;
      if(profile.emails && profile.emails[0] && profile.emails[0].value) {
        //twitter doesn't provide profile.email's field by default. You must
        //request the permission to twitter to ask email to users.
        //To be sure, I decided to check if email's field is available.
        user[serviceName].email = profile.emails[0].value; //get the first email
      }
      return user;
  }
  return user;
}

function authenticate(req, accessToken, refreshToken, profile, done, serviceName, userRef) {
  process.nextTick(() => {
    var sessionLocalUserId = req.session.localUserId;
    //check if the user is already logged in using the LOCAL authentication
    if(sessionLocalUserId) {
      console.log("sessionLocalUserId found - managing 3dauth + local");
      //the user is already logged in
      userRef.findOne({ '_id': sessionLocalUserId }, (err, user) => {
        if (err) {
          throw err;
        }
        console.log("User found - saving");
        var userUpdated = updateUser(user, accessToken, profile, serviceName);
        console.log("updated localuser with 3dpartyauth");
        console.log(userUpdated);
        userUpdated.save(err => {
          if (err) {
            throw err;
          }

          //----------------- experimental ---------------
          authExperimentalFeatures.collapseDb(user, serviceName, req)
          .then(result => {
            console.log("collapseDb localuser with 3dpartyauth promise: " + result);
            return done(null, result);<commit_msg>forgot to commit an updated version of 3dparty-passport used in the previous commit<commit_after>var _und = require('underscore');
var serviceNames = require('../serviceNames');
var thirdpartyConfig = require('./3dpartyconfig');
var FacebookStrategy = require('passport-facebook').Strategy;
var GitHubStrategy = require('passport-github').Strategy;
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var LinkedInStrategy = require('passport-linkedin-oauth2').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;

var logger = require('../../../utils/logger');
var util = require('../../../utils/util');

//----------experimental---
var authExperimentalFeatures = require('../common/auth-experimental-collapse-db.js');
//-------------------------

function updateUser (user, accessToken, profile, serviceName) {
  if(util.isNotSimpleCustomObjectOrDate(user)) {
    logger.error("impossible to update because user must be an object");
    throw 'impossible to update because user must be an object';
  }

  if(util.isNotSimpleCustomObjectOrDate(profile)) {
    logger.error("impossible to update because profile must be an object");
    throw 'impossible to update because profile must be an objects';
  }

  if(!_und.isString(serviceName) || !_und.isString(accessToken)) {
    logger.error("impossible to update because both serviceName and accessToken must be strings");
    throw 'impossible to update because both serviceName and accessToken must be strings';
  }

  const whitelistServices = _und.without(serviceNames, 'local', 'profile');
  if(whitelistServices.indexOf(serviceName) === -1) {
    logger.error("impossible to update because serviceName is not recognized");
    throw 'impossible to update because serviceName is not recognized';
  }

  // warning: if you are not able to set a value in user[serviceName]
  // go to models/users.js and add the missing property there.
  // common
  user[serviceName].id = profile.id;
  user[serviceName].token = accessToken;
  // other cases
  switch(serviceName) {
    case 'facebook':
      user[serviceName].name  = profile.name.givenName + ' ' + profile.name.familyName;
      user[serviceName].profileUrl = profile.profileUrl;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'github':
      user[serviceName].name  = profile.displayName;
      user[serviceName].username = profile.username;
      user[serviceName].profileUrl = profile.profileUrl;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'google':
      user[serviceName].name  = profile.displayName;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'linkedin':
      user[serviceName].name  = profile.name.givenName + ' ' + profile.name.familyName;
      user[serviceName].email = profile.emails[0].value; //get the first email
      return user;
    case 'twitter':
      user[serviceName].name  = profile.displayName ? profile.displayName : profile.username;
      user[serviceName].username  = profile.username;
      if(profile.emails && profile.emails[0] && profile.emails[0].value) {
        //twitter doesn't provide profile.email's field by default. You must
        //request the permission to twitter to ask email to users.
        //To be sure, I decided to check if email's field is available.
        user[serviceName].email = profile.emails[0].value; //get the first email
      }
      return user;
  }
  return user;
}

function authenticate(req, accessToken, refreshToken, profile, done, serviceName, userRef) {
  process.nextTick(() => {
    var sessionLocalUserId = req.session.localUserId;
    //check if the user is already logged in using the LOCAL authentication
    if(sessionLocalUserId) {
      console.log("sessionLocalUserId found - managing 3dauth + local");
      //the user is already logged in
      userRef.findOne({ '_id': sessionLocalUserId }, (err, user) => {
        if (err) {
          done(err);
          return;
        }
        if(!user) {
          done('Impossible to find an user with sessionLocalUserId');
          return;
        }
        console.log("User found - saving");
        var userUpdated = updateUser(user, accessToken, profile, serviceName);
        console.log("updated localuser with 3dpartyauth");
        userUpdated.save(err => {
          if (err) {
            done(err);
          }

          //----------------- experimental ---------------
          authExperimentalFeatures.collapseDb(user, serviceName, req)
          .then(result => {
            console.log("collapseDb localuser with 3dpartyauth promise: " + result);
            return done(null, result);
{'fraction_non_alphanumeric': 0.12967714346803508, 'fraction_numerical': 0.003100277955954672, 'mean_word_length': 3.1540852575488456, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4263955', 'n_tokens_mistral': 2534, 'n_tokens_neox': 2497, 'n_words': 706}