<commit_before>'use strict';

/**
 * This engine is responsible for 
 * finding, creating and updating auth objects
 * 
 * @return {Object} engine functions
 */
module.exports = function(){
	var waterlock = this;
  
	return {

    /**
     * Simple wrapper for Auth find/populate method
     * 
     * @param  {Object}   criteria should be id to find the auth by
     * @param  {Function} cb         function to be called when the auth has been
     *                               found or an error has occurred 
     * @api public                          
     */
    findAuth: function(criteria, cb){
      var self = this;
      waterlock.Auth.findOne(criteria).populate('user')
      .exec(function(err, auth){
        cb(err, self._invertAuth(auth));
      });
    },

    /**
     * This will create a user and auth object if one is not found
     * 
     * @param  {Object}   criteria   should be id to find the auth by
     * @param  {Object}   attributes auth attributes
     * @param  {Function} cb         function to be called when the auth has been
     *                               found or an error has occurred 
     * @api public
     */
    findOrCreateAuth: function(criteria, attributes, cb){
      var self = this;
      waterlock.Auth.findOrCreate(criteria, attributes).populate('user')
        .exec(function(err, auth){
        if(err){
          waterlock.logger.debug(err);
          return cb(err);
        }

        // population didn't work try again
        if(typeof auth.user === 'number'){
          if(!self.hasOwnProperty('_findOrCreateAuthAttempts')){
            self._findOrCreateAuthAttempts = 0;
          }
          
          if(self._findOrCreateAuthAttempts > 0){
            return cb('Cannot find or create auth');
          }
          
          self._findOrCreateAuthAttempts++;
          // let's try that again
          return self.findOrCreateAuth(auth.id, null, cb);
        }

        // if we passed the top section we can delete the attempts
        delete(self._findOrCreateAuthAttempts);

        // create the user
        if(!auth.user){
          waterlock.User.create({auth:auth.id}).exec(function(err, user){
            if(err){
              waterlock.logger.debug(err);
              return cb(err);
            }

            // update the auth object
            waterlock.Auth.update(auth.id, {user:user.id}).exec(function(err, auth){
              if(err){
                waterlock.logger.debug(err);
                return cb(err);
              }

              user.auth = auth.shift();
              cb(err, user);  
            });
          });
        }else{
          // just fire off update to user object so we can get the 
          // backwards association going.
          if(!auth.user.auth){
            waterlock.User.update(auth.user.id, {auth:auth.id}).exec(function(){});
          }
          
          cb(err, self._invertAuth(auth));
        }
      });
    },

    /**
     * Attach given auth attributes to user 
     * 
     * @param  {Object}   attributes auth attributes
     * @param  {Object}   user       user instance
     * @param  {Function} cb         function to be called when the auth has been
     *                               attached or an error has occurred 
     * @api public
     */
    attachAuthToUser: function(attributes, user, cb){
      var self = this;
      attributes.user = user.id;

      waterlock.User.findOne(user.id).exec(function(err, user){
        if(err){
          waterlock.logger.debug(err);
          return cb(err);
        }
  
        if(user.auth){
          delete(attributes.auth); 
          //update existing auth
          waterlock.Auth.findOne(user.auth).exec(function(err, auth){
            if(err){
              waterlock.logger.debug(err); 
              return cb(err); 
            }

            // Check if any attribtues have changed if so update them
            if(self._updateAuth(auth, attributes)){
               auth.save(function(err){
                if(err){
                  waterlock.logger.debug(err); 
                  return cb(err); 
                }
                user.auth = auth; 
                cb(err, user); 
              });           
            }else{
              user.auth = auth; 
              cb(err, user); 
            }

          });
        }else{
          // force create by pass null criteria 
          self.findOrCreateAuth(null, attributes, cb);
        }
      });
    },

    /**
     * Inverts the auth object so we don't need to run another query
     * 
     * @param  {Object} auth Auth object
     * @return {Object}      User object
     * @api private
     */
    _invertAuth: function(auth){<commit_msg>changed null to user.id<commit_after>'use strict';

/**
 * This engine is responsible for 
 * finding, creating and updating auth objects
 * 
 * @return {Object} engine functions
 */
module.exports = function(){
	var waterlock = this;
  
	return {

    /**
     * Simple wrapper for Auth find/populate method
     * 
     * @param  {Object}   criteria should be id to find the auth by
     * @param  {Function} cb         function to be called when the auth has been
     *                               found or an error has occurred 
     * @api public                          
     */
    findAuth: function(criteria, cb){
      var self = this;
      waterlock.Auth.findOne(criteria).populate('user')
      .exec(function(err, auth){
        cb(err, self._invertAuth(auth));
      });
    },

    /**
     * This will create a user and auth object if one is not found
     * 
     * @param  {Object}   criteria   should be id to find the auth by
     * @param  {Object}   attributes auth attributes
     * @param  {Function} cb         function to be called when the auth has been
     *                               found or an error has occurred 
     * @api public
     */
    findOrCreateAuth: function(criteria, attributes, cb){
      var self = this;
      waterlock.Auth.findOrCreate(criteria, attributes).populate('user')
        .exec(function(err, auth){
        if(err){
          waterlock.logger.debug(err);
          return cb(err);
        }

        // population didn't work try again
        if(typeof auth.user === 'number'){
          if(!self.hasOwnProperty('_findOrCreateAuthAttempts')){
            self._findOrCreateAuthAttempts = 0;
          }
          
          if(self._findOrCreateAuthAttempts > 0){
            return cb('Cannot find or create auth');
          }
          
          self._findOrCreateAuthAttempts++;
          // let's try that again
          return self.findOrCreateAuth(auth.id, null, cb);
        }

        // if we passed the top section we can delete the attempts
        delete(self._findOrCreateAuthAttempts);

        // create the user
        if(!auth.user){
          waterlock.User.create({auth:auth.id}).exec(function(err, user){
            if(err){
              waterlock.logger.debug(err);
              return cb(err);
            }

            // update the auth object
            waterlock.Auth.update(auth.id, {user:user.id}).exec(function(err, auth){
              if(err){
                waterlock.logger.debug(err);
                return cb(err);
              }

              user.auth = auth.shift();
              cb(err, user);  
            });
          });
        }else{
          // just fire off update to user object so we can get the 
          // backwards association going.
          if(!auth.user.auth){
            waterlock.User.update(auth.user.id, {auth:auth.id}).exec(function(){});
          }
          
          cb(err, self._invertAuth(auth));
        }
      });
    },

    /**
     * Attach given auth attributes to user 
     * 
     * @param  {Object}   attributes auth attributes
     * @param  {Object}   user       user instance
     * @param  {Function} cb         function to be called when the auth has been
     *                               attached or an error has occurred 
     * @api public
     */
    attachAuthToUser: function(attributes, user, cb){
      var self = this;
      attributes.user = user.id;

      waterlock.User.findOne(user.id).exec(function(err, user){
        if(err){
          waterlock.logger.debug(err);
          return cb(err);
        }
  
        if(user.auth){
          delete(attributes.auth); 
          //update existing auth
          waterlock.Auth.findOne(user.auth).exec(function(err, auth){
            if(err){
              waterlock.logger.debug(err); 
              return cb(err); 
            }

            // Check if any attribtues have changed if so update them
            if(self._updateAuth(auth, attributes)){
               auth.save(function(err){
                if(err){
                  waterlock.logger.debug(err); 
                  return cb(err); 
                }
                user.auth = auth; 
                cb(err, user); 
              });           
            }else{
              user.auth = auth; 
              cb(err, user); 
            }

          });
        }else{
          // force create by pass of user id
          self.findOrCreateAuth(user.id, attributes, cb);
        }
      });
    },

    /**
     * Inverts the auth object so we don't need to run another query
     * 
     * @param  {Object} auth Auth object
     * @return {Object}      User object
     * @api private
     */
    _invertAuth: function(auth){
{'fraction_non_alphanumeric': 0.10509654954099398, 'fraction_numerical': 0.00042207449614857024, 'mean_word_length': 1.4902785076195482, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4388181', 'n_tokens_mistral': 2592, 'n_tokens_neox': 2498, 'n_words': 691}