Code coverage report for lib/User.js

Statements: 89.38% (101 / 113)      Branches: 71.43% (20 / 28)      Functions: 83.33% (30 / 36)      Lines: 89.38% (101 / 113)      Ignored: none     

All files » lib/ » User.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288            1 1 1 1 1       1   34     34     34   34   34     34   34   34   34   34   34   34   34         1 1     1           1   10   10 10 10 10 10 10                           1   10   40     3 3                 10     2 2             2         10     1 1             2             10     7   3 3 3   7         10     1   1 1   1                 1 1 1   1 1 1                   1 2   2 2 2   2 2   2 4   4     4   4   2 8 8         4 2                                         1 1 1 1 1 1 1   4 4 4 1                                   1 1 1       1   1 1 1 1                   1 1 1 1 1          
'use strict';
 
/*
    User Module
*/
 
var ApiRequest = require('./shared/ApiRequest.js');
var Addresses = require('./Addresses.js');
var Preferences = require('./Preferences.js');
var utils = require('./utils');
var lodash = require('lodash');
 
 
// class representing a User
function User(options,url)
{
    this._options = options;
 
    // override the supported methods by the BaseRequest
    this._supportedMethods = ['get','post','patch','delete'];
 
    // self_link to the user
    this._url = url;
 
    this._path = {};
 
    this._rootTemplate = this._url.split(this._options.endpoint)[1];
 
    // set the template in the corresponding request methods only
    this._template = '';
 
    this._info = null;
 
    this._addresses = null;
 
    this._subscriptions = [];
 
    this._subscriptionListIds = [];
 
    this._preferences = null;
 
    this._cleartext_password = null;
    // keys used for setting GET accessors
    this._keys = ['user_id','created_on','self_link','is_server_owner'];
}
 
 
// resolve circular dependency
module.exports = User;
var Member = require('./Member.js');
 
 
User.prototype = new ApiRequest();
 
 
// ensure that the data has been fetched
// @async
// @public
User.prototype.getInfo = function(callback) {
    // setting the template
    this._template = this._rootTemplate;
    // checking for existence of _info
    Eif ( !this._info ) {
        var that = this;
        return that.get().then(function(data) {
                            that._info = data;
                            that._setAccessors()
                            return utils.promisify(that,callback);
                        }).catch(function(e) {
                            console.error(e);
                        });
    } 
    // info already has been GETed
    else {
        return utils.promisify(this,callback);
    }
}
 
 
// set the GET & SET accessors 
// @private
User.prototype._setAccessors = function() {
    // setting only GET accessors
    this._keys.forEach( (function(key) {
 
            Object.defineProperty(this,key,{
 
                get : function() {
                    Eif ( key in this._info )
                        return this._info[key];
                    else 
                        throw new Error('KeyError : key not found in the info hashmap');
                }
            });
        }).bind(this)
    ); // only GET accessors on this._info
 
    // GETTER & SETTER for the display_name
    Object.defineProperty(this,'display_name',{
 
        get : function() {
            Eif ( 'display_name' in this._info ) {
                return this._info['display_name'];
            } else {
                return null;
            }
        },
 
        set : function(value) {
            this._info['display_name'] = value;
        }
    }); // display_name
 
    // GETTER & SETTER for the password
    Object.defineProperty(this,'password',{
 
        get : function() {
            Eif ( 'password' in this._info ) {
                return this._info['password'];
            } else {
                return null;
            }
        },
 
        set : function(value) {
            this._cleartext_password = value;
        },
 
        configurable : true
    }); // password
 
    // GETTER for the Addresses object linked to the user
    Object.defineProperty(this,'addresses',{
 
        get : function() {
            if ( !this._addresses )
            {   // addresses are not linked directly to a user
                var pathSegments = this._url.split('/');
                var userId = pathSegments[pathSegments.length-1];
                this._addresses = new Addresses(this._options,'',userId);
            }
            return this._addresses;
        }
    });
 
    // GETTER for the Preferences object corresponding the user
    Object.defineProperty(this,'preferences',{
 
        get : function() {
            Eif ( !this._preferences )
            {
                var path = this._rootTemplate + '/preferences';
                this._preferences = new Preferences(this._options,path);
            }
            return this._preferences;
        }
    });
}
 
 
// Link a address to the user
// @public
// @async
User.prototype.addAddress = function(email,callback) {
    this._template = '(:selfUrl)/addresses';
    this._path.selfUrl = this._rootTemplate;
        // no need to update the _info as it does not contain addresses info
        var that = this;
        return that.post({email : email}).then(function(data) {
                        return utils.promisify(that,callback);
                    }).catch(function(e) {
                         console.error(e);
                    });
}
 
 
// Returns a promise to the array of Members object corresponding to a User 
// @async
// @public
User.prototype.getSubscriptions = function(callback) {
    Eif ( lodash.isEmpty(this._subscriptions) )
    {
        var that = this; // for keeping this in the scope
        var counter = 0;
        return new utils.Promise(function(resolve,reject) {
 
            that.getInfo().then(function() {
                    return that.addresses.getAddresses();
                }).then(function(response) {
                    response.forEach(function(entry) {
                        that._template = '/members/find';
                        // POST data
                        var data = {
                            subscriber : entry.email
                        };
                        that.post(data)
                            .then(function(response) {
                                if ( 'entries' in response )
                                {
                                    response.entries.forEach(function(entry) {
                                        var member = new Member(that._options,entry['self_link']);
                                        that._subscriptions.push(member);
                                    });
                                } 
 
                                // keep a check on the end of loop manually
                                if ( ++counter == that.addresses.length ) {
                                    resolve(that._subscriptions);
                                }
 
                            })
 
                    }); // end forEach()
 
                }).catch(function(e) {
                    console.error(e)
                });
        }).nodeify(callback || utils.noop);
    }
    else {
        return utils.promisify(this._subscriptions,callback);
    }
}
 
 
 // @async
 // @public
 // Returns a promise to the array of list_ids to which the members are subscribed
User.prototype.getSubscriptionListIds = function(callback) {
    Eif ( lodash.isEmpty(this._subscriptionListIds) ) {
        var that = this;
        return new utils.Promise(function(resolve,reject) {
            var counter = 0; // keep an eye on the finishing of the loop
            that.getSubscriptions().then(function() {
                that._subscriptions.forEach(function(member) {
                    // get the info for each of the member
                    member.getInfo().then(function(data) {
                        that._subscriptionListIds.push(member.list_id);
                        if ( ++counter == that._subscriptions.length ) {
                            resolve(that._subscriptionListIds);
                        }
                    }).catch(function(e) {
                        console.error(e)
                    }); // getInfo()
                }); // end forEach()
            });
        }).nodeify(callback || utils.noop); // end promisification           
    }
    else {
        return utils.promisify(this._subscriptionListIds,callback);
    }
}
 
 
// Save user properties
// @async
// @public
User.prototype.save = function(callback) {
    var that = this;
    var data = {
        display_name : that._info['display_name']
    };
    // check for the existence of cleartext_password
    (that._cleartext_password) ? (data['cleartext_password'] = that._cleartext_password) : (that._cleartext_password = null);
    // set the template
    that._template = that._rootTemplate;
    return that.patch(data).then(function(data) {
                    that._info = null;
                    return utils.promisify(that,callback)
                }).catch(function(e) {
                    console.error(e);
                });
}
 
 
// deletes the user
// @public
// @async
User.prototype.deleteUser = function(callback) {
    var that = this;
    that._template = that._rootTemplate;
    return that.delete().then(function(data) {
                    return utils.promisify(that,callback)
                }).catch(function(e) {
                    console.error(e);
                });             
}