Source: mongodb/models/user.js

/**
 * @module mongodb/models/user
 */

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var util = require('util');
var _ = require('underscore');

// ---- Users & Segments ---- //
/**
 * Mongoose Schema representing External User ID's, in case we ever cookie-sync
 *
 * @class
 * @type {Schema}
 */
var externalIDSchema = new Schema({
    source: String,
    ext_id: String,
    tstamp: { type: Date, default: Date.now }
});
var ExternalId = mongoose.model('ExternalId', externalIDSchema);

/**
 * Mongoose Schema representing Data Segments, in case we ever use them.
 *
 * @class
 * @type {Schema}
 */
var segmentSchema = new Schema({
    name: { type: String, required: true },
    clique: String //TODO: Validator
});
var Segment = mongoose.model('Segment', segmentSchema);

/**
 * Mongoose Schema representing individual users.
 *
 * @class
 * @type {Schema}
 */
var userSchema = new Schema({
    uuid:               { type: String, required: true, index: true },
    tstamp:             { type: Date, default: Date.now },
    days_expiration:    Number,
    external_ids:       [externalIDSchema],
    useragent:          { type: String },
    //freq: { type: Number, default: 1 }, //disable until you can determine atomicity of transactions
    segments:           [{ type: Schema.ObjectId, ref: 'Segment'}]
});

var UserModels = function(connection){
    this.connection = connection;

    this.ExternalId = this.connection.model('ExternalId', externalIDSchema);
    this.Segment = this.connection.model('Segment', segmentSchema);
    this.User = this.connection.model('User', userSchema);
};

// List of useragent regex's to ignore when storing user data
// First one is any healthcheck requests from Google Load Balancer
var IGNORE_USERAGENTS = [new RegExp('^Google-GCLB.*'),new RegExp('^GoogleHC')];


/**
 * Gets or sets User object in Mongo Users DB.
 *
 * If user is found in DB, updates timestamp and returns it
 *
 * Otherwise, creates new User and saves to DB.
 *
 * @param uuid
 * @param days_expiration
 * @param useragent
 * @param callback takes (err, user) args
 */
UserModels.prototype.get_or_set_user = function(uuid, days_expiration, useragent, callback){
    // first check to make sure no ignore_useragents are found in useragent
    var skip = false;
    IGNORE_USERAGENTS.forEach(function(bad_ua){
        if (bad_ua.exec(useragent)){
            skip = true;
        }
    });
    if (skip){
        // TODO: don't callback with error cause it'll get thrown currently,
        // TODO: instead callback with null user.  This probably isn't a great
        // TODO: way to handle this.
        return callback(null, null);
    }
    var models = this;
    models.User.findOne({'uuid': uuid}).exec(function(err, user){
        if (err) return callback(err);
        if (user) {
            // if user exists, update timestamp execute callback on save
            user.tstamp = Date.now();
            user.days_expiration = days_expiration;
            user.useragent = useragent;
            //user.freq += 1; // increment f-cap by one // see above about atomicity
            user.save(callback)
        } else {
            // if not, create new user and save to DB
            var new_user = new models.User({
                uuid: uuid,
                days_expiraton: days_expiration,
                useragent: useragent
            });
            new_user.save(callback);
        }
    });
};

exports.UserModels = UserModels;