<commit_before>var ns = require("./ns"),
  socket = require("./socket"),
  channels = require("./channels"),
  cache = require("./simple-cache"),
  util = require("util"),
  _ = require("underscore")._;

var DEFAULT_AUTHORITY = "guest";

function resolveAuthorities(authorities) {
  var curr,
      type,
      outAuths = [];

  for (var i = 0; i < authorities.length; i++) {
    curr = authorities[i];
    type = typeof(curr);
    if (type === 'string') {
      outAuths.push(curr);
    } else if (type === 'object') {
      // TODO:
      // The auth is an object (such as a lease).  Resolve it into a string "role".
      // If it is a lease, validate the lease (expiration etc.).  If the lease is
      // still valid, push the name onto the list.
    }
  }

  return outAuths;
}

/**
 * @class represents a user object on the server.  Instances are usually stuffed in a user's session.
 * @property {String} username the user's username
 * @property {Object} profile the user's profile object, if available
 * @property {Array} authorities an array of the authorities (roles) a user has granted to them
 * @property {boolean} authenticated true if the user is logged in
 */
var User = function(options) {
  options = options || {};
  this.username = options.username || 'anonymous';
  this.profile = options.profile || null;
  this.authorities = options.authorities || [DEFAULT_AUTHORITY];
  this.authenticated = false;
  if (options.authenticated) {
    this.authenticated = true;
  }
};

/**
 * @class manages all auth communication between client and server.
 */
var api = exports.api = /** @lends api.prototype */ {
  /**
   * note: making this a method call to support adding other conditions in the future without requiring api changes
   * @returns {boolean} the value of "authenticated".
   */
  isLoggedIn: function(user) {
    return user.authenticated;
  },
  /**
   * @param {String} named the authority to test for
   * @returns {boolean} returns true if the user has the named authority
   */
  hasAuthority: function(user, named) {
    if (typeof named === "string") {
      return (user.authorities && user.authorities.indexOf(named) >= 0);
    }
    return false;
  },
  /**
   * @param {Array} list an array of named authorities to test for
   * @returns {boolean} returns true if the user has any of the authorities in the given list
   */
  hasAnyAuthority: function(user, list) {
    for (var i = 0; i < list.length; i++) {
      if (api.hasAuthority(user, list[i])) return true;
    }
    return false;
  },
  /**
   * @param {Array} list an array of named authorities to test for
   * @returns {boolean} returns true if the user has all of the authorities in the given list
   */
  hasAllAuthorities: function(user, list) {
    for (var i = 0; i < list.length; i++) {
      if (!this.hasAuthority(user, list[i])) return false;
    }
    return true;
  },
  /**
   * Logs in by session id, username, and password.
   * If no sessionId is provided, an attempt will be made to use the current request's session.
   * If successful, the resulting user is passed into the callback function, otherwise an error is passed.
   * @param {String} sessionId The sessionId to automatically store the returned user object in, or null is no storage is desired
   * @param {String} username Username of the user to login
   * @param {String} password Password of the user to login
   * @param {Function} cb Callback function to call with result of the login attempt
   * @return undefined
   */
  loginBySessionId: function(sessionId, username, password, cb) {
    cb = cb || feather.emptyFn;
    if (!sessionId) {
      cb("Session id is required for loginBySessionId method.");
    } else {
      if (!username || !password) {
        cb("No username or password submitted.");
      }

      cache.getItemsWait([
        "feather-authdb",
        "feather-server",
        "feather-logger",
        "feather-options"
      ], function(err, cacheItems) {
        debugger;
        if (err) cb(err); else {
          var authdb = cacheItems["feather-authdb"],
            server = cacheItems["feather-server"],
            logger = cacheItems["feather-logger"],
            appOptions = cacheItems["feather-options"];

          authdb.get({id: appOptions.auth.userIdPrefix + username}, function(err, dbResult) {
            if (!err) {
              if (dbResult.password === password) {
                var user = new User({
                  authenticated: true,
                  profile: dbResult.profile || {},
                  username: (dbResult.profile && dbResult.profile.username) || dbResult.username || dbResult.name,
                  authorities: resolveAuthorities(dbResult.roles || dbResult.authorities)
                });
                server.sessionStore.get(sessionId, function(err, sess) {
                  if (!err) {
                    sess.user = user;
                    server.sessionStore.set(sessionId, sess);
                    cb(null, {user: user});
                  } else {
                    cb(err);
                  }
                });
              } else {
                logger.warn("Invalid login attempt for username '" + username + "'");
                cb("Invalid username/password");
              }
            } else {
              if (err.error && err.error === "not_found") {
                err = "Username " + username + " not found.";
              }
              cb(err);
            }
          });
        }
      });
    } //end else
  },
  /**
   * Destroys the user's session before returning
   * @param {String} sessionId The session id to use to retrieve the user for.
   * @param {Function} cb Callback function to be called after logout.
   * @return undefined
   */
  logoutBySessionId: function(sessionId, cb) {
    if (!sessionId) {
      cb && cb("Session id is required for loginBySessionId method.");
    } else {
      cache.getItemsWait([
        "feather-server",
        "feather-logger"
      ], function(err, cacheItems) {
        if (err) cb(err); else {
          var server = cacheItems["feather-server"],
            logger = cacheItems["feather-logger"];

          server.sessionStore.get(sessionId, function(err, sess) {
            if (err) cb(err); else {
              server.sessionStore.destroy(sessionId, function() {
                //after destroying the existing session, generate and store a new one, and pass the new sid back to the client
                var dummyReq = {headers:{}, sessionStore: server.sessionStore};
                server.sessionStore.generate(dummyReq);
                server.sessionStore.set(dummyReq.session.id, dummyReq.session);
                logger.info("new session ID = " + dummyReq.session.id);
                cb(null, dummyReq.session);
              });
            }
          });
        }
      });
    }
  },
  /**
   * Not implemented.
   */
   signup: function(options) {

   },
  /**
   * Not implemented.
   */
   getAuthorities: function(options) {

   },
  /**
   * Retrieves the user associated with the session matching the passed in sessionId.
   * If successful, the resulting user is passed into the callback function, otherwise an error is passed.
   * @param {String} sessionId The session id to use to retrieve the user for.
   * @param {Function} cb A callback function that is called with the user object as the 2nd argument if successful. If an error occurred retrieving the session, the error is passed to the callback as the first argument.
   * @return undefined
   */
  getUserBySessionId: function(sessionId, cb) {
    if (!sessionId) {
      cb("Session id is required for getUserBySessionId method.");
    } else {
      cache.getItemsWait([
        "feather-server"
      ], function(err, cacheItems) {
        if (err) cb(err); else {
          var server = cacheItems["feather-server"];

          server.sessionStore.get(sessionId, function(err, sess) {
            if (err) cb(err); else {
              if (sess) {
                cb(null, {user: sess.user});
              } else {
                cb();
              }
            }
          });
        }
      });
    }
  }
};

// var authChannel = channels.addChannel({
//   id: "feather:auth",
//   messages: ["login", "getUser", "logout"],
//   announceConnections: false,
//   hooks: {
//     message: function(args, cb) {
//       //this channel won't propagate messages, it's just used for internal messaging

//     }
//   }
// });

//TODO: migrate these handlers to proper channels implementation (preferably via flight services)

cache.getItemsWait([
  "feather-logger"
], function(err, cacheItems) {
  if (err) throw err;

  var logger = cacheItems["feather-logger"];

  // initialize event listeners
  socket.on("auth:login", function(args) {
    var eventArgs = args.message.data.eventArgs;
    api.loginBySessionId(args.message.sid, eventArgs.username, eventArgs.password, function(err, loginResult) {
      var result = {success: true};
      if (err) {
        result.success = false;
        result.err = err;
      } else {
        result.user = loginResult.user;
      }
      args.result.eventArgs = result;
      args.client.json.send(args.result);
    });
  });

  socket.on("auth:getUser", function(args) {
    api.getUserBySessionId(args.message.sid, function(err, getUserResult) {
      var result = {success: true};
      if (err || !getUserResult || !getUserResult.user) {
        result.success = false;
        result.err = err || "No user found.";
        logger.trace("user err: " + result.err);
      } else {
        result.user = getUserResult.user;
        logger.trace("user: " + util.inspect(getUserResult));
      }
      args.result.eventArgs = result;
      args.client.json.send(args.result);
    });
  });

  socket.on("auth:logout", function(args) {
    api.logoutBySessionId(args.message.sid, function(err, sid) {
      var result = {success: true, result: sid};
      if (err) {
        result.success = false;
        result.err = err;
      }
      args.result.eventArgs = result;
      args.client.json.send(args.result);
    });
  });
});
<commit_msg>remove debugger<commit_after>var ns = require("./ns"),
  socket = require("./socket"),
  channels = require("./channels"),
  cache = require("./simple-cache"),
  util = require("util"),
  _ = require("underscore")._;

var DEFAULT_AUTHORITY = "guest";

function resolveAuthorities(authorities) {
  var curr,
      type,
      outAuths = [];

  for (var i = 0; i < authorities.length; i++) {
    curr = authorities[i];
    type = typeof(curr);
    if (type === 'string') {
      outAuths.push(curr);
    } else if (type === 'object') {
      // TODO:
      // The auth is an object (such as a lease).  Resolve it into a string "role".
      // If it is a lease, validate the lease (expiration etc.).  If the lease is
      // still valid, push the name onto the list.
    }
  }

  return outAuths;
}

/**
 * @class represents a user object on the server.  Instances are usually stuffed in a user's session.
 * @property {String} username the user's username
 * @property {Object} profile the user's profile object, if available
 * @property {Array} authorities an array of the authorities (roles) a user has granted to them
 * @property {boolean} authenticated true if the user is logged in
 */
var User = function(options) {
  options = options || {};
  this.username = options.username || 'anonymous';
  this.profile = options.profile || null;
  this.authorities = options.authorities || [DEFAULT_AUTHORITY];
  this.authenticated = false;
  if (options.authenticated) {
    this.authenticated = true;
  }
};

/**
 * @class manages all auth communication between client and server.
 */
var api = exports.api = /** @lends api.prototype */ {
  /**
   * note: making this a method call to support adding other conditions in the future without requiring api changes
   * @returns {boolean} the value of "authenticated".
   */
  isLoggedIn: function(user) {
    return user.authenticated;
  },
  /**
   * @param {String} named the authority to test for
   * @returns {boolean} returns true if the user has the named authority
   */
  hasAuthority: function(user, named) {
    if (typeof named === "string") {
      return (user.authorities && user.authorities.indexOf(named) >= 0);
    }
    return false;
  },
  /**
   * @param {Array} list an array of named authorities to test for
   * @returns {boolean} returns true if the user has any of the authorities in the given list
   */
  hasAnyAuthority: function(user, list) {
    for (var i = 0; i < list.length; i++) {
      if (api.hasAuthority(user, list[i])) return true;
    }
    return false;
  },
  /**
   * @param {Array} list an array of named authorities to test for
   * @returns {boolean} returns true if the user has all of the authorities in the given list
   */
  hasAllAuthorities: function(user, list) {
    for (var i = 0; i < list.length; i++) {
      if (!this.hasAuthority(user, list[i])) return false;
    }
    return true;
  },
  /**
   * Logs in by session id, username, and password.
   * If no sessionId is provided, an attempt will be made to use the current request's session.
   * If successful, the resulting user is passed into the callback function, otherwise an error is passed.
   * @param {String} sessionId The sessionId to automatically store the returned user object in, or null is no storage is desired
   * @param {String} username Username of the user to login
   * @param {String} password Password of the user to login
   * @param {Function} cb Callback function to call with result of the login attempt
   * @return undefined
   */
  loginBySessionId: function(sessionId, username, password, cb) {
    cb = cb || feather.emptyFn;
    if (!sessionId) {
      cb("Session id is required for loginBySessionId method.");
    } else {
      if (!username || !password) {
        cb("No username or password submitted.");
      }

      cache.getItemsWait([
        "feather-authdb",
        "feather-server",
        "feather-logger",
        "feather-options"
      ], function(err, cacheItems) {
        if (err) cb(err); else {
          var authdb = cacheItems["feather-authdb"],
            server = cacheItems["feather-server"],
            logger = cacheItems["feather-logger"],
            appOptions = cacheItems["feather-options"];

          authdb.get({id: appOptions.auth.userIdPrefix + username}, function(err, dbResult) {
            if (!err) {
              if (dbResult.password === password) {
                var user = new User({
                  authenticated: true,
                  profile: dbResult.profile || {},
                  username: (dbResult.profile && dbResult.profile.username) || dbResult.username || dbResult.name,
                  authorities: resolveAuthorities(dbResult.roles || dbResult.authorities)
                });
                server.sessionStore.get(sessionId, function(err, sess) {
                  if (!err) {
                    sess.user = user;
                    server.sessionStore.set(sessionId, sess);
                    cb(null, {user: user});
                  } else {
                    cb(err);
                  }
                });
              } else {
                logger.warn("Invalid login attempt for username '" + username + "'");
                cb("Invalid username/password");
              }
            } else {
              if (err.error && err.error === "not_found") {
                err = "Username " + username + " not found.";
              }
              cb(err);
            }
          });
        }
      });
    } //end else
  },
  /**
   * Destroys the user's session before returning
   * @param {String} sessionId The session id to use to retrieve the user for.
   * @param {Function} cb Callback function to be called after logout.
   * @return undefined
   */
  logoutBySessionId: function(sessionId, cb) {
    if (!sessionId) {
      cb && cb("Session id is required for loginBySessionId method.");
    } else {
      cache.getItemsWait([
        "feather-server",
        "feather-logger"
      ], function(err, cacheItems) {
        if (err) cb(err); else {
          var server = cacheItems["feather-server"],
            logger = cacheItems["feather-logger"];

          server.sessionStore.get(sessionId, function(err, sess) {
            if (err) cb(err); else {
              server.sessionStore.destroy(sessionId, function() {
                //after destroying the existing session, generate and store a new one, and pass the new sid back to the client
                var dummyReq = {headers:{}, sessionStore: server.sessionStore};
                server.sessionStore.generate(dummyReq);
                server.sessionStore.set(dummyReq.session.id, dummyReq.session);
                logger.info("new session ID = " + dummyReq.session.id);
                cb(null, dummyReq.session);
              });
            }
          });
        }
      });
    }
  },
  /**
   * Not implemented.
   */
   signup: function(options) {

   },
  /**
   * Not implemented.
   */
   getAuthorities: function(options) {

   },
  /**
   * Retrieves the user associated with the session matching the passed in sessionId.
   * If successful, the resulting user is passed into the callback function, otherwise an error is passed.
   * @param {String} sessionId The session id to use to retrieve the user for.
   * @param {Function} cb A callback function that is called with the user object as the 2nd argument if successful. If an error occurred retrieving the session, the error is passed to the callback as the first argument.
   * @return undefined
   */
  getUserBySessionId: function(sessionId, cb) {
    if (!sessionId) {
      cb("Session id is required for getUserBySessionId method.");
    } else {
      cache.getItemsWait([
        "feather-server"
      ], function(err, cacheItems) {
        if (err) cb(err); else {
          var server = cacheItems["feather-server"];

          server.sessionStore.get(sessionId, function(err, sess) {
            if (err) cb(err); else {
              if (sess) {
                cb(null, {user: sess.user});
              } else {
                cb();
              }
            }
          });
        }
      });
    }
  }
};

// var authChannel = channels.addChannel({
//   id: "feather:auth",
//   messages: ["login", "getUser", "logout"],
//   announceConnections: false,
//   hooks: {
//     message: function(args, cb) {
//       //this channel won't propagate messages, it's just used for internal messaging

//     }
//   }
// });

//TODO: migrate these handlers to proper channels implementation (preferably via flight services)

cache.getItemsWait([
  "feather-logger"
], function(err, cacheItems) {
  if (err) throw err;

  var logger = cacheItems["feather-logger"];

  // initialize event listeners
  socket.on("auth:login", function(args) {
    var eventArgs = args.message.data.eventArgs;
    api.loginBySessionId(args.message.sid, eventArgs.username, eventArgs.password, function(err, loginResult) {
      var result = {success: true};
      if (err) {
        result.success = false;
        result.err = err;
      } else {
        result.user = loginResult.user;
      }
      args.result.eventArgs = result;
      args.client.json.send(args.result);
    });
  });

  socket.on("auth:getUser", function(args) {
    api.getUserBySessionId(args.message.sid, function(err, getUserResult) {
      var result = {success: true};
      if (err || !getUserResult || !getUserResult.user) {
        result.success = false;
        result.err = err || "No user found.";
        logger.trace("user err: " + result.err);
      } else {
        result.user = getUserResult.user;
        logger.trace("user: " + util.inspect(getUserResult));
      }
      args.result.eventArgs = result;
      args.client.json.send(args.result);
    });
  });

  socket.on("auth:logout", function(args) {
    api.logoutBySessionId(args.message.sid, function(err, sid) {
      var result = {success: true, result: sid};
      if (err) {
        result.success = false;
        result.err = err;
      }
      args.result.eventArgs = result;
      args.client.json.send(args.result);
    });
  });
});
<|endoftext|>


<commit_before>'use strict';

var request = require('request'),
    NodeCache = require('node-cache'),
    cache = new NodeCache({
        stdTTL: 600,
        checkperiod: 120
    }),
    config = {
        cookie_domain: process.env.COOKIE_AUTH_DOMAIN || 'https://access.redhat.com',
        cookie_auth_url: process.env.COOKIE_AUTH_URL || 'https://access.redhat.com/services/user/status?jsoncallback=',
    };

function authCheck(req, res, next) {
    var cookies = req.cookies;
    if (!cookies.rh_sso || !cookies.rh_user || !cookies.JSESSIONID) {
        req.authorized = false;
        return next();
    }
    if (cookies.rh_sso) {
        var cachedUserData = cache.get(cookies.rh_sso)[cookies.rh_sso];
        if (cachedUserData) {
            req.authorized = cachedUserData;
            return next();
        }
    }
    request({
        uri: config.cookie_auth_url,
        strictSSL: false,
        jar: _getJar(cookies)
    }, function(err, response, body) {
        try {
            var userData = JSON.parse(body.substring(body.indexOf('({') + 1, body.indexOf('})') + 1));
            if (userData.authorized) {
                req.authorized = userData;
                cache.set(cookies.rh_sso, userData);
            } else {
                req.authorized = false;
            }
        } catch (e) {
            req.authorized = false;
        }
        next();
    });
}

function _getJar(cookies) {
    var jar = request.jar();
    jar.setCookie(request.cookie('rh_sso=' + cookies.rh_sso), config.cookie_domain);
    jar.setCookie(request.cookie('rh_user=' + escape(cookies.rh_user)), config.cookie_domain);
    jar.setCookie(request.cookie('JSESSIONID=' + cookies.JSESSIONID), config.cookie_domain);
    return jar;
}

module.exports = function() {
    return authCheck;
};
<commit_msg>allow missing jsession, but add it if we find it<commit_after>'use strict';

var request = require('request'),
    NodeCache = require('node-cache'),
    cache = new NodeCache({
        stdTTL: 600,
        checkperiod: 120
    }),
    config = {
        cookie_domain: process.env.COOKIE_AUTH_DOMAIN || 'https://access.redhat.com',
        cookie_auth_url: process.env.COOKIE_AUTH_URL || 'https://access.redhat.com/services/user/status?jsoncallback=',
    };

function authCheck(req, res, next) {
    var cookies = req.cookies;
    if (!cookies.rh_sso || !cookies.rh_user) {
        req.authorized = false;
        return next();
    }
    if (cookies.rh_sso) {
        var cachedUserData = cache.get(cookies.rh_sso)[cookies.rh_sso];
        if (cachedUserData) {
            req.authorized = cachedUserData;
            return next();
        }
    }
    request({
        uri: config.cookie_auth_url,
        strictSSL: false,
        jar: _getJar(cookies)
    }, function(err, response, body) {
        try {
            var userData = JSON.parse(body.substring(body.indexOf('({') + 1, body.indexOf('})') + 1));
            if (userData.authorized) {
                req.authorized = userData;
                cache.set(cookies.rh_sso, userData);
                if (response.headers['set-cookie']) {
                    req.headers['set-cookie'] = response.headers['set-cookie'];
                }
            } else {
                req.authorized = false;
            }
        } catch (e) {
            req.authorized = false;
        }
        next();
    });
}

function _getJar(cookies) {
    var jar = request.jar();
    jar.setCookie(request.cookie('rh_sso=' + cookies.rh_sso), config.cookie_domain);
    jar.setCookie(request.cookie('rh_user=' + escape(cookies.rh_user)), config.cookie_domain);
    jar.setCookie(request.cookie('JSESSIONID=' + cookies.JSESSIONID), config.cookie_domain);
    return jar;
}

module.exports = function() {
    return authCheck;
};
<|endoftext|>


<commit_before>const Client           = require('../../../../base/client');
const Header           = require('../../../../base/header');
const BinarySocket     = require('../../../../base/socket');
const Validation       = require('../../../../common/form_validation');
const getElementById   = require('../../../../../_common/common_functions').getElementById;
const isVisible        = require('../../../../../_common/common_functions').isVisible;
const localize         = require('../../../../../_common/localize').localize;
const State            = require('../../../../../_common/storage').State;
const isEmptyObject    = require('../../../../../_common/utility').isEmptyObject;
const showLoadingImage = require('../../../../../_common/utility').showLoadingImage;

const FinancialAssessment = (() => {
    let financial_assessment = {};
    let arr_validation       = [];

    const form_selector = '#frm_assessment';

    const onLoad = () => {
        $(form_selector).on('submit', (event) => {
            event.preventDefault();
            submitForm();
        });
        BinarySocket.wait('landing_company').then(() => {
            if (/^(costarica|maltainvest)$/.test(Client.get('landing_company_shortcode'))) {
                getElementById('risk_disclaimer').setVisibility(1);
            }
        });

        getFinancialAssessment();
    };

    const getFinancialAssessment = () => {
        BinarySocket.send({ get_financial_assessment: 1 }).then((response) => {
            handleForm(response.get_financial_assessment);
        });
    };

    const displayHighRiskClassification = () => {
        $('#high_risk_classification').setVisibility(Client.getRiskAssessment());
    };

    const handleForm = (response = State.getResponse('get_financial_assessment')) => {
        hideLoadingImg(!isVisible(getElementById('msg_main')));

        financial_assessment = $.extend({}, response);

        if (isEmptyObject(financial_assessment)) {
            BinarySocket.wait('get_account_status').then(() => { displayHighRiskClassification(); });
        }

        // display Trading Experience only for financial & MT5 financial accounts
        const is_mt5_financial = /real_vanuatu_(standard|advanced|mamm_advanced)/.test(localStorage.getItem('financial_assessment_redirect'));
        $('#trading_experience_form').setVisibility(is_mt5_financial || Client.isAccountOfType('financial'));

        Object.keys(financial_assessment).forEach((key) => {
            const val = financial_assessment[key];
            $(`#${key}`).val(val);
        });

        arr_validation = [];
        $(form_selector).find('select').map(function () {
            const id = $(this).attr('id');
            arr_validation.push({ selector: `#${id}`, validations: ['req'] });
            if (financial_assessment[id] === undefined) {  // handle fields not previously set by client
                financial_assessment[id] = '';
            }
        });
        Validation.init(form_selector, arr_validation);
    };

    const submitForm = () => {
        const $btn_submit = $(`${form_selector} #btn_submit`);
        $btn_submit.attr('disabled', 'disabled');

        if (Validation.validate(form_selector)) {
            let has_changed = false;
            Object.keys(financial_assessment).forEach((key) => {
                const $key = $(`#${key}`);
                if ($key.length && $key.val() !== financial_assessment[key]) {
                    has_changed = true;
                }
            });
            if (Object.keys(financial_assessment).length === 0) has_changed = true;
            if (!has_changed) {
                showFormMessage(localize('You did not change anything.'), false);
                setTimeout(() => { $btn_submit.removeAttr('disabled'); }, 1000);
                return;
            }

            const data = { set_financial_assessment: 1 };
            showLoadingImage(getElementById('msg_form'));
            $(form_selector).find('select').each(function () {
                financial_assessment[$(this).attr('id')] = data[$(this).attr('id')] = $(this).val() || null;
            });
            BinarySocket.send(data).then((response) => {
                $btn_submit.removeAttr('disabled');
                if (response.error) {
                    showFormMessage(localize('Sorry, an error occurred while processing your request.'), false);
                } else {
                    showFormMessage(localize('Your changes have been updated successfully.'), true);
                    // need to remove financial_assessment_not_complete from status if any
                    BinarySocket.send({ get_account_status: 1 }).then(() => {
                        Header.displayAccountStatus();
                        displayHighRiskClassification();
                    });
                    getFinancialAssessment();
                }
            });
        } else {
            setTimeout(() => { $btn_submit.removeAttr('disabled'); }, 1000);
        }
    };

    const hideLoadingImg = (show_form) => {
        $('#assessment_loading').remove();
        if (show_form) {
            $(form_selector).setVisibility(1);
        }
    };

    const showFormMessage = (localized_msg, is_success) => {
        const redirect_url = localStorage.getItem('financial_assessment_redirect');
        if (is_success && /metatrader/i.test(redirect_url)) {
            localStorage.removeItem('financial_assessment_redirect');
            $.scrollTo($('h1#heading'), 500, { offset: -10 });
            $(form_selector).setVisibility(0);
            $('#msg_main').setVisibility(1);
            BinarySocket.send({ get_account_status: 1 }).then((response_status) => {
                if (+response_status.get_account_status.prompt_client_to_authenticate && Client.isAccountOfType('financial')) {
                    $('#msg_authenticate').setVisibility(1);
                }
            });
        } else {
            $('#msg_form')
                .attr('class', is_success ? 'success-msg' : 'errorfield')
                .html(is_success ? $('<ul/>', { class: 'checked', style: 'display: inline-block;' }).append($('<li/>', { text: localized_msg })) : localized_msg)
                .css('display', 'block')
                .delay(5000)
                .fadeOut(1000);
        }
    };

    const onUnload = () => {
        localStorage.removeItem('financial_assessment_redirect');
    };

    return {
        onLoad,
        onUnload,
    };
})();

module.exports = FinancialAssessment;
<commit_msg>fixed trading experience not showing for labuan advanced accounts<commit_after>const Client           = require('../../../../base/client');
const Header           = require('../../../../base/header');
const BinarySocket     = require('../../../../base/socket');
const Validation       = require('../../../../common/form_validation');
const getElementById   = require('../../../../../_common/common_functions').getElementById;
const isVisible        = require('../../../../../_common/common_functions').isVisible;
const localize         = require('../../../../../_common/localize').localize;
const State            = require('../../../../../_common/storage').State;
const isEmptyObject    = require('../../../../../_common/utility').isEmptyObject;
const showLoadingImage = require('../../../../../_common/utility').showLoadingImage;

const FinancialAssessment = (() => {
    let financial_assessment = {};
    let arr_validation       = [];

    const form_selector = '#frm_assessment';

    const onLoad = () => {
        $(form_selector).on('submit', (event) => {
            event.preventDefault();
            submitForm();
        });
        BinarySocket.wait('landing_company').then(() => {
            if (/^(costarica|maltainvest)$/.test(Client.get('landing_company_shortcode'))) {
                getElementById('risk_disclaimer').setVisibility(1);
            }
        });

        getFinancialAssessment();
    };

    const getFinancialAssessment = () => {
        BinarySocket.send({ get_financial_assessment: 1 }).then((response) => {
            handleForm(response.get_financial_assessment);
        });
    };

    const displayHighRiskClassification = () => {
        $('#high_risk_classification').setVisibility(Client.getRiskAssessment());
    };

    const handleForm = (response = State.getResponse('get_financial_assessment')) => {
        hideLoadingImg(!isVisible(getElementById('msg_main')));

        financial_assessment = $.extend({}, response);

        if (isEmptyObject(financial_assessment)) {
            BinarySocket.wait('get_account_status').then(() => { displayHighRiskClassification(); });
        }

        // display Trading Experience only for financial & MT5 financial accounts
        const is_mt5_financial = /labuan_advanced|real_vanuatu_(standard|advanced|mamm_advanced)/.test(localStorage.getItem('financial_assessment_redirect'));
        $('#trading_experience_form').setVisibility(is_mt5_financial || Client.isAccountOfType('financial'));

        Object.keys(financial_assessment).forEach((key) => {
            const val = financial_assessment[key];
            $(`#${key}`).val(val);
        });

        arr_validation = [];
        $(form_selector).find('select').map(function () {
            const id = $(this).attr('id');
            arr_validation.push({ selector: `#${id}`, validations: ['req'] });
            if (financial_assessment[id] === undefined) {  // handle fields not previously set by client
                financial_assessment[id] = '';
            }
        });
        Validation.init(form_selector, arr_validation);
    };

    const submitForm = () => {
        const $btn_submit = $(`${form_selector} #btn_submit`);
        $btn_submit.attr('disabled', 'disabled');

        if (Validation.validate(form_selector)) {
            let has_changed = false;
            Object.keys(financial_assessment).forEach((key) => {
                const $key = $(`#${key}`);
                if ($key.length && $key.val() !== financial_assessment[key]) {
                    has_changed = true;
                }
            });
            if (Object.keys(financial_assessment).length === 0) has_changed = true;
            if (!has_changed) {
                showFormMessage(localize('You did not change anything.'), false);
                setTimeout(() => { $btn_submit.removeAttr('disabled'); }, 1000);
                return;
            }

            const data = { set_financial_assessment: 1 };
            showLoadingImage(getElementById('msg_form'));
            $(form_selector).find('select').each(function () {
                financial_assessment[$(this).attr('id')] = data[$(this).attr('id')] = $(this).val() || null;
            });
            BinarySocket.send(data).then((response) => {
                $btn_submit.removeAttr('disabled');
                if (response.error) {
                    showFormMessage(localize('Sorry, an error occurred while processing your request.'), false);
                } else {
                    showFormMessage(localize('Your changes have been updated successfully.'), true);
                    // need to remove financial_assessment_not_complete from status if any
                    BinarySocket.send({ get_account_status: 1 }).then(() => {
                        Header.displayAccountStatus();
                        displayHighRiskClassification();
                    });
                    getFinancialAssessment();
                }
            });
        } else {
            setTimeout(() => { $btn_submit.removeAttr('disabled'); }, 1000);
        }
    };

    const hideLoadingImg = (show_form) => {
        $('#assessment_loading').remove();
        if (show_form) {
            $(form_selector).setVisibility(1);
        }
    };

    const showFormMessage = (localized_msg, is_success) => {
        const redirect_url = localStorage.getItem('financial_assessment_redirect');
        if (is_success && /metatrader/i.test(redirect_url)) {
            localStorage.removeItem('financial_assessment_redirect');
            $.scrollTo($('h1#heading'), 500, { offset: -10 });
            $(form_selector).setVisibility(0);
            $('#msg_main').setVisibility(1);
            BinarySocket.send({ get_account_status: 1 }).then((response_status) => {
                if (+response_status.get_account_status.prompt_client_to_authenticate && Client.isAccountOfType('financial')) {
                    $('#msg_authenticate').setVisibility(1);
                }
            });
        } else {
            $('#msg_form')
                .attr('class', is_success ? 'success-msg' : 'errorfield')
                .html(is_success ? $('<ul/>', { class: 'checked', style: 'display: inline-block;' }).append($('<li/>', { text: localized_msg })) : localized_msg)
                .css('display', 'block')
                .delay(5000)
                .fadeOut(1000);
        }
    };

    const onUnload = () => {
        localStorage.removeItem('financial_assessment_redirect');
    };

    return {
        onLoad,
        onUnload,
    };
})();

module.exports = FinancialAssessment;
<|endoftext|>


<commit_before>// authentication and authorization functions
var Client = require('cas.js');
var url = require('url');
var ad = require('../config/ad.json');
var pause = require('pause');

var ldapClient = require('../lib/ldap-client');

var mongoose = require('mongoose');
var User = mongoose.model('User');

var cas = new Client({
  base_url: 'https://liud-dev.nscl.msu.edu/cas',
  service: 'http://localhost:3000',
  version: 1.0
});

function ensureAuthenticated(req, res, next) {
  var ticketUrl = url.parse(req.url, true);
  if (req.session.userid) {
    console.log(req.session);
    if (req.query.ticket) {
      // remove the ticket query param
      console.log(req.query);
      delete ticketUrl.query.ticket;
      return res.redirect(301, url.format({
        pathname: ticketUrl.pathname,
        query: ticketUrl.query
      }));
    }
    next();
  } else if (req.query.ticket) {
    console.log(req.session);
    var halt = pause(req);
    cas.validate(req.query.ticket, function (err, status, userid) {
      if (err) {
        console.error(err.message);
        return res.send(401, err.message);
      }
      if (status) {
        req.session.userid = userid;
        User.findOne({
          adid: userid
        }).exec(function (err, user) {
          if (err) {
            console.error(err.msg);
            return res.send(500, 'internal error with db');
          }
          if (user) {
            req.session.roles = user.roles;
            req.session.username = user.name;
            user.lastVisitedOn = Date.now();
            user.save(function (err) {
              if (err) {
                console.error(err.message);
              }
            });
            if (req.session.landing) {
              return res.redirect(req.session.landing);
            }
            next();
            halt.resume();
          } else {
            // create a new user
            var searchFilter = ad.searchFilter.replace('_id', userid);
            var opts = {
              filter: searchFilter,
              attributes: ad.objAttributes,
              scope: 'sub'
            };
            ldapClient.search(ad.searchBase, opts, false, function (err, result) {
              if (err) {
                console.error(err.name + ' : ' + err.message);
                return res.send(500, 'something wrong with ad');
              }
              if (result.length === 0) {
                console.warn('cannot find ' + userid);
                return res.send(500, userid + ' is not found!');
              }
              if (result.length > 1) {
                return res.send(500, userid + ' is not unique!');
              }

              var first = new User({
                adid: userid,
                name: result[0].displayName,
                email: result[0].mail,
                office: result[0].physicalDeliveryOfficeName,
                phone: result[0].telephoneNumber,
                mobile: result[0].mobile,
                roles: [],
                lastVisitedOn: Date.now()
              });

              first.save(function (err, newUser) {
                if (err) {
                  console.error(err.msg);
                  return res.send(500, 'internal error with db');
                }
                req.session.roles = [];
                console.info('A new user logs in: ' + newUser.name);
                req.session.username = newUser.name;
                next();
                halt.resume();
              });
            });
          }
        });
      } else {
        console.error('CAS reject this ticket');
        return res.redirect(cas.service);
      }
    });
  } else {
    // if this is ajax call, then force the browser to refresh to the current page
    if (req.xhr) {
      res.set('WWW-Authenticate', 'CAS realm="' + url.format({
        protocol: 'http',
        hostname: ticketUrl.hostname
      }) + '"');
      res.send(401, 'xhr cannot be authenticated');
    } else {
      req.session.landing = req.url;
      res.redirect('https://' + cas.hostname + cas.base_path + '/login?service=' + encodeURIComponent(cas.service));
    }
  }
}

function verifyRole(role) {
  return function (req, res, next) {
    // console.log(req.session);
    if (req.session.roles) {
      if (req.session.roles.indexOf(role) > -1) {
        next();
      } else {
        res.send(403, "You are not authorized to access this resource. ");
      }
    } else {
      console.log("Cannot find the user's role.");
      res.send(500, "something wrong for the user's session");
    }
  };
}

module.exports = {
  ensureAuthenticated: ensureAuthenticated,
  verifyRole: verifyRole
};
<commit_msg>debug again<commit_after>// authentication and authorization functions
var Client = require('cas.js');
var url = require('url');
var ad = require('../config/ad.json');
var pause = require('pause');

var ldapClient = require('../lib/ldap-client');

var mongoose = require('mongoose');
var User = mongoose.model('User');

var cas = new Client({
  base_url: 'https://liud-dev.nscl.msu.edu/cas',
  service: 'http://localhost:3000',
  version: 1.0
});

function ensureAuthenticated(req, res, next) {
  console.log('at beginning, the req is ' + req);
  // console.log(req);
  var ticketUrl = url.parse(req.url, true);
  if (req.session.userid) {
    console.log(req.session);
    if (req.query.ticket) {
      // remove the ticket query param
      console.log(req.query);
      delete ticketUrl.query.ticket;
      return res.redirect(301, url.format({
        pathname: ticketUrl.pathname,
        query: ticketUrl.query
      }));
    }
    next();
  } else if (req.query.ticket) {
    console.log('has a ticket: ' + req.query.ticket + ', session: ' + req.session);
    var halt = pause(req);
    cas.validate(req.query.ticket, function (err, status, userid) {
      if (err) {
        console.error(err.message);
        return res.send(401, err.message);
      }
      if (status) {
        req.session.userid = userid;
        User.findOne({
          adid: userid
        }).exec(function (err, user) {
          if (err) {
            console.error(err.msg);
            return res.send(500, 'internal error with db');
          }
          if (user) {
            req.session.roles = user.roles;
            req.session.username = user.name;
            user.lastVisitedOn = Date.now();
            user.save(function (err) {
              if (err) {
                console.error(err.message);
              }
            });
            if (req.session.landing) {
              return res.redirect(req.session.landing);
            }
            next();
            halt.resume();
          } else {
            // create a new user
            var searchFilter = ad.searchFilter.replace('_id', userid);
            var opts = {
              filter: searchFilter,
              attributes: ad.objAttributes,
              scope: 'sub'
            };
            ldapClient.search(ad.searchBase, opts, false, function (err, result) {
              if (err) {
                console.error(err.name + ' : ' + err.message);
                return res.send(500, 'something wrong with ad');
              }
              if (result.length === 0) {
                console.warn('cannot find ' + userid);
                return res.send(500, userid + ' is not found!');
              }
              if (result.length > 1) {
                return res.send(500, userid + ' is not unique!');
              }

              var first = new User({
                adid: userid,
                name: result[0].displayName,
                email: result[0].mail,
                office: result[0].physicalDeliveryOfficeName,
                phone: result[0].telephoneNumber,
                mobile: result[0].mobile,
                roles: [],
                lastVisitedOn: Date.now()
              });

              first.save(function (err, newUser) {
                if (err) {
                  console.error(err.msg);
                  return res.send(500, 'internal error with db');
                }
                req.session.roles = [];
                console.info('A new user logs in: ' + newUser.name);
                req.session.username = newUser.name;
                next();
                halt.resume();
              });
            });
          }
        });
      } else {
        console.error('CAS reject this ticket: ' + req.query.ticket);
        return res.send(401, 'CAS reject this ticket.');
      }
    });
  } else {
    // if this is ajax call, then force the browser to refresh to the current page
    if (req.xhr) {
      res.set('WWW-Authenticate', 'CAS realm="' + url.format({
        protocol: 'http',
        hostname: ticketUrl.hostname
      }) + '"');
      res.send(401, 'xhr cannot be authenticated');
    } else {
      req.session.landing = req.url;
      res.redirect('https://' + cas.hostname + cas.base_path + '/login?service=' + encodeURIComponent(cas.service));
    }
  }
}

function verifyRole(role) {
  return function (req, res, next) {
    // console.log(req.session);
    if (req.session.roles) {
      if (req.session.roles.indexOf(role) > -1) {
        next();
      } else {
        res.send(403, "You are not authorized to access this resource. ");
      }
    } else {
      console.log("Cannot find the user's role.");
      res.send(500, "something wrong for the user's session");
    }
  };
}

module.exports = {
  ensureAuthenticated: ensureAuthenticated,
  verifyRole: verifyRole
};
<|endoftext|>


<commit_before>"use strict";
const gh = require("simple-github");
const jwt = require("jsonwebtoken");

const CERT = process.env.GITHUB_INTEGRATION_KEY;  // get private key
const ID = process.env.GITHUB_INTEGRATION_ID;
const GH_TOKEN = process.env.GITHUB_TOKEN;

let sign = (exp) => {
    return jwt.sign({ iss: ID }, CERT, { algorithm: 'RS256', expiresIn: exp });
};

let headers = token => {
    return {
        "Authorization": `Bearer ${ token }`,
        "Accept": "application/vnd.github.v3+json"
    };
};

let getAuthHeaders = (installation, options) => {
    if (installation) {
        return gh({
            debug: options && options.debug,
            headers: headers(sign("5m"))
        }).request("POST /installations/:installation_id/access_tokens", {
            installation_id: installation.id
        }).then(installation => headers(installation.token));
    }
    return Promise.resolve({ "Authorization": `token ${ GH_TOKEN }` });
};

module.exports = getAuthHeaders;
<commit_msg>Revert "No longer need preview header"<commit_after>"use strict";
const gh = require("simple-github");
const jwt = require("jsonwebtoken");

const CERT = process.env.GITHUB_INTEGRATION_KEY;  // get private key
const ID = process.env.GITHUB_INTEGRATION_ID;
const GH_TOKEN = process.env.GITHUB_TOKEN;

let sign = (exp) => {
    return jwt.sign({ iss: ID }, CERT, { algorithm: 'RS256', expiresIn: exp });
};

let headers = token => {
    return {
        "Authorization": `Bearer ${ token }`,
        "Accept": "application/vnd.github.machine-man-preview+json"
    };
};

let getAuthHeaders = (installation, options) => {
    if (installation) {
        return gh({
            debug: options && options.debug,
            headers: headers(sign("5m"))
        }).request("POST /installations/:installation_id/access_tokens", {
            installation_id: installation.id
        }).then(installation => headers(installation.token));
    }
    return Promise.resolve({ "Authorization": `token ${ GH_TOKEN }` });
};

module.exports = getAuthHeaders;
<|endoftext|>


<commit_before>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2011 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

/**
 * Emulates very small parts of cachedTypes.js and itemFields.js APIs for use with connector
 */

/**
 * @namespace
 */
Zotero.Connector_Types = new function() {
	/**
	 * Initializes types
	 * @param {Object} typeSchema typeSchema generated by Zotero.Connector.GetData#_generateTypeSchema
	 */
	this.init = function() {
		const schemaTypes = ["itemTypes", "creatorTypes", "fields"];

		// attach IDs and make referenceable by either ID or name
		for(var i=0; i<schemaTypes.length; i++) {
			var schemaType = schemaTypes[i];
			this[schemaType] = Zotero.Utilities.deepCopy(Zotero.Connector_Types.schema[schemaType]);
			for(var id in Zotero.Connector_Types.schema[schemaType]) {
				var entry = this[schemaType][id];
				entry.unshift(parseInt(id, 10));
				this[schemaType][entry[1]/* name */] = entry;
			}
		}

		var itemTypes = Zotero.Connector_Types["itemTypes"];
		var creatorTypes = Zotero.Connector_Types["creatorTypes"];
		var fields = Zotero.Connector_Types["fields"];

		Zotero.CachedTypes = function() {
			var thisType = Zotero.Connector_Types[this.schemaType];

			this.getID = function(idOrName) {
				var type = thisType[idOrName];
				return (type ? type[0]/* id */ : false);
			};

			this.getName = function(idOrName) {
				var type = thisType[idOrName];
				return (type ? type[1]/* name */ : false);
			};

			this.getLocalizedString = function(idOrName) {
				var type = thisType[idOrName];
				return (type ? type[2]/* localizedString */ : false);
			};
		}

		Zotero.ItemTypes = new function() {
			this.schemaType = "itemTypes";
			Zotero.CachedTypes.call(this);

			this.getImageSrc = function(idOrName) {
				var itemType = Zotero.Connector_Types["itemTypes"][idOrName];
				var icon = itemType ? itemType[6]/* icon */ : "treeitem-"+idOrName+".png";

				if(Zotero.isBookmarklet) {
					return ZOTERO_CONFIG.BOOKMARKLET_URL+"images/"+icon;
				} else if(Zotero.isFx) {
					return "chrome://zotero/skin/"+icon;
				} else if(Zotero.isChrome) {
					return chrome.extension.getURL("images/"+icon);
				} else if(Zotero.isSafari) {
					return safari.extension.baseURI+"images/itemTypes/"+icon;
				}
			};
		}

		Zotero.CreatorTypes = new function() {
			this.schemaType = "creatorTypes";
			Zotero.CachedTypes.call(this);

			this.getTypesForItemType = function(idOrName) {
				var itemType = itemTypes[idOrName];
				if(!itemType) return false;

				var itemCreatorTypes = itemType[3]/* creatorTypes */,
					n = itemCreatorTypes.length,
					outputTypes = new Array(n);

				for(var i=0; i<n; i++) {
					var creatorType = creatorTypes[itemCreatorTypes[i]];
					outputTypes[i] = {"id":creatorType[0]/* id */,
						"name":creatorType[1]/* name */};
				}
				return outputTypes;
			};

			this.getPrimaryIDForType = function(idOrName) {
				var itemType = itemTypes[idOrName];
				if(!itemType) return false;
				return itemTypes[3]/* creatorTypes */[0];
			};
		}

		Zotero.ItemFields = new function() {
			this.schemaType = "fields";
			Zotero.CachedTypes.call(this);

			this.isValidForType = function(fieldIdOrName, typeIdOrName) {
				var field = fields[fieldIdOrName], itemType = itemTypes[typeIdOrName];

				// mimics itemFields.js
				if(!field || !itemType) return false;

				       /* fields */        /* id */
				return itemType[4].indexOf(field[0]) !== -1;
			};

			this.getFieldIDFromTypeAndBase = function(typeIdOrName, fieldIdOrName) {
				var baseField = fields[fieldIdOrName], itemType = itemTypes[typeIdOrName];

				if(!baseField || !itemType) return false;

				// get as ID
				baseField = baseField[0]/* id */;

				// loop through base fields for item type
				var baseFields = itemType[5];
				for(var i=0, n=baseFields.length; i<n; i++) {
					if(baseFields[i] === baseField) {
						return i;
					}
				}

				return false;
			};

			this.getBaseIDFromTypeAndField = function(typeIdOrName, fieldIdOrName) {
				var field = fields[fieldIdOrName], itemType = itemTypes[typeIdOrName];
				if(!field || !itemType) {
					throw new Error("Invalid field or type ID");
				}

				var baseField = itemType[5]/* baseFields */[field[0]/* id */];
				return baseField ? baseField : false;
			};

			this.getItemTypeFields = function(typeIdOrName) {
				return itemTypes[typeIdOrName][4]/* fields */.slice();
			};
		}
	};

	/**
	 * Passes schema to a callback
	 * @param {Function} callback
	 */
	this.getSchema = function(callback) {
		callback(Zotero.Connector_Types.schema);
	};
}<commit_msg>Fix Zotero.ItemFields.getFieldIDFromTypeAndBase in connector<commit_after>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2011 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

/**
 * Emulates very small parts of cachedTypes.js and itemFields.js APIs for use with connector
 */

/**
 * @namespace
 */
Zotero.Connector_Types = new function() {
	/**
	 * Initializes types
	 * @param {Object} typeSchema typeSchema generated by Zotero.Connector.GetData#_generateTypeSchema
	 */
	this.init = function() {
		const schemaTypes = ["itemTypes", "creatorTypes", "fields"];

		// attach IDs and make referenceable by either ID or name
		for(var i=0; i<schemaTypes.length; i++) {
			var schemaType = schemaTypes[i];
			this[schemaType] = Zotero.Utilities.deepCopy(Zotero.Connector_Types.schema[schemaType]);
			for(var id in Zotero.Connector_Types.schema[schemaType]) {
				var entry = this[schemaType][id];
				entry.unshift(parseInt(id, 10));
				this[schemaType][entry[1]/* name */] = entry;
			}
		}

		var itemTypes = Zotero.Connector_Types["itemTypes"];
		var creatorTypes = Zotero.Connector_Types["creatorTypes"];
		var fields = Zotero.Connector_Types["fields"];

		Zotero.CachedTypes = function() {
			var thisType = Zotero.Connector_Types[this.schemaType];

			this.getID = function(idOrName) {
				var type = thisType[idOrName];
				return (type ? type[0]/* id */ : false);
			};

			this.getName = function(idOrName) {
				var type = thisType[idOrName];
				return (type ? type[1]/* name */ : false);
			};

			this.getLocalizedString = function(idOrName) {
				var type = thisType[idOrName];
				return (type ? type[2]/* localizedString */ : false);
			};
		}

		Zotero.ItemTypes = new function() {
			this.schemaType = "itemTypes";
			Zotero.CachedTypes.call(this);

			this.getImageSrc = function(idOrName) {
				var itemType = Zotero.Connector_Types["itemTypes"][idOrName];
				var icon = itemType ? itemType[6]/* icon */ : "treeitem-"+idOrName+".png";

				if(Zotero.isBookmarklet) {
					return ZOTERO_CONFIG.BOOKMARKLET_URL+"images/"+icon;
				} else if(Zotero.isFx) {
					return "chrome://zotero/skin/"+icon;
				} else if(Zotero.isChrome) {
					return chrome.extension.getURL("images/"+icon);
				} else if(Zotero.isSafari) {
					return safari.extension.baseURI+"images/itemTypes/"+icon;
				}
			};
		}

		Zotero.CreatorTypes = new function() {
			this.schemaType = "creatorTypes";
			Zotero.CachedTypes.call(this);

			this.getTypesForItemType = function(idOrName) {
				var itemType = itemTypes[idOrName];
				if(!itemType) return false;

				var itemCreatorTypes = itemType[3]/* creatorTypes */,
					n = itemCreatorTypes.length,
					outputTypes = new Array(n);

				for(var i=0; i<n; i++) {
					var creatorType = creatorTypes[itemCreatorTypes[i]];
					outputTypes[i] = {"id":creatorType[0]/* id */,
						"name":creatorType[1]/* name */};
				}
				return outputTypes;
			};

			this.getPrimaryIDForType = function(idOrName) {
				var itemType = itemTypes[idOrName];
				if(!itemType) return false;
				return itemTypes[3]/* creatorTypes */[0];
			};
		}

		Zotero.ItemFields = new function() {
			this.schemaType = "fields";
			Zotero.CachedTypes.call(this);

			this.isValidForType = function(fieldIdOrName, typeIdOrName) {
				var field = fields[fieldIdOrName], itemType = itemTypes[typeIdOrName];

				// mimics itemFields.js
				if(!field || !itemType) return false;

				       /* fields */        /* id */
				return itemType[4].indexOf(field[0]) !== -1;
			};

			this.getFieldIDFromTypeAndBase = function(typeIdOrName, fieldIdOrName) {
				var baseField = fields[fieldIdOrName], itemType = itemTypes[typeIdOrName];

				if(!baseField || !itemType) return false;

				// get as ID
				baseField = baseField[0]/* id */;

				// loop through base fields for item type
				var baseFields = itemType[5];
				for(var i in baseFields) {
					if(baseFields[i] === baseField) {
						return i;
					}
				}

				return false;
			};

			this.getBaseIDFromTypeAndField = function(typeIdOrName, fieldIdOrName) {
				var field = fields[fieldIdOrName], itemType = itemTypes[typeIdOrName];
				if(!field || !itemType) {
					throw new Error("Invalid field or type ID");
				}

				var baseField = itemType[5]/* baseFields */[field[0]/* id */];
				return baseField ? baseField : false;
			};

			this.getItemTypeFields = function(typeIdOrName) {
				return itemTypes[typeIdOrName][4]/* fields */.slice();
			};
		}
	};

	/**
	 * Passes schema to a callback
	 * @param {Function} callback
	 */
	this.getSchema = function(callback) {
		callback(Zotero.Connector_Types.schema);
	};
}<|endoftext|>


<commit_before>var AuthRequest = require('./authRequest')
  , fs = require('fs');

/**
 * A Blob represents a binary data object that is stored with the Nitrogen service.
 *
 * @class Blob
 * @namespace nitrogen
 */

function Blob() {
    this.id = null;
}

Blob.stringEndsWith = function(s, suffix) {
    return s.indexOf(suffix, s.length - suffix.length) !== -1;
};

/**
 * This method loads the metadata for a blob from a file: its timestamp, content type, and content length.
 *
 * @method fromFile
 * @async
 * @param {String} path The path to load this blob from.
 * @param {Object} callback Callback with the blob.
 *   @param {Object} callback.err If the load of the blob fails, this contains the error.
 *   @param {Object} callback.blob The blob metadata from the passed file.
 **/

Blob.fromFile = function(path, callback) {
	var suffix_mappings = [
		{ suffix: 'jpg', content_type: "image/jpeg", message_type: "image" },
		{ suffix: 'jpeg', content_type: "image/jpeg", message_type: "image" },
        { suffix: 'png', content_type: "image/png", message_type: "image" }
	];

	var blob = new Blob();

	suffix_mappings.forEach(function(suffix_mapping) {
		if (Blob.stringEndsWith(path, suffix_mapping.suffix)) {
			blob.content_type = suffix_mapping.content_type;
			blob.message_type = suffix_mapping.message_type;
		}
	});

    if (!blob.content_type || !blob.message_type) {
        console.log('WARNING: message_type not assigned in Blob.fromFile for path: ' + path);
    }

	fs.stat(path, function(err, stats) {
		if (err) return callback(err);

		blob.timestamp = stats.mtime;
		blob.content_length = stats.size;

		return callback(null, blob);
	});
};

/**
 * Saves the blob stream with the Nitrogen service.
 *
 * @method fromFile
 * @async
 * @param {Object} session An open session with a Nitrogen service.
 * @param {Object} stream A stream with the contents of the blob.
 * @param {Object} callback
 *   @param {Object} callback.err If the load of the blob fails, this contains the error.
 *   @param {Object} callback.blob The updated blob metadata.
 **/

Blob.prototype.save = function(session, stream, callback) {
    if (!session.service.config.blobs_endpoint) return callback("blob endpoint not available on this service");

	var self = this;

	stream.pipe(
        AuthRequest.post(session, { url: session.service.config.blobs_endpoint,
                                    headers: { 'Content-Type': self.content_type,
                                               'Content-Length': self.content_length } }, function (err, resp, body) {
            if (err) return callback(err);
            if (resp.statusCode != 200) return callback(resp.statusCode);

            var blobJSON = JSON.parse(body);
            self.updateAttributes(blobJSON.blob);

            return callback(null, self);
        })
    );
};

/**
 * Fetches a blob from the Nitrogen service.
 *
 * @method fromFile
 * @async
 * @private
 * @param {Object} session An open session with a Nitrogen service.
 * @param {Object} url The url for the blob.
 * @param {Object} callback
 *   @param {Object} callback.err If the load of the blob fails, this contains the error.
 *   @param {Object} callback.resp The response object from the request.
 *   @param {Object} callback.blobData The blob's data.
 **/

Blob.get = function(session, url, callback) {
    AuthRequest.get(session, { url: url, encoding: null }, callback);
};

Blob.prototype.updateAttributes = function(json) {
    for(var key in json) {
        if(json.hasOwnProperty(key)) {
            this[key] = json[key];
        }
    }
};

module.exports = Blob;
<commit_msg>fix spacing<commit_after>var AuthRequest = require('./authRequest')
  , fs = require('fs');

/**
 * A Blob represents a binary data object that is stored with the Nitrogen service.
 *
 * @class Blob
 * @namespace nitrogen
 */

function Blob() {
    this.id = null;
}

Blob.stringEndsWith = function(s, suffix) {
    return s.indexOf(suffix, s.length - suffix.length) !== -1;
};

/**
 * This method loads the metadata for a blob from a file: its timestamp, content type, and content length.
 *
 * @method fromFile
 * @async
 * @param {String} path The path to load this blob from.
 * @param {Object} callback Callback with the blob.
 *   @param {Object} callback.err If the load of the blob fails, this contains the error.
 *   @param {Object} callback.blob The blob metadata from the passed file.
 **/

Blob.fromFile = function(path, callback) {
    var suffix_mappings = [
        { suffix: 'jpg', content_type: "image/jpeg", message_type: "image" },
        { suffix: 'jpeg', content_type: "image/jpeg", message_type: "image" },
        { suffix: 'png', content_type: "image/png", message_type: "image" }
    ];

    var blob = new Blob();

    suffix_mappings.forEach(function(suffix_mapping) {
        if (Blob.stringEndsWith(path, suffix_mapping.suffix)) {
            blob.content_type = suffix_mapping.content_type;
            blob.message_type = suffix_mapping.message_type;
        }
    });

    if (!blob.content_type || !blob.message_type) {
        console.log('WARNING: message_type not assigned in Blob.fromFile for path: ' + path);
    }

    fs.stat(path, function(err, stats) {
        if (err) return callback(err);

        blob.timestamp = stats.mtime;
        blob.content_length = stats.size;

        return callback(null, blob);
    });
};

/**
 * Saves the blob stream with the Nitrogen service.
 *
 * @method fromFile
 * @async
 * @param {Object} session An open session with a Nitrogen service.
 * @param {Object} stream A stream with the contents of the blob.
 * @param {Object} callback
 *   @param {Object} callback.err If the load of the blob fails, this contains the error.
 *   @param {Object} callback.blob The updated blob metadata.
 **/

Blob.prototype.save = function(session, stream, callback) {
    if (!session.service.config.blobs_endpoint) return callback("blob endpoint not available on this service");

    var self = this;

    stream.pipe(
        AuthRequest.post(session, { url: session.service.config.blobs_endpoint,
                                    headers: { 'Content-Type': self.content_type,
                                               'Content-Length': self.content_length } }, function (err, resp, body) {
            if (err) return callback(err);
            if (resp.statusCode != 200) return callback(resp.statusCode);

            var blobJSON = JSON.parse(body);
            self.updateAttributes(blobJSON.blob);

            return callback(null, self);
        })
    );
};

/**
 * Fetches a blob from the Nitrogen service.
 *
 * @method fromFile
 * @async
 * @private
 * @param {Object} session An open session with a Nitrogen service.
 * @param {Object} url The url for the blob.
 * @param {Object} callback
 *   @param {Object} callback.err If the load of the blob fails, this contains the error.
 *   @param {Object} callback.resp The response object from the request.
 *   @param {Object} callback.blobData The blob's data.
 **/

Blob.get = function(session, url, callback) {
    AuthRequest.get(session, { url: url, encoding: null }, callback);
};

Blob.prototype.updateAttributes = function(json) {
    for(var key in json) {
        if(json.hasOwnProperty(key)) {
            this[key] = json[key];
        }
    }
};

module.exports = Blob;
<|endoftext|>


<commit_before>"use strict";
var Client = require("./client");
var CALL_PATH = "calls";

function Call(){
  //for compatibility
  if(arguments.length > 0){
    this.from = arguments[0];
    this.to = arguments[1];
  }
}

/** Get information about a call that was made or received
 * @param client Client instance
 * @param id Id of call
 * @param callback callback function
 * @example
 * bandwidth.Client.get(client, "id", function(err, call){});
 * */
Call.get = function(client, id, callback){
  if(arguments.length === 2){
    callback = id;
    id = client;
    client = new Client();
  }
  client.makeRequest("get", client.concatUserPath(CALL_PATH) + "/" +  id, function(err, item){
    if(err){
      return callback(err);
    }
    item.client = client;
    item.__proto__ = Call.prototype;
    callback(null, item);
  });
};

/** Get a list of previous calls that were made or received
 *  @param client Client instance
 *  @param query query parametes
 *  @param callback callback function
 *  @example
 *  bandwidth.Call.list(client, function(err, list){});
 * */
Call.list = function(client, query, callback){
  if(arguments.length === 2){
    callback = query;
    if(client instanceof Client){
      query = {};
    }
    else{
      query = client;
      client = new Client();
    }
  }
  else if(arguments.length === 1){
    callback = client;
    client = new Client();
    query = {};
  }
  client.makeRequest("get", client.concatUserPath(CALL_PATH), query, function(err, items){
    if(err){
      return callback(err);
    }
    items = items || [];
    var result = items.map(function(item){
      item.client = client;
      item.__proto__ = Call.prototype;
      return item;
    });
    callback(null, result);
  });
};

/** Make a phone call
 * @param client Client instance
 * @param item call's data
 * @param callback callback function
 * #example
 * bandwidth.Call.create(client, {from: "", to: ""}, function(err, call){});
 * */
Call.create = function(client, item, callback){
  if(arguments.length === 2){
    callback = item;
    item = client;
    client = new Client();
  }
  var request = client.createRequest("post", client.concatUserPath(CALL_PATH));
  request.type("json").send(item).end(function(res){
    if(res.ok && res.headers.location){
      Client.getIdFromLocationHeader(res.headers.location, function(err, id){
        if(err){
          return callback(err);
        }
        Call.get(client, id, callback);
      });
    }
    else{
      client.checkResponse(res, callback);
    }
  });
};

/** Make changes to an active phone call. E.g.: transfer, hang up, answer or reject incoming calls, call recording, etc.
 * @param data changed data
 * @param callback callback function
 * @example
 * call.update({state: "rejected"}, function(err){}) ;
 * */
Call.prototype.update = function(data, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH) + "/" + this.id,  data, callback);
};

/** Play an audio or speak a sentence in a call
 * @param data audio data
 * @param callback callback function
 * @example
 * call.playAudio({fileUrl: ""}, function(err}{});
 * */
Call.prototype.playAudio = function(data, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH) + "/" + this.id + "/audio",  data, callback);
};

/** Speak a sentence in a call
 * @param sentence sentence to speak
 * @param tag optional tag value which will be used in events
 * @param gender optional gender value (default: female)
 * @param voice optional voice name (default: kate)
 * @param callback callback function
 * @example
 * call.speakSentence("test", "tag", function(err){});
 */
Call.prototype.speakSentence = function(sentence, tag, gender, voice, callback){
  if(arguments.length === 2){
    callback = tag;
    tag = null;
  }
  else if(arguments.length === 3){
    callback = gender;
    gender = null;
  }
  else if(arguments.length === 4){
    callback = voice;
    return callback(new Error("Parameters 'gender' and 'voice' should be used together"));
  }
  this.playAudio({
    gender: gender || "female",
    locale: "en_US",
    voice: voice || "kate",
    sentence: sentence,
    tag: tag
  }, callback);
};

/** Play audio file in call
 * @param recordingUrl url to audio file
 * @param callback callback function
 * @example
 * call.playRecording("url", function(err){});
 */
Call.prototype.playRecording = function(recordingUrl, callback){
  this.playAudio({
    fileUrl: recordingUrl,
  }, callback);
};

/** Send DTMF
 * @param dtmf stmv value
 * @param callback callback function
 * @example
 * call.setDtmf("0", function(err){});*/
Call.prototype.setDtmf = function(dtmf, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH) + "/" + this.id + "/dtmf",  {dtmfOut: dtmf}, callback);
};

/** Gather the DTMF digits pressed
 * @param data gather's data
 * @param callback callback function
 * @example
 * call.createGather("Press a digit", function(err, gather){})
 * call.createGather({maxDigits: 1, prompt: {sentence: "Press a digit", bargeable: true }}, function(err, gather){})
 * */
Call.prototype.createGather = function(data, callback){
  if(typeof data === "string"){
    data = {
      tag: this.id,
      maxDigits: 1,
      prompt: {
        locale: "en_US",
        gender: "female",
        sentence: data,
        voice: "kate",
        bargeable: true
      }
    };
  }
  var self = this;
  var request = self.client.createRequest("post", self.client.concatUserPath(CALL_PATH) + "/" + this.id + "/gather");
  request.type("json").send(data).end(function(res){
    if(res.ok && res.headers.location){
      Client.getIdFromLocationHeader(res.headers.location, function(err, id){
        if(err){
          return callback(err);
        }
        self.getGather(id, callback);
      });
    }
    else{
      self.client.checkResponse(res, callback);
    }
  });
};

/** Update the gather DTMF (Stop Gather)
 * @param gatherId Id of gather
 * @param data changed data
 * @param callback callback function
 * @example
 * call.updateGather("id", {state: "completed"}, function(err){});*/
Call.prototype.updateGather = function(gatherId, data, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/gather/" + gatherId), data, callback);
};

/** Get the gather DTMF parameters and results
 * @param gatherId Id of gather
 * @param callback callback function
 * @example
 * call.getGather("1", function(err, gather){});*/
Call.prototype.getGather = function(gatherId, callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/gather/" + gatherId), callback);
};

/** Gets information about one call event
 * @param eventId Id of event
 * @param callback callback function
 * @example
 * call.getEvent("id", function(err, ev){});*/
Call.prototype.getEvent = function(eventId, callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/events/" + eventId), callback);
};

/** Gets the list of call events for a call
 * @example
 * call.getEvents(function(err, list){});*/
Call.prototype.getEvents = function(callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/events"), callback);
};

/** Retrieve all recordings related to the call
 * @param callback callback function
 * @example
 * call.getRecordings(function(err, list){})*/
Call.prototype.getRecordings = function(callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/recordings"), callback);
};

/** Hangup a call
 * @param callback callback function
 * @example
 * call.hangUp(function(err){});
 * */
Call.prototype.hangUp = function(callback){
  var self = this;
  self.update({state: "completed"}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Answer on incoming call
 * @param callback callback function
 * @example
 * call.answerOnIncoming(function(err){}); */
Call.prototype.answerOnIncoming = function(callback){
  var self = this;
  self.update({state: "active"}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Reject incoming call
 * @param callback callback
 * @example
 * call.rejectIncoming(function(err){});
 */
Call.prototype.rejectIncoming = function(callback){
  var self = this;
  self.update({state: "rejected"}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Tune on recording
 * @example
 * call.recordingOn(function(err){});
 */
Call.prototype.recordingOn = function(callback){
  var self = this;
  self.update({recordingEnabled: true}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Tune off recording
 * @example
 * call.recordingOff(function(err){});
 */
Call.prototype.recordingOff = function(callback){
  var self = this;
  self.update({recordingEnabled: false}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Refresh information about a call */
Call.prototype.reload = function(callback){
  var self = this;
  self.client.makeRequest("get", self.client.concatUserPath(CALL_PATH) + "/" +  self.id, function(err, item){
    if(err){
      return callback(err);
    }
    var k;
    for(k in item){
      self[k] = item[k];
    }
    callback();
  });
};

module.exports = Call;
<commit_msg>Add static method to update a call without needing to "get" it first<commit_after>"use strict";
var Client = require("./client");
var CALL_PATH = "calls";

function Call(){
  //for compatibility
  if(arguments.length > 0){
    this.from = arguments[0];
    this.to = arguments[1];
  }
}

/** Get information about a call that was made or received
 * @param client Client instance
 * @param id Id of call
 * @param callback callback function
 * @example
 * bandwidth.Client.get(client, "id", function(err, call){});
 * */
Call.get = function(client, id, callback){
  if(arguments.length === 2){
    callback = id;
    id = client;
    client = new Client();
  }
  client.makeRequest("get", client.concatUserPath(CALL_PATH) + "/" +  id, function(err, item){
    if(err){
      return callback(err);
    }
    item.client = client;
    item.__proto__ = Call.prototype;
    callback(null, item);
  });
};

/** Get a list of previous calls that were made or received
 *  @param client Client instance
 *  @param query query parametes
 *  @param callback callback function
 *  @example
 *  bandwidth.Call.list(client, function(err, list){});
 * */
Call.list = function(client, query, callback){
  if(arguments.length === 2){
    callback = query;
    if(client instanceof Client){
      query = {};
    }
    else{
      query = client;
      client = new Client();
    }
  }
  else if(arguments.length === 1){
    callback = client;
    client = new Client();
    query = {};
  }
  client.makeRequest("get", client.concatUserPath(CALL_PATH), query, function(err, items){
    if(err){
      return callback(err);
    }
    items = items || [];
    var result = items.map(function(item){
      item.client = client;
      item.__proto__ = Call.prototype;
      return item;
    });
    callback(null, result);
  });
};

/** Make a phone call
 * @param client Client instance
 * @param item call's data
 * @param callback callback function
 * #example
 * bandwidth.Call.create(client, {from: "", to: ""}, function(err, call){});
 * */
Call.create = function(client, item, callback){
  if(arguments.length === 2){
    callback = item;
    item = client;
    client = new Client();
  }
  var request = client.createRequest("post", client.concatUserPath(CALL_PATH));
  request.type("json").send(item).end(function(res){
    if(res.ok && res.headers.location){
      Client.getIdFromLocationHeader(res.headers.location, function(err, id){
        if(err){
          return callback(err);
        }
        Call.get(client, id, callback);
      });
    }
    else{
      client.checkResponse(res, callback);
    }
  });
};

/** Make changes to an active phone call. E.g.: transfer, hang up, answer or reject incoming calls, call recording, etc.
 * @param client Client instance
 * @param id Id of call
 * @param data changed data
 * @param callback callback function
 * @example
 * bandwidth.Call.update(client, "id", {state: "rejected"}, function(err){}) ;
 * */
Call.update = function(client, id, data, callback){
  client.makeRequest("post", client.concatUserPath(CALL_PATH) + "/" + id, data, callback);
};

/** Make changes to an active phone call. E.g.: transfer, hang up, answer or reject incoming calls, call recording, etc.
 * @param data changed data
 * @param callback callback function
 * @example
 * call.update({state: "rejected"}, function(err){}) ;
 * */
Call.prototype.update = function(data, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH) + "/" + this.id,  data, callback);
};

/** Play an audio or speak a sentence in a call
 * @param data audio data
 * @param callback callback function
 * @example
 * call.playAudio({fileUrl: ""}, function(err}{});
 * */
Call.prototype.playAudio = function(data, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH) + "/" + this.id + "/audio",  data, callback);
};

/** Speak a sentence in a call
 * @param sentence sentence to speak
 * @param tag optional tag value which will be used in events
 * @param gender optional gender value (default: female)
 * @param voice optional voice name (default: kate)
 * @param callback callback function
 * @example
 * call.speakSentence("test", "tag", function(err){});
 */
Call.prototype.speakSentence = function(sentence, tag, gender, voice, callback){
  if(arguments.length === 2){
    callback = tag;
    tag = null;
  }
  else if(arguments.length === 3){
    callback = gender;
    gender = null;
  }
  else if(arguments.length === 4){
    callback = voice;
    return callback(new Error("Parameters 'gender' and 'voice' should be used together"));
  }
  this.playAudio({
    gender: gender || "female",
    locale: "en_US",
    voice: voice || "kate",
    sentence: sentence,
    tag: tag
  }, callback);
};

/** Play audio file in call
 * @param recordingUrl url to audio file
 * @param callback callback function
 * @example
 * call.playRecording("url", function(err){});
 */
Call.prototype.playRecording = function(recordingUrl, callback){
  this.playAudio({
    fileUrl: recordingUrl,
  }, callback);
};

/** Send DTMF
 * @param dtmf stmv value
 * @param callback callback function
 * @example
 * call.setDtmf("0", function(err){});*/
Call.prototype.setDtmf = function(dtmf, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH) + "/" + this.id + "/dtmf",  {dtmfOut: dtmf}, callback);
};

/** Gather the DTMF digits pressed
 * @param data gather's data
 * @param callback callback function
 * @example
 * call.createGather("Press a digit", function(err, gather){})
 * call.createGather({maxDigits: 1, prompt: {sentence: "Press a digit", bargeable: true }}, function(err, gather){})
 * */
Call.prototype.createGather = function(data, callback){
  if(typeof data === "string"){
    data = {
      tag: this.id,
      maxDigits: 1,
      prompt: {
        locale: "en_US",
        gender: "female",
        sentence: data,
        voice: "kate",
        bargeable: true
      }
    };
  }
  var self = this;
  var request = self.client.createRequest("post", self.client.concatUserPath(CALL_PATH) + "/" + this.id + "/gather");
  request.type("json").send(data).end(function(res){
    if(res.ok && res.headers.location){
      Client.getIdFromLocationHeader(res.headers.location, function(err, id){
        if(err){
          return callback(err);
        }
        self.getGather(id, callback);
      });
    }
    else{
      self.client.checkResponse(res, callback);
    }
  });
};

/** Update the gather DTMF (Stop Gather)
 * @param gatherId Id of gather
 * @param data changed data
 * @param callback callback function
 * @example
 * call.updateGather("id", {state: "completed"}, function(err){});*/
Call.prototype.updateGather = function(gatherId, data, callback){
  this.client.makeRequest("post", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/gather/" + gatherId), data, callback);
};

/** Get the gather DTMF parameters and results
 * @param gatherId Id of gather
 * @param callback callback function
 * @example
 * call.getGather("1", function(err, gather){});*/
Call.prototype.getGather = function(gatherId, callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/gather/" + gatherId), callback);
};

/** Gets information about one call event
 * @param eventId Id of event
 * @param callback callback function
 * @example
 * call.getEvent("id", function(err, ev){});*/
Call.prototype.getEvent = function(eventId, callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/events/" + eventId), callback);
};

/** Gets the list of call events for a call
 * @example
 * call.getEvents(function(err, list){});*/
Call.prototype.getEvents = function(callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/events"), callback);
};

/** Retrieve all recordings related to the call
 * @param callback callback function
 * @example
 * call.getRecordings(function(err, list){})*/
Call.prototype.getRecordings = function(callback){
  this.client.makeRequest("get", this.client.concatUserPath(CALL_PATH + "/" + this.id + "/recordings"), callback);
};

/** Hangup a call
 * @param callback callback function
 * @example
 * call.hangUp(function(err){});
 * */
Call.prototype.hangUp = function(callback){
  var self = this;
  self.update({state: "completed"}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Answer on incoming call
 * @param callback callback function
 * @example
 * call.answerOnIncoming(function(err){}); */
Call.prototype.answerOnIncoming = function(callback){
  var self = this;
  self.update({state: "active"}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Reject incoming call
 * @param callback callback
 * @example
 * call.rejectIncoming(function(err){});
 */
Call.prototype.rejectIncoming = function(callback){
  var self = this;
  self.update({state: "rejected"}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Tune on recording
 * @example
 * call.recordingOn(function(err){});
 */
Call.prototype.recordingOn = function(callback){
  var self = this;
  self.update({recordingEnabled: true}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Tune off recording
 * @example
 * call.recordingOff(function(err){});
 */
Call.prototype.recordingOff = function(callback){
  var self = this;
  self.update({recordingEnabled: false}, function(err){
    if(err){
      return callback(err);
    }
    self.reload(callback);
  });
};

/** Refresh information about a call */
Call.prototype.reload = function(callback){
  var self = this;
  self.client.makeRequest("get", self.client.concatUserPath(CALL_PATH) + "/" +  self.id, function(err, item){
    if(err){
      return callback(err);
    }
    var k;
    for(k in item){
      self[k] = item[k];
    }
    callback();
  });
};

module.exports = Call;
<|endoftext|>