<commit_before>
/*!
 * Connect - utils
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var crypto = require('crypto')
  , Path = require('path')
  , fs = require('fs');

/**
 * Return md5 hash of the given string and optional encoding,
 * defaulting to hex.
 *
 * @param {String} str
 * @param {String} encoding
 * @return {String}
 * @api public
 */

exports.md5 = function(str, encoding){
  return crypto
    .createHash('md5')
    .update(str)
    .digest(encoding || 'hex');
};

/**
 * Merge object b with object a.
 *
 * @param {Object} a
 * @param {Object} b
 * @return {Object}
 * @api public
 */

exports.merge = function(a, b){
  if (a && b) {
    for (var key in b) {
      a[key] = b[key];
    }
  }
  return a;
};

/**
 * Return a unique identifier with the given `len`.
 *
 * @param {Number} len
 * @return {String}
 * @api public
 */

exports.uid = function(len) {
  var buf = []
    , chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    , charlen = chars.length;

  for (var i = 0; i < len; ++i) {
    buf.push(chars[getRandomInt(0, charlen - 1)]);
  }

  return buf.join('');
};

/**
 * Parse the given cookie string into an object.
 *
 * @param {String} str
 * @return {Object}
 * @api public
 */

exports.parseCookie = function(str){
  var obj = {}
    , pairs = str.split(/[;,] */);
  for (var i = 0, len = pairs.length; i < len; ++i) {
    var pair = pairs[i]
      , eqlIndex = pair.indexOf('=')
      , key = pair.substr(0, eqlIndex).trim().toLowerCase()
      , val = pair.substr(++eqlIndex, pair.length).trim();

    // Quoted values
    if (val[0] === '"') {
      val = val.slice(1, -1);
    }

    // Only assign once
    if (obj[key] === undefined) {
      obj[key] = decodeURIComponent(val.replace(/\+/g, ' '));
    }
  }
  return obj;
};

/**
 * Serialize the given object into a cookie string.
 *
 * @param {String} name
 * @param {String} val
 * @param {Object} obj
 * @return {String}
 * @api public
 */

exports.serializeCookie = function(name, val, obj){
  var pairs = [name + '=' + encodeURIComponent(val)]
    , obj = obj || {}
    , keys = Object.keys(obj)
    , len = keys.length;
  for (var i = 0; i < len; ++i) {
    var key = keys[i]
      , val = obj[key];
    if (val instanceof Date) {
      val = val.toUTCString();
    } else if (typeof val === "boolean") {
      if (true === val) pairs.push(key);
      continue;
    }
    pairs.push(key + '=' + val);
  }
  return pairs.join('; ');
};

/**
 * Pause `data` and `end` events on the given `obj`.
 *
 * @param {Object} obj
 * @return {Object}
 * @api public
 */

exports.pause = function(obj){
  var onData
    , onEnd
    , events = [];

  // buffer data
  obj.on('data', onData = function(data, encoding){
    events.push(['data', data, encoding]);
  });

  // buffer end
  obj.on('end', onEnd = function(data, encoding){
    events.push(['end', data, encoding]);
  });

  return {
    end: function(){
      obj.removeListener('data', onData);
      obj.removeListener('end', onEnd);
    },
    resume: function(){
      this.end();
      for (var i = 0, len = events.length; i < len; ++i) {
        obj.emit.apply(obj, events[i]);
      }
    }
  };
};

/**
 * Check `req` and `res` to see if it has been modified.
 *
 * @param {IncomingMessage} req
 * @param {ServerResponse} res
 * @return {Boolean}
 * @api public
 */

exports.modified = function(req, res, headers) {
  var headers = headers || res._headers || {}
    , modifiedSince = req.headers['if-modified-since']
    , lastModified = headers['last-modified']
    , noneMatch = req.headers['if-none-match']
    , etag = headers['etag'];

  // check If-None-Match
  if (noneMatch && etag && noneMatch == etag) {
    return false;
  }

  // check If-Modified-Since
  if (modifiedSince && lastModified) {
    modifiedSince = new Date(modifiedSince);
    lastModified = new Date(lastModified);
    // Ignore invalid dates
    if (!isNaN(modifiedSince.getTime())) {
      if (lastModified <= modifiedSince) return false;
    }
  }

  return true;
}

/**
 * Respond with 304 "Not Modified".
 *
 * @param {ServerResponse} res
 * @param {Object} headers
 * @api private
 */

exports.notModified = function(res) {
  // strip Content-* headers
  Object.keys(res._headers).forEach(function(field){
    if (0 == field.indexOf('content')) {
      res.removeHeader(field);
    }
  });
  res.statusCode = 304;
  res.end();
}

/**
 * Check if `req` is a conditional GET request.
 *
 * @param {IncomingMessage} req
 * @return {Boolean}
 * @api public
 */

exports.conditionalGET = function(req) {
  return req.headers['if-modified-since']
    || req.headers['if-none-match'];
}

/**
 * Return an ETag in the form of `<size>-<mtime>`
 * from the given `stat`.
 *
 * @param {Object} stat
 * @return {String}
 * @api public
 */

exports.etag = function(stat) {
  return stat.size + '-' + Number(stat.mtime);
};

/**
 * Parse "Range" header `str` relative to the given file `size`.
 *
 * @param {Number} size
 * @param {String} str
 * @return {Array}
 * @api public
 */

exports.parseRange = function(size, str){
  var valid = true;
  var arr = str.substr(6).split(',').map(function(range){
    var range = range.split('-')
      , start = parseInt(range[0], 10)
      , end = parseInt(range[1], 10);

    // -500
    if (isNaN(start)) {
      start = size - end;
      end = size - 1;
    // 500-
    } else if (isNaN(end)) {
      end = size - 1;
    }

    // Invalid
    if (isNaN(start) || isNaN(end) || start > end) valid = false;

    return { start: start, end: end };
  });
  return valid ? arr : undefined;
};

/**
 * Convert array-like object to an Array.
 *
 * node-bench: "16.5 times faster than Array.prototype.slice.call()"
 *
 * @param {Object} obj
 * @return {Array}
 * @api public
 */

var toArray = exports.toArray = function(obj){
  var len = obj.length
    , arr = new Array(len);
  for (var i = 0; i < len; ++i) {
    arr[i] = obj[i];
  }
  return arr;
};

/**
 * Retrun a random int, used by `utils.uid()`
 *
 * @param {Number} min
 * @param {Number} max
 * @return {Number}
 * @api private
 */

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
<commit_msg>Added removeContentHeaders() util<commit_after>
/*!
 * Connect - utils
 * Copyright(c) 2010 Sencha Inc.
 * Copyright(c) 2011 TJ Holowaychuk
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var crypto = require('crypto')
  , Path = require('path')
  , fs = require('fs');

/**
 * Return md5 hash of the given string and optional encoding,
 * defaulting to hex.
 *
 * @param {String} str
 * @param {String} encoding
 * @return {String}
 * @api public
 */

exports.md5 = function(str, encoding){
  return crypto
    .createHash('md5')
    .update(str)
    .digest(encoding || 'hex');
};

/**
 * Merge object b with object a.
 *
 * @param {Object} a
 * @param {Object} b
 * @return {Object}
 * @api public
 */

exports.merge = function(a, b){
  if (a && b) {
    for (var key in b) {
      a[key] = b[key];
    }
  }
  return a;
};

/**
 * Return a unique identifier with the given `len`.
 *
 * @param {Number} len
 * @return {String}
 * @api public
 */

exports.uid = function(len) {
  var buf = []
    , chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    , charlen = chars.length;

  for (var i = 0; i < len; ++i) {
    buf.push(chars[getRandomInt(0, charlen - 1)]);
  }

  return buf.join('');
};

/**
 * Parse the given cookie string into an object.
 *
 * @param {String} str
 * @return {Object}
 * @api public
 */

exports.parseCookie = function(str){
  var obj = {}
    , pairs = str.split(/[;,] */);
  for (var i = 0, len = pairs.length; i < len; ++i) {
    var pair = pairs[i]
      , eqlIndex = pair.indexOf('=')
      , key = pair.substr(0, eqlIndex).trim().toLowerCase()
      , val = pair.substr(++eqlIndex, pair.length).trim();

    // Quoted values
    if (val[0] === '"') {
      val = val.slice(1, -1);
    }

    // Only assign once
    if (obj[key] === undefined) {
      obj[key] = decodeURIComponent(val.replace(/\+/g, ' '));
    }
  }
  return obj;
};

/**
 * Serialize the given object into a cookie string.
 *
 * @param {String} name
 * @param {String} val
 * @param {Object} obj
 * @return {String}
 * @api public
 */

exports.serializeCookie = function(name, val, obj){
  var pairs = [name + '=' + encodeURIComponent(val)]
    , obj = obj || {}
    , keys = Object.keys(obj)
    , len = keys.length;
  for (var i = 0; i < len; ++i) {
    var key = keys[i]
      , val = obj[key];
    if (val instanceof Date) {
      val = val.toUTCString();
    } else if (typeof val === "boolean") {
      if (true === val) pairs.push(key);
      continue;
    }
    pairs.push(key + '=' + val);
  }
  return pairs.join('; ');
};

/**
 * Pause `data` and `end` events on the given `obj`.
 *
 * @param {Object} obj
 * @return {Object}
 * @api public
 */

exports.pause = function(obj){
  var onData
    , onEnd
    , events = [];

  // buffer data
  obj.on('data', onData = function(data, encoding){
    events.push(['data', data, encoding]);
  });

  // buffer end
  obj.on('end', onEnd = function(data, encoding){
    events.push(['end', data, encoding]);
  });

  return {
    end: function(){
      obj.removeListener('data', onData);
      obj.removeListener('end', onEnd);
    },
    resume: function(){
      this.end();
      for (var i = 0, len = events.length; i < len; ++i) {
        obj.emit.apply(obj, events[i]);
      }
    }
  };
};

/**
 * Check `req` and `res` to see if it has been modified.
 *
 * @param {IncomingMessage} req
 * @param {ServerResponse} res
 * @return {Boolean}
 * @api public
 */

exports.modified = function(req, res, headers) {
  var headers = headers || res._headers || {}
    , modifiedSince = req.headers['if-modified-since']
    , lastModified = headers['last-modified']
    , noneMatch = req.headers['if-none-match']
    , etag = headers['etag'];

  // check If-None-Match
  if (noneMatch && etag && noneMatch == etag) {
    return false;
  }

  // check If-Modified-Since
  if (modifiedSince && lastModified) {
    modifiedSince = new Date(modifiedSince);
    lastModified = new Date(lastModified);
    // Ignore invalid dates
    if (!isNaN(modifiedSince.getTime())) {
      if (lastModified <= modifiedSince) return false;
    }
  }

  return true;
};

/**
 * Respond with 304 "Not Modified".
 *
 * @param {ServerResponse} res
 * @param {Object} headers
 * @api public
 */

exports.notModified = function(res) {
  exports.removeContentHeaders(res);
  res.statusCode = 304;
  res.end();
};

/**
 * Strip `Content-*` headers from `res`.
 *
 * @param {ServerResponse} res
 * @api public
 */

exports.removeContentHeaders = function(res){
  Object.keys(res._headers).forEach(function(field){
    if (0 == field.indexOf('content')) {
      res.removeHeader(field);
    }
  });
};

/**
 * Check if `req` is a conditional GET request.
 *
 * @param {IncomingMessage} req
 * @return {Boolean}
 * @api public
 */

exports.conditionalGET = function(req) {
  return req.headers['if-modified-since']
    || req.headers['if-none-match'];
};

/**
 * Return an ETag in the form of `<size>-<mtime>`
 * from the given `stat`.
 *
 * @param {Object} stat
 * @return {String}
 * @api public
 */

exports.etag = function(stat) {
  return stat.size + '-' + Number(stat.mtime);
};

/**
 * Parse "Range" header `str` relative to the given file `size`.
 *
 * @param {Number} size
 * @param {String} str
 * @return {Array}
 * @api public
 */

exports.parseRange = function(size, str){
  var valid = true;
  var arr = str.substr(6).split(',').map(function(range){
    var range = range.split('-')
      , start = parseInt(range[0], 10)
      , end = parseInt(range[1], 10);

    // -500
    if (isNaN(start)) {
      start = size - end;
      end = size - 1;
    // 500-
    } else if (isNaN(end)) {
      end = size - 1;
    }

    // Invalid
    if (isNaN(start) || isNaN(end) || start > end) valid = false;

    return { start: start, end: end };
  });
  return valid ? arr : undefined;
};

/**
 * Convert array-like object to an Array.
 *
 * node-bench: "16.5 times faster than Array.prototype.slice.call()"
 *
 * @param {Object} obj
 * @return {Array}
 * @api public
 */

var toArray = exports.toArray = function(obj){
  var len = obj.length
    , arr = new Array(len);
  for (var i = 0; i < len; ++i) {
    arr[i] = obj[i];
  }
  return arr;
};

/**
 * Retrun a random int, used by `utils.uid()`
 *
 * @param {Number} min
 * @param {Number} max
 * @return {Number}
 * @api private
 */

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
<|endoftext|>


<commit_before>(function(exports, node) {

exports.GameLoop = GameLoop;

var Stager = node.Stager;
var GameStage = node.GameStage;

// Constants.
GameLoop.GAMEOVER = 'NODEGAME_GAMEOVER';
GameLoop.END_SEQ  = 'NODEGAME_END_SEQ';

// Constructor.
// Stager object, expert setting (default: false) as parameter.
function GameLoop(plot) {
	if (!(plot instanceof Stager)) {
		node.warn("GameLoop didn't receive Stager object");
		return;
	}

	this.plot = plot;
}

// TODO:
// .next
// .previous
// .jumpTo
// more!

// Accepts too high step (if given as integer)
GameLoop.prototype.next = function(curStage) {
	// Find out flexibility mode:
	var flexibleMode = (this.plot.sequence.length === 0);

	var seqIdx, seqObj = null, stageObj;
	var stageNo, stepNo, roundNo;
	var nextStage = null;

	curStage = new GameStage(curStage);

	if (flexibleMode) {
		if (curStage.stage === 0) {
			// Get first stage:
			if (this.plot.generalNextFunction) {
				nextStage = this.plot.generalNextFunction();
			}

			if (nextStage) {
				return new GameStage({
					stage: nextStage,
					step:  1,
					round: 1
				});
			}

			return GameLoop.END_SEQ;
		}

		// Get stage object:
		stageObj = this.plot.stages[curStage.stage];

		if ('undefined' === typeof stageObj) {
			node.warn('next received nonexistent stage: ' + curStage.stage);
			return null;
		}

		// Find step number:
		if ('number' === typeof curStage.step) {
			stepNo = curStage.step;
		}
		else {
			stepNo = stageObj.steps.indexOf(curStage.step) + 1;
		}
		if (stepNo < 1) {
			node.warn('next received nonexistent step: ' +
					stageObj.id + '.' + curStage.step);
			return null;
		}

		// Handle stepping:
		if (stepNo + 1 <= stageObj.steps.length) {
			return new GameStage({
				stage: stageObj.id,
				step:  stepNo + 1,
				round: 1
			});
		}

		// Get next stage:
		if (this.plot.nextFunctions[stageObj.id]) {
			nextStage = this.plot.nextFunctions[stageObj.id]();
		}
		else if (this.plot.generalNextFunction) {
			nextStage = this.plot.generalNextFunction();
		}

		if (nextStage) {
			return new GameStage({
				stage: nextStage,
				step:  1,
				round: 1
			});
		}

		return GameLoop.END_SEQ;
	}
	else {
		if (curStage.stage === 0) {
			return new GameStage({
				stage: 1,
				step:  1,
				round: 1
			});
		}

		// Find stage number:
		if ('number' === typeof curStage.stage) {
			stageNo = curStage.stage;
		}
		else {
			for (seqIdx = 0; seqIdx < this.plot.sequence.length; seqIdx++) {
				if (this.plot.sequence[seqIdx].id === curStage.stage) {
					break;
				}
			}
			stageNo = seqIdx + 1;
		}
		if (stageNo < 1 || stageNo > this.plot.sequence.length) {
			node.warn('next received nonexistent stage: ' + curStage.stage);
			return null;
		}

		// Get sequence object:
		seqObj = this.plot.sequence[stageNo - 1];

		if (seqObj.type === 'gameover') return GameLoop.GAMEOVER;

		// Get stage object:
		stageObj = this.plot.stages[seqObj.id];

		// Find step number:
		if ('number' === typeof curStage.step) {
			stepNo = curStage.step;
		}
		else {
			stepNo = stageObj.steps.indexOf(curStage.step) + 1;
		}
		if (stepNo < 1) {
			node.warn('next received nonexistent step: ' +
					stageObj.id + '.' + curStage.step);
			return GameLoop.END_SEQ;
		}

		// Handle stepping:
		if (stepNo + 1 <= stageObj.steps.length) {
			return new GameStage({
				stage: stageNo,
				step:  stepNo + 1,
				round: curStage.round
			});
		}

		// Handle repeat block:
		if (seqObj.type === 'repeat' && curStage.round + 1 <= seqObj.num) {
			return new GameStage({
				stage: stageNo,
				step:  1,
				round: curStage.round + 1
			});
		}

		// Handle looping blocks:
		if ((seqObj.type === 'doLoop' || seqObj.type === 'loop') && seqObj.cb()) {
			return new GameStage({
				stage: stageNo,
				step:  1,
				round: 1
			});
		}

		// Go to next stage:
		if (stageNo < this.plot.sequence.length) {
			// Skip over loops if their callbacks return false:
			while (this.plot.sequence[stageNo].type === 'loop' &&
			       !this.plot.sequence[stageNo].cb()) {
				stageNo++;
			}

			return new GameStage({
				stage: stageNo + 1,
				step:  1,
				round: 1
			});
		}

		// No more stages remaining:
		return null;
	}
};

// ## Closure
})(
	'undefined' != typeof node ? node : module.exports
  , 'undefined' != typeof node ? node : module.parent.exports
);
<commit_msg>- added docstrings in GameLoop<commit_after>/**
 * # GameLoop
 *
 * `nodeGame` container of game-state functions
 *
 * ---
 */
(function(exports, node) {

// ## Global scope
exports.GameLoop = GameLoop;

var Stager = node.Stager;
var GameStage = node.GameStage;

// ## Constants
GameLoop.GAMEOVER = 'NODEGAME_GAMEOVER';
GameLoop.END_SEQ  = 'NODEGAME_END_SEQ';

/**
 * ## GameLoop constructor
 *
 * Creates a new instance of GameLoop
 *
 * Takes a sequence object created with Stager.
 *
 * @param {object} plot The Stager object
 *
 * @see Stager
 */
function GameLoop(plot) {
	if (!(plot instanceof Stager)) {
		node.warn("GameLoop didn't receive Stager object");
		return;
	}

	this.plot = plot;
}

// ## GameLoop methods

// TODO:
// .next
// .previous
// .jumpTo
// more!

// Accepts too high step (if given as integer)
/**
 * ## GameLoop.next
 *
 * Returns the next stage in the loop
 *
 * If the step in `curStage` is an integer and out of bounds, that bound is assumed.
 *
 * @param {object} curStage Optional. The GameStage object from which to get
 *  the next one. Defaults to returning the first stage.
 *
 * @return {object} The GameStage describing the next stage
 *
 * @see GameStage
 */
GameLoop.prototype.next = function(curStage) {
	// Find out flexibility mode:
	var flexibleMode = (this.plot.sequence.length === 0);

	var seqIdx, seqObj = null, stageObj;
	var stageNo, stepNo, roundNo;
	var nextStage = null;

	curStage = new GameStage(curStage);

	if (flexibleMode) {
		if (curStage.stage === 0) {
			// Get first stage:
			if (this.plot.generalNextFunction) {
				nextStage = this.plot.generalNextFunction();
			}

			if (nextStage) {
				return new GameStage({
					stage: nextStage,
					step:  1,
					round: 1
				});
			}

			return GameLoop.END_SEQ;
		}

		// Get stage object:
		stageObj = this.plot.stages[curStage.stage];

		if ('undefined' === typeof stageObj) {
			node.warn('next received nonexistent stage: ' + curStage.stage);
			return null;
		}

		// Find step number:
		if ('number' === typeof curStage.step) {
			stepNo = curStage.step;
		}
		else {
			stepNo = stageObj.steps.indexOf(curStage.step) + 1;
		}
		if (stepNo < 1) {
			node.warn('next received nonexistent step: ' +
					stageObj.id + '.' + curStage.step);
			return null;
		}

		// Handle stepping:
		if (stepNo + 1 <= stageObj.steps.length) {
			return new GameStage({
				stage: stageObj.id,
				step:  stepNo + 1,
				round: 1
			});
		}

		// Get next stage:
		if (this.plot.nextFunctions[stageObj.id]) {
			nextStage = this.plot.nextFunctions[stageObj.id]();
		}
		else if (this.plot.generalNextFunction) {
			nextStage = this.plot.generalNextFunction();
		}

		if (nextStage) {
			return new GameStage({
				stage: nextStage,
				step:  1,
				round: 1
			});
		}

		return GameLoop.END_SEQ;
	}
	else {
		if (curStage.stage === 0) {
			return new GameStage({
				stage: 1,
				step:  1,
				round: 1
			});
		}

		// Find stage number:
		if ('number' === typeof curStage.stage) {
			stageNo = curStage.stage;
		}
		else {
			for (seqIdx = 0; seqIdx < this.plot.sequence.length; seqIdx++) {
				if (this.plot.sequence[seqIdx].id === curStage.stage) {
					break;
				}
			}
			stageNo = seqIdx + 1;
		}
		if (stageNo < 1 || stageNo > this.plot.sequence.length) {
			node.warn('next received nonexistent stage: ' + curStage.stage);
			return null;
		}

		// Get sequence object:
		seqObj = this.plot.sequence[stageNo - 1];

		if (seqObj.type === 'gameover') return GameLoop.GAMEOVER;

		// Get stage object:
		stageObj = this.plot.stages[seqObj.id];

		// Find step number:
		if ('number' === typeof curStage.step) {
			stepNo = curStage.step;
		}
		else {
			stepNo = stageObj.steps.indexOf(curStage.step) + 1;
		}
		if (stepNo < 1) {
			node.warn('next received nonexistent step: ' +
					stageObj.id + '.' + curStage.step);
			return GameLoop.END_SEQ;
		}

		// Handle stepping:
		if (stepNo + 1 <= stageObj.steps.length) {
			return new GameStage({
				stage: stageNo,
				step:  stepNo + 1,
				round: curStage.round
			});
		}

		// Handle repeat block:
		if (seqObj.type === 'repeat' && curStage.round + 1 <= seqObj.num) {
			return new GameStage({
				stage: stageNo,
				step:  1,
				round: curStage.round + 1
			});
		}

		// Handle looping blocks:
		if ((seqObj.type === 'doLoop' || seqObj.type === 'loop') && seqObj.cb()) {
			return new GameStage({
				stage: stageNo,
				step:  1,
				round: 1
			});
		}

		// Go to next stage:
		if (stageNo < this.plot.sequence.length) {
			// Skip over loops if their callbacks return false:
			while (this.plot.sequence[stageNo].type === 'loop' &&
			       !this.plot.sequence[stageNo].cb()) {
				stageNo++;
			}

			return new GameStage({
				stage: stageNo + 1,
				step:  1,
				round: 1
			});
		}

		// No more stages remaining:
		return null;
	}
};

// ## Closure
})(
	'undefined' != typeof node ? node : module.exports
  , 'undefined' != typeof node ? node : module.parent.exports
);
<|endoftext|>


<commit_before>import { canAccessRoomAsync } from './canAccessRoom';
import { hasPermissionAsync } from './hasPermission';
import { Subscriptions, Rooms } from '../../../models/server/raw';

const subscriptionOptions = {
	projection: {
		blocked: 1,
		blocker: 1,
	},
};

export const canSendMessageAsync = async (rid, { uid, username }, extraData) => {
	const room = await Rooms.findOneById(rid);

	if (!await canAccessRoomAsync(room, { _id: uid, username }, extraData)) {
		throw new Error('error-not-allowed');
	}

	const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, uid, subscriptionOptions);
	if (subscription.blocked || subscription.blocker) {
		throw new Error('room_is_blocked');
	}

	if (room.ro === true && !await hasPermissionAsync(uid, 'post-readonly', rid)) {
		// Unless the user was manually unmuted
		if (!(room.unmuted || []).includes(username)) {
			throw new Error('You can\'t send messages because the room is readonly.');
		}
	}

	if ((room.muted || []).includes(username)) {
		throw new Error('You_have_been_muted');
	}

	return room;
};

export const canSendMessage = (rid, { uid, username }, extraData) => Promise.await(canSendMessageAsync(rid, { uid, username }, extraData));
<commit_msg>[FIX] Sending messages to livechat rooms without a subscription (#15707)<commit_after>import { canAccessRoomAsync } from './canAccessRoom';
import { hasPermissionAsync } from './hasPermission';
import { Subscriptions, Rooms } from '../../../models/server/raw';

const subscriptionOptions = {
	projection: {
		blocked: 1,
		blocker: 1,
	},
};

export const canSendMessageAsync = async (rid, { uid, username }, extraData) => {
	const room = await Rooms.findOneById(rid);

	if (!await canAccessRoomAsync(room, { _id: uid, username }, extraData)) {
		throw new Error('error-not-allowed');
	}

	const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, uid, subscriptionOptions);
	if (subscription && (subscription.blocked || subscription.blocker)) {
		throw new Error('room_is_blocked');
	}

	if (room.ro === true && !await hasPermissionAsync(uid, 'post-readonly', rid)) {
		// Unless the user was manually unmuted
		if (!(room.unmuted || []).includes(username)) {
			throw new Error('You can\'t send messages because the room is readonly.');
		}
	}

	if ((room.muted || []).includes(username)) {
		throw new Error('You_have_been_muted');
	}

	return room;
};

export const canSendMessage = (rid, { uid, username }, extraData) => Promise.await(canSendMessageAsync(rid, { uid, username }, extraData));
<|endoftext|>


<commit_before>'use strict';

var schedule = require('node-schedule'),
    mongoose = require('mongoose'),
    User = mongoose.model('User'),
    Walkin = mongoose.model('Walkin'),
    Email = require('./email-util.server.controller.js');

var popOpt = [
    { path : 'user', model : 'User', select : 'firstName lastName username'},
];

var scheduledSurveyBroadCast_Walkin = function(){
    return schedule.scheduleJob('0 8 12 * * 1-5',
    function(){
        var i, user, today = new Date(Date.now());
        today.setHours(0); today.setMinutes(0);

        Walkin.find({status : 'Completed', isActive : true, updated : {$gte: today} })
            .select('user -_id').populate(popOpt).exec(
            function(err, users){
                if(err) return console.error(err);

                for(i = 0; i < users.length; i++){
                    user = users[i].user;
                    Email.sendSurvey_routine(user.username+'@emory.edu', user.firstName);
                }
            });
    });
};

exports.initScheduledJobs = function(){
    console.log('Initializing Scheduled Jobs...');

    scheduledSurveyBroadCast_Walkin(); console.log('---> Scheduled Routine Walk-in Survery Email BroadCast @ 6pm: Done.');
};

<commit_msg>Update scheduled time<commit_after>'use strict';

var schedule = require('node-schedule'),
    mongoose = require('mongoose'),
    User = mongoose.model('User'),
    Walkin = mongoose.model('Walkin'),
    Email = require('./email-util.server.controller.js');

var popOpt = [
    { path : 'user', model : 'User', select : 'firstName lastName username'},
];

var scheduledSurveyBroadCast_Walkin = function(){
    return schedule.scheduleJob('0 0 18 * * 1-5',
    function(){
        var i, user, today = new Date(Date.now());
        today.setHours(0); today.setMinutes(0);

        Walkin.find({status : 'Completed', isActive : true, updated : {$gte: today} })
            .select('user -_id').populate(popOpt).exec(
            function(err, users){
                if(err) return console.error(err);

                for(i = 0; i < users.length; i++){
                    user = users[i].user;
                    Email.sendSurvey_routine(user.username+'@emory.edu', user.firstName);
                }
            });
    });
};

exports.initScheduledJobs = function(){
    console.log('Initializing Scheduled Jobs...');

    scheduledSurveyBroadCast_Walkin(); console.log('---> Scheduled Routine Walk-in Survery Email BroadCast @ 6pm: Done.');
};

<|endoftext|>


<commit_before>/**
 * Copyright 2014 Ian Davies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 * 		http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
define([], function() {

	    var pathDefs = {
	        fill: ['M15.833,24.334c2.179-0.443,4.766-3.995,6.545-5.359 c1.76-1.35,4.144-3.732,6.256-4.339c-3.983,3.844-6.504,9.556-10.047,13.827c-2.325,2.802-5.387,6.153-6.068,9.866 c2.081-0.474,4.484-2.502,6.425-3.488c5.708-2.897,11.316-6.804,16.608-10.418c4.812-3.287,11.13-7.53,13.935-12.905 c-0.759,3.059-3.364,6.421-4.943,9.203c-2.728,4.806-6.064,8.417-9.781,12.446c-6.895,7.477-15.107,14.109-20.779,22.608 c3.515-0.784,7.103-2.996,10.263-4.628c6.455-3.335,12.235-8.381,17.684-13.15c5.495-4.81,10.848-9.68,15.866-14.988 c1.905-2.016,4.178-4.42,5.556-6.838c0.051,1.256-0.604,2.542-1.03,3.672c-1.424,3.767-3.011,7.432-4.723,11.076 c-2.772,5.904-6.312,11.342-9.921,16.763c-3.167,4.757-7.082,8.94-10.854,13.205c-2.456,2.777-4.876,5.977-7.627,8.448 c9.341-7.52,18.965-14.629,27.924-22.656c4.995-4.474,9.557-9.075,13.586-14.446c1.443-1.924,2.427-4.939,3.74-6.56 c-0.446,3.322-2.183,6.878-3.312,10.032c-2.261,6.309-5.352,12.53-8.418,18.482c-3.46,6.719-8.134,12.698-11.954,19.203 c-0.725,1.234-1.833,2.451-2.265,3.77c2.347-0.48,4.812-3.199,7.028-4.286c4.144-2.033,7.787-4.938,11.184-8.072 c3.142-2.9,5.344-6.758,7.925-10.141c1.483-1.944,3.306-4.056,4.341-6.283c0.041,1.102-0.507,2.345-0.876,3.388 c-1.456,4.114-3.369,8.184-5.059,12.212c-1.503,3.583-3.421,7.001-5.277,10.411c-0.967,1.775-2.471,3.528-3.287,5.298 c2.49-1.163,5.229-3.906,7.212-5.828c2.094-2.028,5.027-4.716,6.33-7.335c-0.256,1.47-2.07,3.577-3.02,4.809'],
	    },
	            animDefs = {
	        fill: {speed: .8, easing: 'ease-in-out'}
	    };

	function initRadioButton(el) {

	    function createSVGEl(def) {
	        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
	        if (def) {
	            svg.setAttributeNS(null, 'viewBox', def.viewBox);
	            svg.setAttributeNS(null, 'preserveAspectRatio', def.preserveAspectRatio);
	        }
	        else {
	            svg.setAttributeNS(null, 'viewBox', '0 0 100 100');
	        }
	        svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
	        return svg;
	    }

        var svg = createSVGEl();
        el.parentNode.appendChild(svg);
	}

    function draw(el, type) {
        var paths = [], pathDef,
                animDef,
                svg = el.parentNode.querySelector('svg');

        switch (type) {
            case 'fill':
                pathDef = pathDefs.fill;
                animDef = animDefs.fill;
                break;
        }
        ;

        paths.push(document.createElementNS('http://www.w3.org/2000/svg', 'path'));

        if (type === 'cross' || type === 'list') {
            paths.push(document.createElementNS('http://www.w3.org/2000/svg', 'path'));
        }

        for (var i = 0, len = paths.length; i < len; ++i) {
            var path = paths[i];
            svg.appendChild(path);

            path.setAttributeNS(null, 'd', pathDef[i]);

            var length = path.getTotalLength();
            // Set up the starting positions
            path.style.strokeDasharray = length + ' ' + length;
            if (i === 0) {
                path.style.strokeDashoffset = Math.floor(length) - 1;
            }
            else
                path.style.strokeDashoffset = length;
            // Trigger a layout so styles are calculated & the browser
            // picks up the starting position before animating
            path.getBoundingClientRect();
            // Define our transition
            path.style.transition = path.style.WebkitTransition = path.style.MozTransition = 'stroke-dashoffset ' + animDef.speed + 's ' + animDef.easing + ' ' + i * animDef.speed + 's';
            // Go!
            path.style.strokeDashoffset = '0';
        }
    }

    function reset(el) {
        Array.prototype.slice.call(el.parentNode.querySelectorAll('svg > path')).forEach(function(el) {
            el.parentNode.removeChild(el);
        });
    }

	return [function() {

		return {
			restrict: 'A',

			link: function(scope, element, attrs) {
				initRadioButton(element[0]);

				if (attrs.ngModel != null && attrs.ngModel.length > 0) {
					var dotPos = attrs.ngModel.indexOf('.');

					var watchCollection;
					if (dotPos > -1) {
						watchCollection = attrs.ngModel.substr(0, dotPos);
					} else {
						watchCollection = attrs.ngModel;
					}

					scope.$watchCollection(watchCollection, function(newVal, oldVal) {
						index = scope.$eval(attrs.ngValue);

						if (index == newVal.selectedAnswer) {
							draw(element[0], 'fill');
						} else {
							reset(element[0]);
						}
					});
				}
			}
		};
	}];
});

<commit_msg>Fixed radio button drawing to work on account settings and multiple choice questions.<commit_after>/**
 * Copyright 2014 Ian Davies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 * 		http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
define([], function() {

	    var pathDefs = {
	        fill: ['M15.833,24.334c2.179-0.443,4.766-3.995,6.545-5.359 c1.76-1.35,4.144-3.732,6.256-4.339c-3.983,3.844-6.504,9.556-10.047,13.827c-2.325,2.802-5.387,6.153-6.068,9.866 c2.081-0.474,4.484-2.502,6.425-3.488c5.708-2.897,11.316-6.804,16.608-10.418c4.812-3.287,11.13-7.53,13.935-12.905 c-0.759,3.059-3.364,6.421-4.943,9.203c-2.728,4.806-6.064,8.417-9.781,12.446c-6.895,7.477-15.107,14.109-20.779,22.608 c3.515-0.784,7.103-2.996,10.263-4.628c6.455-3.335,12.235-8.381,17.684-13.15c5.495-4.81,10.848-9.68,15.866-14.988 c1.905-2.016,4.178-4.42,5.556-6.838c0.051,1.256-0.604,2.542-1.03,3.672c-1.424,3.767-3.011,7.432-4.723,11.076 c-2.772,5.904-6.312,11.342-9.921,16.763c-3.167,4.757-7.082,8.94-10.854,13.205c-2.456,2.777-4.876,5.977-7.627,8.448 c9.341-7.52,18.965-14.629,27.924-22.656c4.995-4.474,9.557-9.075,13.586-14.446c1.443-1.924,2.427-4.939,3.74-6.56 c-0.446,3.322-2.183,6.878-3.312,10.032c-2.261,6.309-5.352,12.53-8.418,18.482c-3.46,6.719-8.134,12.698-11.954,19.203 c-0.725,1.234-1.833,2.451-2.265,3.77c2.347-0.48,4.812-3.199,7.028-4.286c4.144-2.033,7.787-4.938,11.184-8.072 c3.142-2.9,5.344-6.758,7.925-10.141c1.483-1.944,3.306-4.056,4.341-6.283c0.041,1.102-0.507,2.345-0.876,3.388 c-1.456,4.114-3.369,8.184-5.059,12.212c-1.503,3.583-3.421,7.001-5.277,10.411c-0.967,1.775-2.471,3.528-3.287,5.298 c2.49-1.163,5.229-3.906,7.212-5.828c2.094-2.028,5.027-4.716,6.33-7.335c-0.256,1.47-2.07,3.577-3.02,4.809'],
	    },
	            animDefs = {
	        fill: {speed: .8, easing: 'ease-in-out'}
	    };

	function initRadioButton(el) {

	    function createSVGEl(def) {
	        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
	        if (def) {
	            svg.setAttributeNS(null, 'viewBox', def.viewBox);
	            svg.setAttributeNS(null, 'preserveAspectRatio', def.preserveAspectRatio);
	        }
	        else {
	            svg.setAttributeNS(null, 'viewBox', '0 0 100 100');
	        }
	        svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
	        return svg;
	    }

        var svg = createSVGEl();
        el.parentNode.appendChild(svg);
	}

    function draw(el, type) {
        var paths = [], pathDef,
                animDef,
                svg = el.parentNode.querySelector('svg');

        switch (type) {
            case 'fill':
                pathDef = pathDefs.fill;
                animDef = animDefs.fill;
                break;
        }
        ;

        paths.push(document.createElementNS('http://www.w3.org/2000/svg', 'path'));

        if (type === 'cross' || type === 'list') {
            paths.push(document.createElementNS('http://www.w3.org/2000/svg', 'path'));
        }

        for (var i = 0, len = paths.length; i < len; ++i) {
            var path = paths[i];
            svg.appendChild(path);

            path.setAttributeNS(null, 'd', pathDef[i]);

            var length = path.getTotalLength();
            // Set up the starting positions
            path.style.strokeDasharray = length + ' ' + length;
            if (i === 0) {
                path.style.strokeDashoffset = Math.floor(length) - 1;
            }
            else
                path.style.strokeDashoffset = length;
            // Trigger a layout so styles are calculated & the browser
            // picks up the starting position before animating
            path.getBoundingClientRect();
            // Define our transition
            path.style.transition = path.style.WebkitTransition = path.style.MozTransition = 'stroke-dashoffset ' + animDef.speed + 's ' + animDef.easing + ' ' + i * animDef.speed + 's';
            // Go!
            path.style.strokeDashoffset = '0';
        }
    }

    function reset(el) {
        Array.prototype.slice.call(el.parentNode.querySelectorAll('svg > path')).forEach(function(el) {
            el.parentNode.removeChild(el);
        });
    }

	return [function() {

		return {
			restrict: 'A',

			link: function(scope, element, attrs) {
				initRadioButton(element[0]);

				if (attrs.ngModel != null && attrs.ngModel.length > 0) {
					var dotPos = attrs.ngModel.indexOf('.');

					var watchCollection;
					if (dotPos > -1) {
						watchCollection = attrs.ngModel.substr(0, dotPos);
					} else {
						watchCollection = attrs.ngModel;
					}

					scope.$watchCollection(watchCollection, function(newVal, oldVal) {
						if (attrs.value != undefined){
							existingValue = attrs.value;
							index = scope.$eval(attrs.ngModel);
						} else {
							existingValue = newVal.selectedAnswer;
							index = scope.$eval(attrs.ngValue);
						}

						if (index == existingValue) {
							draw(element[0], 'fill');
						} else {
							reset(element[0]);
						}
					});
				}
			}
		};
	}];
});

<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'
import { connect } from 'react-redux'

// Global module dependencies
import { SettingsPageLayout } from '../../../components/Layout'

// Current module dependencies
import * as WidgetSelectors from '../selectors'

export const SettingsContainer = ({ children, ...rest }) => (
  <SettingsPageLayout>
    {children && React.cloneElement(children, {...rest})}
  </SettingsPageLayout>
)

SettingsContainer.propTypes = {
  children: PropTypes.object,
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired,
  credentials: PropTypes.object.isRequired
}

const mapStateToProps = (state, props) => ({
  widget: WidgetSelectors.getWidget(state, props),
  credentials: state.auth.credentials
})

export default connect(mapStateToProps)(SettingsContainer)
<commit_msg>Fix widgets required mobilization props that injected by container<commit_after>import React, { PropTypes } from 'react'
import { connect } from 'react-redux'

// Global module dependencies
import { SettingsPageLayout } from '../../../components/Layout'

// Parent module dependencies
import * as MobilizationSelectors from '../../mobilizations/selectors'

// Current module dependencies
import * as WidgetSelectors from '../selectors'

export const SettingsContainer = ({ children, ...rest }) => (
  <SettingsPageLayout>
    {children && React.cloneElement(children, {...rest})}
  </SettingsPageLayout>
)

SettingsContainer.propTypes = {
  children: PropTypes.object,
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired
}

const mapStateToProps = (state, props) => ({
  mobilization: MobilizationSelectors.getCurrent(state, props),
  widget: WidgetSelectors.getWidget(state, props)
})

export default connect(mapStateToProps)(SettingsContainer)
<|endoftext|>


<commit_before>var serialport = (require("serialport/package").version.split(".")[0] > 3 ? require("serialport") : require("serialport").SerialPort);
var stream     = require("../stream");
var pdu        = require("modbus-pdu");

function Driver() {

}

Driver.connect = function (device, options) {
	options = options || {};

	var port = new serialport(device || "/dev/ttyS0", {
		baudRate : options.baudRate || 9600,
		dataBits : options.dataBits || 8,
		stopBits : options.stopBits || 1,
		parity   : options.parity   || "none",
		lock     : (typeof options.lock != "undefined" ? !!options.lock : true),
		autoOpen : false
	});

	return {
		attach : function (transport, next) {
			port.on("error", function () {});

			port.open(function (err) {
				if (err) return next(pdu.Exception.error("GatewayPathUnavailable"));

				return next(null, new stream(transport(port, options), options));
			});

			return port;
		}
	}
};

module.exports = Driver;
<commit_msg>serial: allow to pass any option that you can use in serialport<commit_after>var serialport = (require("serialport/package").version.split(".")[0] > 3 ? require("serialport") : require("serialport").SerialPort);
var stream     = require("../stream");
var pdu        = require("modbus-pdu");

function Driver() {

}

Driver.connect = function (device, options) {
	options = options || {};

	options.autoOpen = false;
	options.baudRate = options.baudRate || 9600;
	options.dataBits = options.dataBits || 8;
	options.stopBits = options.stopBits || 1;
	options.parity   = options.parity || "none";

	var port = new serialport(device || "/dev/ttyS0", options);

	return {
		attach : function (transport, next) {
			port.on("error", function () {});

			port.open(function (err) {
				if (err) return next(pdu.Exception.error("GatewayPathUnavailable"));

				return next(null, new stream(transport(port, options), options));
			});

			return port;
		}
	}
};

module.exports = Driver;
<|endoftext|>


<commit_before>var request = require('request');

var ElasticClient = function(options)
{
	options = options || {};
	var host = options.host? options.host : "localhost";
	var port = options.port? options.port : 9200;
	this.url = 'http://' + host + ':' + port,
	this.index = options.index? options.index : 'main';
	this.type = options.type? options.type : 'main';
};

ElasticClient.prototype.status = function(callback) {
	 var requestObj = {
	 	url : this.url + '/_status',
	 	method : 'GET'
	 }

	 this.processRequest(requestObj, callback);
};

ElasticClient.prototype.createIndex = function(name, indexDef, callback) {
	if (!callback && typeof indexDef === 'function') {
		callback = indexDef;
	}

	if(name && typeof name === 'string')
	{
		var requestObj = {
			url : this.url + '/' + name,
			method : 'PUT'
		};

		if(indexDef)
		{
			requestObj.json = indexDef;
		}

		this.processRequest(requestObj, callback);
	}
	else
		throw new Error('name must be not empty string')
};

ElasticClient.prototype.deleteIndex = function(name, callback) {

	if(name && typeof name === 'string')
	{
		var requestObj = {
				url : this.url + '/' + name,
				method : 'DELETE'
		};
		this.processRequest(requestObj,callback);
	}
	else
		throw new Error('name must be not empty string');

};

ElasticClient.prototype.indexStatus = function(name, callback) {
	if(name && typeof name === 'string')
	{
		var url = this.url + '/' + name + '/_status';
		request(url,function(err, response, body){
			if (err) {callback(err, null);}
			else {
				if (response.statusCode == 200) {
					callback(null, body);
				}
				else {
					callback(new Error('HTTP error code:' + response.statusCode ), body);
				}
			}
		});
	}
	else
		throw new Error('name must be not empty string');
};

ElasticClient.prototype.indexObject = function(object, id, callback) {
	if (typeof id === 'function') {
		callback = id;
		id = null;
	}

	var requestObject =  {
		url : this.url + '/' + this.index + '/' + this.type + (id ? '/' + id : ''),
		method : 'POST',
		json : object
	};

	this.processRequest(requestObject, callback);
};

ElasticClient.prototype.searchExactTerm = function(field, term, boost, callback) {
	if (typeof boost === 'function') {
		callback = boost;
		boost = undefined;
	}

	var termQuery = require('./query/termQuery');
	var query = new termQuery(field, term, boost);
	this.query(query,callback);
};

ElasticClient.prototype.searchText = function(field, text, options, callback) {
	if (typeof options === 'function') {
		callback = options;
		options = null;
	}

	var mQuery = require('./query/matchQuery');
	var query = new mQuery(field, text, options);
	this.query(query, callback);
};

ElasticClient.prototype.query = function(query, callback) {
	var requestObject = {
		url : this.url + '/' + this.index + '/_search',
		method : 'POST',
		json : query.toJson()
	}

	this.processRequest(requestObject, callback);
};

ElasticClient.prototype.processRequest = function(requestObject, callback) {
	request(requestObject, function(err, response, body)
		{
			if (err) { callback(err, null); }
			else {
				if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 204) {
					callback(null, body);
				}
				else
				{
					callback(new Error('Http error:' + response.statusCode), body);
				}
			}
		});
};

exports = module.exports;
exports.ElasticClient = ElasticClient;
<commit_msg>Add analyze function for split phrase to tokens<commit_after>var request = require('request');

var ElasticClient = function(options)
{
	options = options || {};
	var host = options.host? options.host : "localhost";
	var port = options.port? options.port : 9200;
	this.url = 'http://' + host + ':' + port,
	this.index = options.index? options.index : 'main';
	this.type = options.type? options.type : 'main';
};

ElasticClient.prototype.status = function(callback) {
	 var requestObj = {
	 	url : this.url + '/_status',
	 	method : 'GET'
	 }

	 this.processRequest(requestObj, callback);
};

ElasticClient.prototype.createIndex = function(name, indexDef, callback) {
	if (!callback && typeof indexDef === 'function') {
		callback = indexDef;
	}

	if(name && typeof name === 'string')
	{
		var requestObj = {
			url : this.url + '/' + name,
			method : 'PUT'
		};

		if(indexDef)
		{
			requestObj.json = indexDef;
		}

		this.processRequest(requestObj, callback);
	}
	else
		throw new Error('name must be not empty string')
};

ElasticClient.prototype.deleteIndex = function(name, callback) {

	if(name && typeof name === 'string')
	{
		var requestObj = {
				url : this.url + '/' + name,
				method : 'DELETE'
		};
		this.processRequest(requestObj,callback);
	}
	else
		throw new Error('name must be not empty string');

};

ElasticClient.prototype.indexStatus = function(name, callback) {
	if(name && typeof name === 'string')
	{
		var url = this.url + '/' + name + '/_status';
		request(url,function(err, response, body){
			if (err) {callback(err, null);}
			else {
				if (response.statusCode == 200) {
					callback(null, body);
				}
				else {
					callback(new Error('HTTP error code:' + response.statusCode ), body);
				}
			}
		});
	}
	else
		throw new Error('name must be not empty string');
};

ElasticClient.prototype.indexObject = function(object, id, callback) {
	if (typeof id === 'function') {
		callback = id;
		id = null;
	}

	var requestObject =  {
		url : this.url + '/' + this.index + '/' + this.type + (id ? '/' + id : ''),
		method : 'POST',
		json : object
	};

	this.processRequest(requestObject, callback);
};

ElasticClient.prototype.searchExactTerm = function(field, term, boost, callback) {
	if (typeof boost === 'function') {
		callback = boost;
		boost = undefined;
	}

	var termQuery = require('./query/termQuery');
	var query = new termQuery(field, term, boost);
	this.query(query,callback);
};

ElasticClient.prototype.searchText = function(field, text, options, callback) {
	if (typeof options === 'function') {
		callback = options;
		options = null;
	}

	var mQuery = require('./query/matchQuery');
	var query = new mQuery(field, text, options);
	this.query(query, callback);
};

ElasticClient.prototype.query = function(query, callback) {
	var requestObject = {
		url : this.url + '/' + this.index + '/_search',
		method : 'POST',
		json : query.toJson()
	}

	this.processRequest(requestObject, callback);
};

ElasticClient.prototype.processRequest = function(requestObject, callback) {
	request(requestObject, function(err, response, body)
		{
			if (err) { callback(err, null); }
			else {
				if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 204) {
					callback(null, body);
				}
				else
				{
					callback(new Error('Http error:' + response.statusCode), body);
				}
			}
		});
};

ElasticClient.prototype.analyze = function(text, options, callback) {
	debugger;
	if (typeof options === 'function') {
		callback = options;
		options = null;
	}

	var query = '';
	if(options)
	{
		if (options.analyzer) { query += 'analyzer=' + options.analyzer}
		if (options.tokenizer) {
			if (query) { query += '&'}
			query += 'tokenizer=' + options.tokenizer;
		}

		if (options.filter) {
			if(query) { query += '&' }

			query += 'filter=' + options.filter;
		}
	}

	var requestObject = {
		url : this.url + '/_analyze' + (query? '?' + query : ''),
		method : 'GET',
		body : text
	};
	debugger;
	this.processRequest(requestObject, callback);
};

exports = module.exports;
exports.ElasticClient = ElasticClient;
<|endoftext|>


<commit_before>/*
 * Flush stats to ElasticSearch (http://www.elasticsearch.org/)
 *
 * To enable this backend, include 'elastic' in the backends
 * configuration array:
 *
 *   backends: ['./backends/elastic']
 *  (if the config file is in the statsd folder)
 *
 * A sample configuration can be found in exampleElasticConfig.js
 *
 * This backend supports the following config options:
 *
 *   host:            hostname or IP of ElasticSearch server
 *   port:            port of Elastic Search Server
 *   path:            http path of Elastic Search Server (default: '/')
 *   indexPrefix:     Prefix of the dynamic index to be created (default: 'statsd')
 *   indexTimestamp:  Timestamping format of the index, either "year", "month", "day", or "hour"
 *   indexType:       The dociment type of the saved stat (default: 'stat')
 */

var net = require('net'),
   util = require('util'),
   http = require('http');
// this will be instantiated to the logger
var lg;
var debug;
var flushInterval;
var elasticHost;
var elasticPort;
var elasticPath;
var elasticIndex;
var elasticIndexTimestamp;
var elasticCountType;
var elasticTimerType;
var elasticUsername;
var elasticPassword;

var elasticStats = {};

var es_bulk_insert = function elasticsearch_bulk_insert(listCounters, listTimers, listTimerData, listGaugeData) {

      var renderKV = function(k, v) {
        if (k === '@timestamp') {
          var s = new Date(v).toISOString();
          return '"'+k+'":"'+s+'"';
        } else if (k === 'val') {
          return '"'+k+'":'+v;
        } else {
          return '"'+k+'":"'+v+'"';
        }
      };

      var indexDate = new Date();

      var statsdIndex = elasticIndex + '-' + indexDate.getUTCFullYear()

      if (elasticIndexTimestamp == 'month' || elasticIndexTimestamp == 'day' || elasticIndexTimestamp == 'hour'){
        var indexMo = indexDate.getUTCMonth() +1;
        if (indexMo < 10) {
            indexMo = '0'+indexMo;
        }
        statsdIndex += '.' + indexMo;
      }

      if (elasticIndexTimestamp == 'day' || elasticIndexTimestamp == 'hour'){
        var indexDt = indexDate.getUTCDate();
        if (indexDt < 10) {
            indexDt = '0'+indexDt;
        }
        statsdIndex += '.' +  indexDt;
      }

      if (elasticIndexTimestamp == 'hour'){
        var indexDt = indexDate.getUTCHours();
        if (indexDt < 10) {
            indexDt = '0'+indexDt;
        }
        statsdIndex += '.' +  indexDt;
      }

      var payload = '';
      for (key in listCounters) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticCountType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listCounters[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listCounters[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listCounters[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }
      for (key in listTimers) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticTimerType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listTimers[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listTimers[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listTimers[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }
      for (key in listTimerData) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticTimerDataType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listTimerData[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listTimerData[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listTimerData[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }
      for (key in listGaugeData) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticGaugeDataType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listGaugeData[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listGuageData[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listGaugeData[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }

      var optionsPost = {
        host: elasticHost,
        port: elasticPort,
        path: elasticPath + statsdIndex + '/' + '/_bulk',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Content-Length': payload.length
        }
      };

      if(elasticUsername && elasticPassword) {
          optionsPost.auth = elasticUsername + ':' + elasticPassword;
      }

      var req = http.request(optionsPost, function(res) {
          res.on('data', function(d) {
            if (Math.floor(res.statusCode / 100) == 5){
              var errdata = "HTTP " + res.statusCode + ": " + d;
              lg.log('error', errdata);
            }
          });
      }).on('error', function(err) {
          lg.log('error', 'Error with HTTP request, no stats flushed.');
          console.log(err);
      });

      if (debug) {
        lg.log('ES payload:');
        lg.log(payload);
      }
      req.write(payload);
      req.end();
}

var flush_stats = function elastic_flush(ts, metrics) {
  var statString = '';
  var numStats = 0;
  var key;
  var array_counts     = new Array();
  var array_timers     = new Array();
  var array_timer_data = new Array();
  var array_gauges     = new Array();

  ts = ts*1000;
/*
  var gauges = metrics.gauges;
  var pctThreshold = metrics.pctThreshold;
*/

  for (key in metrics.counters) {
    numStats += fm.counters(key, metrics.counters[key], ts, array_counts);
  }

  for (key in metrics.timers) {
    numStats += fm.timers(key, metrics.timers[key], ts, array_timers);
  }

  if (array_timers.length > 0) {
    for (key in metrics.timer_data) {
      fm.timer_data(key, metrics.timer_data[key], ts, array_timer_data);
    }
  }

  for (key in metrics.gauges) {
    numStats += fm.gauges(key, metrics.gauges[key], ts, array_gauges);
  }
  if (debug) {
    lg.log('metrics:');
    lg.log( JSON.stringify(metrics) );
  }

  es_bulk_insert(array_counts, array_timers, array_timer_data, array_gauges);

  if (debug) {
    lg.log("debug", "flushed " + numStats + " stats to ES");
  }
};

var elastic_backend_status = function (writeCb) {
  for (stat in elasticStats) {
    writeCb(null, 'elastic', stat, elasticStats[stat]);
  }
};

exports.init = function elasticsearch_init(startup_time, config, events, logger) {

  debug = config.debug;
  lg = logger;

  var configEs = config.elasticsearch || { };

  elasticHost           = configEs.host           || 'localhost';
  elasticPort           = configEs.port           || 9200;
  elasticPath           = configEs.path           || '/';
  elasticIndex          = configEs.indexPrefix    || 'statsd';
  elasticIndexTimestamp = configEs.indexTimestamp || 'day';
  elasticCountType      = configEs.countType      || 'counter';
  elasticTimerType      = configEs.timerType      || 'timer';
  elasticTimerDataType  = configEs.timerDataType  || elasticTimerType + '_stats';
  elasticGaugeDataType  = configEs.gaugeDataType  || 'gauge';
  elasticFormatter      = configEs.formatter      || 'default_format';
  elasticUsername       = configEs.username       || undefined;
  elasticPassword       = configEs.password       || undefined;

  fm   = require('./' + elasticFormatter + '.js')
  if (debug) {
    lg.log("debug", "loaded formatter " + elasticFormatter);
  }

  if (fm.init) {
    fm.init(configEs);
  }
  flushInterval         = config.flushInterval;

  elasticStats.last_flush = startup_time;
  elasticStats.last_exception = startup_time;

  events.on('flush', flush_stats);
  events.on('status', elastic_backend_status);

  return true;
};

<commit_msg>Don't quote number values for ES date parsing<commit_after>/*
 * Flush stats to ElasticSearch (http://www.elasticsearch.org/)
 *
 * To enable this backend, include 'elastic' in the backends
 * configuration array:
 *
 *   backends: ['./backends/elastic']
 *  (if the config file is in the statsd folder)
 *
 * A sample configuration can be found in exampleElasticConfig.js
 *
 * This backend supports the following config options:
 *
 *   host:            hostname or IP of ElasticSearch server
 *   port:            port of Elastic Search Server
 *   path:            http path of Elastic Search Server (default: '/')
 *   indexPrefix:     Prefix of the dynamic index to be created (default: 'statsd')
 *   indexTimestamp:  Timestamping format of the index, either "year", "month", "day", or "hour"
 *   indexType:       The dociment type of the saved stat (default: 'stat')
 */

var net = require('net'),
   util = require('util'),
   http = require('http');
// this will be instantiated to the logger
var lg;
var debug;
var flushInterval;
var elasticHost;
var elasticPort;
var elasticPath;
var elasticIndex;
var elasticIndexTimestamp;
var elasticCountType;
var elasticTimerType;
var elasticUsername;
var elasticPassword;

var elasticStats = {};

var es_bulk_insert = function elasticsearch_bulk_insert(listCounters, listTimers, listTimerData, listGaugeData) {

      var renderKV = function(k, v) {
        if (typeof v == 'number') {
          return '"'+k+'":'+v;
        }
        return '"'+k+'":"'+v+'"';
        /*
        if (k === '@timestamp') {
          var s = new Date(v).toISOString();
          return '"'+k+'":"'+s+'"';
        } else if (k === 'val') {
          return '"'+k+'":'+v;
        } else {
          return '"'+k+'":"'+v+'"';
        }
        */
      };

      var indexDate = new Date();

      var statsdIndex = elasticIndex + '-' + indexDate.getUTCFullYear()

      if (elasticIndexTimestamp == 'month' || elasticIndexTimestamp == 'day' || elasticIndexTimestamp == 'hour'){
        var indexMo = indexDate.getUTCMonth() +1;
        if (indexMo < 10) {
            indexMo = '0'+indexMo;
        }
        statsdIndex += '.' + indexMo;
      }

      if (elasticIndexTimestamp == 'day' || elasticIndexTimestamp == 'hour'){
        var indexDt = indexDate.getUTCDate();
        if (indexDt < 10) {
            indexDt = '0'+indexDt;
        }
        statsdIndex += '.' +  indexDt;
      }

      if (elasticIndexTimestamp == 'hour'){
        var indexDt = indexDate.getUTCHours();
        if (indexDt < 10) {
            indexDt = '0'+indexDt;
        }
        statsdIndex += '.' +  indexDt;
      }

      var payload = '';
      for (key in listCounters) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticCountType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listCounters[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listCounters[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listCounters[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }
      for (key in listTimers) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticTimerType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listTimers[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listTimers[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listTimers[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }
      for (key in listTimerData) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticTimerDataType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listTimerData[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listTimerData[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listTimerData[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }
      for (key in listGaugeData) {
        payload += '{"index":{"_index":"'+statsdIndex+'","_type":"'+elasticGaugeDataType+'"}}'+"\n";
        payload += '{';
        innerPayload = '';
          for (statKey in listGaugeData[key]){
            if (innerPayload) innerPayload += ',';
            innerPayload += renderKV(statKey, listGuageData[key][statKey]);
            //innerPayload += '"'+statKey+'":"'+listGaugeData[key][statKey]+'"';
          }
        payload += innerPayload +'}'+"\n";
      }

      var optionsPost = {
        host: elasticHost,
        port: elasticPort,
        path: elasticPath + statsdIndex + '/' + '/_bulk',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Content-Length': payload.length
        }
      };

      if(elasticUsername && elasticPassword) {
          optionsPost.auth = elasticUsername + ':' + elasticPassword;
      }

      var req = http.request(optionsPost, function(res) {
          res.on('data', function(d) {
            if (Math.floor(res.statusCode / 100) == 5){
              var errdata = "HTTP " + res.statusCode + ": " + d;
              lg.log('error', errdata);
            }
          });
      }).on('error', function(err) {
          lg.log('error', 'Error with HTTP request, no stats flushed.');
          console.log(err);
      });

      if (debug) {
        lg.log('ES payload:');
        lg.log(payload);
      }
      req.write(payload);
      req.end();
}

var flush_stats = function elastic_flush(ts, metrics) {
  var statString = '';
  var numStats = 0;
  var key;
  var array_counts     = new Array();
  var array_timers     = new Array();
  var array_timer_data = new Array();
  var array_gauges     = new Array();

  ts = ts*1000;
/*
  var gauges = metrics.gauges;
  var pctThreshold = metrics.pctThreshold;
*/

  for (key in metrics.counters) {
    numStats += fm.counters(key, metrics.counters[key], ts, array_counts);
  }

  for (key in metrics.timers) {
    numStats += fm.timers(key, metrics.timers[key], ts, array_timers);
  }

  if (array_timers.length > 0) {
    for (key in metrics.timer_data) {
      fm.timer_data(key, metrics.timer_data[key], ts, array_timer_data);
    }
  }

  for (key in metrics.gauges) {
    numStats += fm.gauges(key, metrics.gauges[key], ts, array_gauges);
  }
  if (debug) {
    lg.log('metrics:');
    lg.log( JSON.stringify(metrics) );
  }

  es_bulk_insert(array_counts, array_timers, array_timer_data, array_gauges);

  if (debug) {
    lg.log("debug", "flushed " + numStats + " stats to ES");
  }
};

var elastic_backend_status = function (writeCb) {
  for (stat in elasticStats) {
    writeCb(null, 'elastic', stat, elasticStats[stat]);
  }
};

exports.init = function elasticsearch_init(startup_time, config, events, logger) {

  debug = config.debug;
  lg = logger;

  var configEs = config.elasticsearch || { };

  elasticHost           = configEs.host           || 'localhost';
  elasticPort           = configEs.port           || 9200;
  elasticPath           = configEs.path           || '/';
  elasticIndex          = configEs.indexPrefix    || 'statsd';
  elasticIndexTimestamp = configEs.indexTimestamp || 'day';
  elasticCountType      = configEs.countType      || 'counter';
  elasticTimerType      = configEs.timerType      || 'timer';
  elasticTimerDataType  = configEs.timerDataType  || elasticTimerType + '_stats';
  elasticGaugeDataType  = configEs.gaugeDataType  || 'gauge';
  elasticFormatter      = configEs.formatter      || 'default_format';
  elasticUsername       = configEs.username       || undefined;
  elasticPassword       = configEs.password       || undefined;

  fm   = require('./' + elasticFormatter + '.js')
  if (debug) {
    lg.log("debug", "loaded formatter " + elasticFormatter);
  }

  if (fm.init) {
    fm.init(configEs);
  }
  flushInterval         = config.flushInterval;

  elasticStats.last_flush = startup_time;
  elasticStats.last_exception = startup_time;

  events.on('flush', flush_stats);
  events.on('status', elastic_backend_status);

  return true;
};

<|endoftext|>


<commit_before>'use strict';

var EventEmitter = function EventEmitter(){}
  , proto = EventEmitter.prototype;

/**
 *  Add a listener for an event.
 *
 *  @param event The event name.
 *  @param listener The event listener function.
 */
function addListener(event, listener) {
  this._events = this._events || {};
  this._events[event] = this._events[event] || [];
  this._events[event].push(listener);
  return this;
}

/**
 *  Registers a listener to be invoked once.
 *
 *  @param event The event name.
 *  @param listener The listener function.
 */
function once(event, listener) {
  function g() {
    this.removeListener(event, g);
    listener.apply(this, arguments);
  }
  if(typeof listener === 'function') {
    this.on(event, g);
  }
  return this;
}

/**
 *  Remove all listeners for an event.
 *
 *  @param event The event name.
 */
function removeAllListeners(event) {
  if(event) {
    this._events[event] = [];
  }else{
    this._events = {};
  }
  return this;
}

/**
 *  Remove a listener for an event.
 *
 *  @param event The event name.
 *  @param listener The event listener function.
 */
function removeListener(event, listener) {
  this._events = this._events || {};
  if(event in this._events) {
    this._events[event].splice(this._events[event].indexOf(listener), 1);
  }
  return this;
}

/**
 *  Returns an array of listeners for the specified event.
 */
function listeners(event) {
  this._events = this._events || {};
  return this._events[event] || [];
}

/**
 *  Execute each of the listeners in order with the supplied arguments.
 *
 *  Returns true if event had listeners, false otherwise.
 *
 *  @param event The event name.
 *  @param args... The arguments to pass to event listeners.
 */
function emit(event /* , args... */) {
  this._events = this._events || {};
  var list = this._events[event] || [];
  for(var i = 0; i < list.length; i++){
    list[i].apply(this, Array.prototype.slice.call(arguments, 1))
  }
  return list.length > 0;
}

proto.addListener = addListener;
proto.removeAllListeners = removeAllListeners;
proto.removeListener = removeListener;
proto.listeners = listeners;
proto.emit = emit;
// jquery style alias: one()
proto.once = proto.one = once;

// aliases
proto.on = proto.addListener;
proto.off = proto.removeListener;

module.exports = EventEmitter;
<commit_msg>Tidy once().<commit_after>'use strict';

var EventEmitter = function EventEmitter(){}
  , proto = EventEmitter.prototype;

/**
 *  Add a listener for an event.
 *
 *  @param event The event name.
 *  @param listener The event listener function.
 */
function addListener(event, listener) {
  this._events = this._events || {};
  this._events[event] = this._events[event] || [];
  this._events[event].push(listener);
  return this;
}

/**
 *  Registers a listener to be invoked once.
 *
 *  @param event The event name.
 *  @param listener The listener function.
 */
function once(event, listener) {
  function g() {
    this.removeListener(event, g);
    listener.apply(this, arguments);
  };
  this.on(event, g);
  return this;
}

/**
 *  Remove all listeners for an event.
 *
 *  @param event The event name.
 */
function removeAllListeners(event) {
  if(event) {
    this._events[event] = [];
  }else{
    this._events = {};
  }
  return this;
}

/**
 *  Remove a listener for an event.
 *
 *  @param event The event name.
 *  @param listener The event listener function.
 */
function removeListener(event, listener) {
  this._events = this._events || {};
  if(event in this._events) {
    this._events[event].splice(this._events[event].indexOf(listener), 1);
  }
  return this;
}

/**
 *  Returns an array of listeners for the specified event.
 */
function listeners(event) {
  this._events = this._events || {};
  return this._events[event] || [];
}

/**
 *  Execute each of the listeners in order with the supplied arguments.
 *
 *  Returns true if event had listeners, false otherwise.
 *
 *  @param event The event name.
 *  @param args... The arguments to pass to event listeners.
 */
function emit(event /* , args... */) {
  this._events = this._events || {};
  var list = this._events[event] || [];
  for(var i = 0; i < list.length; i++){
    list[i].apply(this, Array.prototype.slice.call(arguments, 1))
  }
  return list.length > 0;
}

proto.addListener = addListener;
proto.removeAllListeners = removeAllListeners;
proto.removeListener = removeListener;
proto.listeners = listeners;
proto.emit = emit;
// jquery style alias: one()
proto.once = proto.one = once;

// aliases
proto.on = proto.addListener;
proto.off = proto.removeListener;

module.exports = EventEmitter;
<|endoftext|>


<commit_before>module.exports = function (sails) {

	/**
	 * Module dependencies.
	 */

	var util		= require( '../util' ),
	async			= require('async'),
	startServer		= require('./start')(sails),
	bodyParserRetry	= require('./bodyParserRetry')(sails);

	/**
	 * Configure the encapsulated Express server
	 */

	return function loadExpress (cb) {

		// Required to be here due to dynmaic NODE_ENV settings via command line args
		var express = require('express');

		var bodyParserEnabled = util.isFunction(sails.config.express.bodyParser),
			bodyParserRetryEnabled = sails.config.express.retryBodyParserWithJSON,
			bodyParser = sails.config.express.bodyParser();

		// Define housing object for Express in the Sails namespace
		sails.express = {};
		sails.http = sails.express;

		// Create express server
		var app = sails.express.app = express();

		// (required by Express 3.x)
		var usingSSL = ( ( sails.config.serverOptions && sails.config.serverOptions.key && sails.config.serverOptions.cert ) ||
					( sails.config.express && sails.config.express.serverOptions && sails.config.express.serverOptions.key && sails.config.express.serverOptions.cert ));

		// Get the appropriate server creation method for the protocol
		var createServer = usingSSL ? require('https').createServer : require('http').createServer;

		// Use serverOptions if they were specified
		// Manually create http server using Express app instance
		if (sails.config.express.serverOptions) {
			sails.express.server = createServer(sails.config.express.serverOptions, sails.express.app);
		}
		else sails.express.server = createServer(sails.express.app);

		// Set up location of server-side views and their engine
		sails.express.app.set('views', sails.config.paths.views);

		var engine = sails.config.views.engine;
		var depPath = sails.config.appPath + '/node_modules/' + engine;
		var engineModule;
		try {
			engineModule = require(depPath);
		}
		catch (e) {
			if (e) {
				sails.log.error('Your configured server-side view engine (' + engine + ') could not be found.');
				sails.log.error('You\'re probably just missing it as a dependency though.');
				sails.log.error('To install ' + engine + ', run:  `npm install ' + engine + ' --save`');
				throw e;
			}
		}

		app.engine(engine, engineModule.__express);
		sails.express.app.set('view engine', engine);

		// Install Express middleware
		/////////////////////////////////////////////////////////////////

		// When Sails binds routes, bind them to the internal Express router
		sails.on('router:bind', function (route) {

			route = util.clone(route);

			// TODO: Add support for error domains

			app[route.verb || 'all'](route.path, route.target);
		});

		// When Sails unbinds routes, remove them from the internal Express router
		sails.on('router:unbind', function (path, method) {

			var newRoutes = [];
			util.each(app.routes[method], function(expressRoute) {
				if (expressRoute.path != path) {
					newRoutes.push(expressRoute);
				}
			});
			app.routes[method] = newRoutes;

		});

		// When Sails is ready, start the express server
		sails.on('ready', startServer);

		// Use the specified cookieParser
		var cookieParser = sails.config.express.cookieParser;
		var sessionSecret = sails.config.session.secret;
		if (util.isFunction(cookieParser)) {
			app.use(cookieParser(sessionSecret));
			if (sails.config.environment === 'development') {
				sails.log.verbose('Using secret: '+sessionSecret+' in cookie parser');
			}
		}

		// Connect session to express
		app.use(express.session(sails.config.session));

		// Limit file uploads per route
		// pre-calculate regexp for performance
		var expresstUtils = require('../../node_modules/express/lib/utils.js');
		var limitedRoutes = [];
		for (var key in sails.config.routes) {
			var route = sails.config.routes[key];
			if (typeof route === 'object' && route.uploadLimit) {
				limitedRoutes.push({matcher: expresstUtils.pathRegexp(key), limit: route.uploadLimit});
			}
		}

		app.use(function(req, res, next) {

			// Limit upload based on route
			for (var key in limitedRoutes){
				var match = limitedRoutes[key].matcher.exec(req.url);
				if(match) {
					return express.limit(limitedRoutes[key].limit)(req, res, next);
				}

			}

			// default to a limit of 10mb
			return express.limit('10mb')(req, res, next);
		});

		// Use body parser, if enabled
		if (bodyParserEnabled) {
			app.use(bodyParser);

			app.use(function handleBodyParserError (err, req, res, next) {

				// Add key middleware
				if (sails.config.hooks.request) {
					sails._mixinLocals(req,res);
					sails._mixinResError(req,res);
					sails._mixinServerMetadata(req,res);
					sails._mixinReqQualifiers(req, res);
				}
				if (sails.config.hooks.views) {
					sails._mixinResView(req,res, function unused () {
						next('Unable to parse HTTP body :: ' + util.inspect(err));
					});
				}

				// Since an error occurred with the body parser,
				// we need to pick up the middleware necessary
				// to serve the error route which we would have
				// gotten in the router and keep going
				next('Unable to parse HTTP body :: ' + util.inspect(err));
			});

			// Retry body parser to try and force JSON, if enabled
			if (bodyParserRetryEnabled) {
				app.use(bodyParserRetry);
			}

		}

		// Use CSRF middleware if enabled
		if(sails.config.csrf){

			// Require CSRF token for non-GET requests
			app.use(express.csrf());

			// Pass csrf token to templates via locals
			app.use(function(req, res, next){
				res.locals._csrf = req.session._csrf;
				next();
			});
		}

		// Allow full REST simulation for clients which don't support it natively
		// (by using _method parameter)
		if (sails.config.express.methodOverride) {
			app.use(sails.config.express.methodOverride());
		}

		// Allow usage of custom express middleware
		// Must be before the router
		if (sails.config.express.customMiddleware) {
			sails.config.express.customMiddleware(app);
		}

		// Add powered-by Sails header
		app.use(function(req, res, next) {
			res.header('X-Powered-By', 'Sails <sailsjs.org>');
			next();
		});

		// Set up express router
		// Route last so all the middleware gets called first
		sails.log.verbose('Using Express router...');

		// Bind static routes and blueprints
		app.use(app.router);

		// Configure flat file server
		// Bind static files AFTER routing
		sails.log.verbose('Configuring express.static flat-file middleware...');
		var flatFileServer = express['static'](sails.config.paths['public'], {
			maxAge: sails.config.cache.maxAge
		});
		sails.express.app.use(flatFileServer);
		app.use(express.favicon());

		// Make some MIME type exceptions
		express['static'].mime.define({
			'application/font-woff': ['woff']
		});

		// Wait until everything else is done,
		// then bind configured 404 behavior
		app.use(sails.config[404]);

		// When Sails is finished routing ALL routes (including implicit routes)
		// add our default error handler
		app.use(sails.config[500]);

		return cb();

	};

};
<commit_msg>added CORES support via route config<commit_after>module.exports = function (sails) {

	/**
	 * Module dependencies.
	 */

	var util		= require( '../util' ),
	async			= require('async'),
	startServer		= require('./start')(sails),
	bodyParserRetry	= require('./bodyParserRetry')(sails);

	/**
	 * Configure the encapsulated Express server
	 */

	return function loadExpress (cb) {

		// Required to be here due to dynmaic NODE_ENV settings via command line args
		var express = require('express'),
			expresstUtils = require('../../node_modules/express/lib/utils.js');

		var bodyParserEnabled = util.isFunction(sails.config.express.bodyParser),
			bodyParserRetryEnabled = sails.config.express.retryBodyParserWithJSON,
			bodyParser = sails.config.express.bodyParser();

		// Define housing object for Express in the Sails namespace
		sails.express = {};
		sails.http = sails.express;

		// Create express server
		var app = sails.express.app = express();

		// (required by Express 3.x)
		var usingSSL = ( ( sails.config.serverOptions && sails.config.serverOptions.key && sails.config.serverOptions.cert ) ||
					( sails.config.express && sails.config.express.serverOptions && sails.config.express.serverOptions.key && sails.config.express.serverOptions.cert ));

		// Get the appropriate server creation method for the protocol
		var createServer = usingSSL ? require('https').createServer : require('http').createServer;

		// Use serverOptions if they were specified
		// Manually create http server using Express app instance
		if (sails.config.express.serverOptions) {
			sails.express.server = createServer(sails.config.express.serverOptions, sails.express.app);
		}
		else sails.express.server = createServer(sails.express.app);

		// Set up location of server-side views and their engine
		sails.express.app.set('views', sails.config.paths.views);

		var engine = sails.config.views.engine;
		var depPath = sails.config.appPath + '/node_modules/' + engine;
		var engineModule;
		try {
			engineModule = require(depPath);
		}
		catch (e) {
			if (e) {
				sails.log.error('Your configured server-side view engine (' + engine + ') could not be found.');
				sails.log.error('You\'re probably just missing it as a dependency though.');
				sails.log.error('To install ' + engine + ', run:  `npm install ' + engine + ' --save`');
				throw e;
			}
		}

		app.engine(engine, engineModule.__express);
		sails.express.app.set('view engine', engine);

		// Install Express middleware
		/////////////////////////////////////////////////////////////////

		// When Sails binds routes, bind them to the internal Express router
		sails.on('router:bind', function (route) {

			route = util.clone(route);

			// TODO: Add support for error domains

			app[route.verb || 'all'](route.path, route.target);
		});

		// When Sails unbinds routes, remove them from the internal Express router
		sails.on('router:unbind', function (path, method) {

			var newRoutes = [];
			util.each(app.routes[method], function(expressRoute) {
				if (expressRoute.path != path) {
					newRoutes.push(expressRoute);
				}
			});
			app.routes[method] = newRoutes;

		});

		// When Sails is ready, start the express server
		sails.on('ready', startServer);

		// Use the specified cookieParser
		var cookieParser = sails.config.express.cookieParser;
		var sessionSecret = sails.config.session.secret;
		if (util.isFunction(cookieParser)) {
			app.use(cookieParser(sessionSecret));
			if (sails.config.environment === 'development') {
				sails.log.verbose('Using secret: '+sessionSecret+' in cookie parser');
			}
		}

		// Connect session to express
		app.use(express.session(sails.config.session));

		// Limit file uploads per route
		// pre-calculate regexp for performance
		var limitedRoutes = [];
		for (var key in sails.config.routes) {
			var route = sails.config.routes[key];
			if (typeof route === 'object' && route.uploadLimit) {
				limitedRoutes.push({matcher: expresstUtils.pathRegexp(key), limit: route.uploadLimit});
			}
		}

		app.use(function(req, res, next) {

			// Limit upload based on route
			for (var key in limitedRoutes){
				var match = limitedRoutes[key].matcher.exec(req.url);
				if(match) {
					return express.limit(limitedRoutes[key].limit)(req, res, next);
				}

			}

			// default to a limit of 10mb
			return express.limit('10mb')(req, res, next);
		});

		// Use body parser, if enabled
		if (bodyParserEnabled) {
			app.use(bodyParser);

			app.use(function handleBodyParserError (err, req, res, next) {

				// Add key middleware
				if (sails.config.hooks.request) {
					sails._mixinLocals(req,res);
					sails._mixinResError(req,res);
					sails._mixinServerMetadata(req,res);
					sails._mixinReqQualifiers(req, res);
				}
				if (sails.config.hooks.views) {
					sails._mixinResView(req,res, function unused () {
						next('Unable to parse HTTP body :: ' + util.inspect(err));
					});
				}

				// Since an error occurred with the body parser,
				// we need to pick up the middleware necessary
				// to serve the error route which we would have
				// gotten in the router and keep going
				next('Unable to parse HTTP body :: ' + util.inspect(err));
			});

			// Retry body parser to try and force JSON, if enabled
			if (bodyParserRetryEnabled) {
				app.use(bodyParserRetry);
			}

		}

		// Use CSRF middleware if enabled
		if(sails.config.csrf){

			// Require CSRF token for non-GET requests
			app.use(express.csrf());

			// Pass csrf token to templates via locals
			app.use(function(req, res, next){
				res.locals._csrf = req.session._csrf;
				next();
			});
		}

		// Use CORES if set per route
		var coresRoutes = [];
		for (var key in sails.config.routes) {
			var route = sails.config.routes[key];
			if (typeof route === 'object' && route.cores) {
			  	if (typeof route.cores === 'boolean') {
      				route.cores = '*';
				}
				coresRoutes.push({matcher: expresstUtils.pathRegexp(key), origin: route.cores});
			}
		}

		app.use(function(req, res, next) {

			// Set CORES header based on route
			for (var key in coresRoutes){
				var match = coresRoutes[key].matcher.exec(req.url);
				if(match) {
				  res.setHeader('Access-Control-Allow-Origin', coresRoutes[key].origin);
				  return next();
				}

			}

			next();
		});

		// Allow full REST simulation for clients which don't support it natively
		// (by using _method parameter)
		if (sails.config.express.methodOverride) {
			app.use(sails.config.express.methodOverride());
		}

		// Allow usage of custom express middleware
		// Must be before the router
		if (sails.config.express.customMiddleware) {
			sails.config.express.customMiddleware(app);
		}

		// Add powered-by Sails header
		app.use(function(req, res, next) {
			res.header('X-Powered-By', 'Sails <sailsjs.org>');
			next();
		});

		// Set up express router
		// Route last so all the middleware gets called first
		sails.log.verbose('Using Express router...');

		// Bind static routes and blueprints
		app.use(app.router);

		// Configure flat file server
		// Bind static files AFTER routing
		sails.log.verbose('Configuring express.static flat-file middleware...');
		var flatFileServer = express['static'](sails.config.paths['public'], {
			maxAge: sails.config.cache.maxAge
		});
		sails.express.app.use(flatFileServer);
		app.use(express.favicon());

		// Make some MIME type exceptions
		express['static'].mime.define({
			'application/font-woff': ['woff']
		});

		// Wait until everything else is done,
		// then bind configured 404 behavior
		app.use(sails.config[404]);

		// When Sails is finished routing ALL routes (including implicit routes)
		// add our default error handler
		app.use(sails.config[500]);

		return cb();

	};

};
<|endoftext|>