The mailman-client API

0.1

A Node.js client for mailman-core

File: lib/User.js

                'use strict';
                
                /**
                * @module mailman-client
                * @submodule User
                */
                
                var ApiRequest = require('./shared/ApiRequest.js');
                var Addresses = require('./Addresses.js');
                var Preferences = require('./Preferences.js');
                var utils = require('./utils');
                var lodash = require('lodash');
                
                
                /**
                * User extends ApiRequest to perform operations on the user resource
                *
                * @class User
                * @constructor
                * @extends ApiRequest
                * @param {Object} options A hash of options for the User instance
                * @param {String} options.endpoint The endpoint URI to request
                * @param {String} [options.username] A username for authenticating API requests
                * @param {String} [options.password] A password for authenticating API requests
                * @param {String} url Location of the user resource on the server
                */
                function User(options,url) {
                    /**
                    * Configuration options such as the endpoint of the API, auth parameters etc.
                    * 
                    * @private
                    * @type Object
                    * @property _options
                    * @default {}
                    */
                    this._options = options || {};
                
                    /**
                    * Supported HTTP methods
                    *
                    * @property _supportedMethods
                    * @type Array
                    * @private
                    * @default ['get','post','patch','delete']
                    */
                    this._supportedMethods = ['get','post','patch','delete'];
                
                    /**
                    * URL of the user resource 
                    *
                    * @private
                    * @type String
                    * @property _url
                    */
                    this._url = url;
                
                    /**
                    * Object containing request path variables used to assemble the request URI
                    *
                    * @property _path
                    * @type Object
                    * @private
                    * @default {}
                    */
                    this._path = {};
                
                    /** 
                    * Root template string for the domain resource used to assemble other endpoints under this category
                    * 
                    * @property _rootTemplate
                    * @type String
                    * @private
                    */
                    this._rootTemplate = this._url.split(this._options.endpoint)[1];
                
                    /**
                    * The URI template used to generate the URI to request 
                    *
                    * @private
                    * @type String
                    * @default ''
                    * @property _template
                    */
                    this._template = '';
                
                    /**
                    * Object containing the resource information, will be null if getInfo() is never called
                    *
                    * @private
                    * @type {Object}
                    * @default null
                    * @property _info
                    */
                    this._info = null;
                
                    /**
                    * Adddress instances linked to the user, will be null if getInfo() is never called
                    *
                    * @private
                    * @type {Array}
                    * @default null
                    * @property _info
                    */  
                    this._addresses = null;
                
                    /**
                    * Array of Member instances corresponding to the list subscriptions for the email address
                    *
                    * @private
                    * @type {Array}
                    * @default []
                    * @property _subscriptions
                    */
                    this._subscriptions = [];
                
                    /**
                    * Array of list ids of lists to which this address is subscribed
                    *
                    * @type {Array}
                    * @private
                    * @default []
                    * @property _subscriptions
                    */
                    this._subscriptionListIds = [];
                
                    /**
                    * The Preferences instance corresponding to User instance
                    * 
                    * @private
                    * @type Preferences
                    * @property _preferences
                    * @default null
                    */
                    this._preferences = null;
                
                    this._cleartext_password = null;
                
                    /**
                    * Array of properties based on the User _info object
                    *
                    * @private
                    * @type Array
                    * @property _keys
                    */
                    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();
                
                
                /**
                * Fetch the resource by making a HTTP GET request and calls the callback(if any), and provide a 
                * promise to the User object itself
                * 
                * @method getInfo
                * @async
                * @param {Function} [callback] The callback function to be invoked with the results
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The User object itself
                * @return {Promise} Promise to the User object itself
                */
                User.prototype.getInfo = function(callback) {
                    this._template = this._rootTemplate;
                    if ( !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);
                                        });
                    }
                    else {
                        return utils.promisify(this,callback);
                    }
                }
                
                
                /**
                * Set the accessors on the object for the resource information i.e _info object
                *
                * @method _setAccessors
                * @private
                */
                User.prototype._setAccessors = function() {
                    this._keys.forEach( (function(key) {
                
                            Object.defineProperty(this,key,{
                
                                get : function() {
                                    if ( 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 and Setter for the display name of the user
                    *
                    * @property display_name
                    * @type String
                    */
                    Object.defineProperty(this,'display_name',{
                
                        get : function() {
                            if ( 'display_name' in this._info ) {
                                return this._info['display_name'];
                            } else {
                                return null;
                            }
                        },
                
                        set : function(value) {
                            this._info['display_name'] = value;
                        }
                    }); // display_name
                
                    /**
                    * Getter and Setter for the password of the user
                    *
                    * @property password
                    * @type String
                    */
                    Object.defineProperty(this,'password',{
                
                        get : function() {
                            if ( 'password' in this._info ) {
                                return this._info['password'];
                            } else {
                                return null;
                            }
                        },
                
                        set : function(value) {
                            this._cleartext_password = value;
                        },
                
                        configurable : true
                    }); // password
                
                    /**
                    * Return the Addresses instance linked to the user
                    *
                    * @property addresses
                    * @type Addresses
                    */
                    Object.defineProperty(this,'addresses',{
                
                        get : function() {
                            if ( !this._addresses )
                            {  
                                var pathSegments = this._url.split('/');
                                var userId = pathSegments[pathSegments.length-1];
                                this._addresses = new Addresses(this._options,'',userId);
                            }
                            return this._addresses;
                        }
                    }); // addresses
                
                    /**
                    * Return the Preferences corresponding to the user
                    *
                    * @property preferences
                    * @type Preferences
                    */
                    Object.defineProperty(this,'preferences',{
                
                        get : function() {
                            if ( !this._preferences )
                            {
                                var path = this._rootTemplate + '/preferences';
                                this._preferences = new Preferences(this._options,path);
                            }
                            return this._preferences;
                        }
                    }); // preferences
                }
                
                
                /**
                * Link a address to the user
                * 
                * @async
                * @method  addAddress
                * @param {String} email The email address to be linked to the user
                * @param {Function} [callback] The callback function to be invoked with the results
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The User object itself
                * @return {Promise} Promise to the User object itself
                */
                User.prototype.addAddress = function(email,callback) {
                    this._template = '(:selfUrl)/addresses';
                    this._path.selfUrl = this._rootTemplate;
                        var that = this;
                        return that.post({email : email}).then(function(data) {
                                        return utils.promisify(that,callback);
                                    }).catch(function(e) {
                                         console.error(e);
                                    });
                }
                
                
                /**
                * Calls the callback (if any) or provide a promise to the array of Member instances
                * corresponding to the current email address 
                * 
                * @async
                * @method getSubscriptions
                * @param {Function} [callback] The callback function to be invoked with the results
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of Member instances corresponding to the current email address
                * @return {Promise} A promise to the array of Member instances corresponding to the current email address
                */
                User.prototype.getSubscriptions = function(callback) {
                    if ( lodash.isEmpty(this._subscriptions) )
                    {
                        var that = this;
                        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';
                                        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);
                    }
                }
                
                 
                /**
                * Calls the callback (if any) or provide a promise to the array of list IDs corresponding to the list subscriptions
                *
                * @async
                * @method getSubscriptionsListIds
                * @param {Function} [callback] The callback function to be invoked with the results
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result An array of list IDs corresponding to the list subscriptions
                * @return {Promise} A promise to an array of list IDs corresponding to the list subscriptions
                */
                User.prototype.getSubscriptionListIds = function(callback) {
                    if ( lodash.isEmpty(this._subscriptionListIds) ) {
                        var that = this;
                        return new utils.Promise(function(resolve,reject) {
                            var counter = 0; 
                            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 the user properties upstream
                *
                * @async
                * @method save
                * @param {Function} [callback] The callback function to be invoked with the results
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The User instance itself
                * @return {Promise} A promise to the User instance itself
                */
                User.prototype.save = function(callback) {
                    var that = this;
                    var data = {
                        display_name : that._info['display_name']
                    };
                    (that._cleartext_password) ? (data['cleartext_password'] = that._cleartext_password) : (that._cleartext_password = null);
                    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
                *
                * @async
                * @method deleteUser
                * @param {Function} [callback] The callback function to be invoked with the results
                * @param {Error|Object} callback.err Any errors encountered during the request
                * @param {Object} callback.result The User instance itself
                * @return {Promise} A promise to the User instance itself
                */
                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);
                                });             
                }
                
                /**
                * Returns the string representation of the User instance
                *
                * @method toString
                * @return {String} The string representation of the user instance
                */
                User.prototype.toString = function() {
                    return '<User ' + this.display_name + ' (' + this.user_id + ')>';
                }