<commit_before>'use strict';

var consts = require('../../constants');
var es = require('event-stream');
var sgvdata = require('sgvdata');

/**********\
 * Entries
\**********/
function configure (app, wares, ctx) {
  var entries = ctx.entries;
  var express = require('express'),
      api = express.Router( )
    ;

    // invoke common middleware
    api.use(wares.sendJSONStatus);
    // text body types get handled as raw buffer stream
    api.use(wares.bodyParser.raw());
    // json body types get handled as parsed json
    api.use(wares.bodyParser.json());
    // shortcut to use extension to specify output content-type
    // api.use(require('express-extension-to-accept')([
    api.use(wares.extensions([
      'json', 'svg', 'csv', 'txt', 'png', 'html', 'tsv'
    ]));
    // also support url-encoded content-type
    api.use(wares.bodyParser.urlencoded({ extended: true }));

    function force_typed_data (opts) {
      function sync (data, next) {
        if (data.type !== opts.type) {
          console.warn('BAD DATA TYPE, setting', data.type, 'to', opts.type);
          data.type = opts.type;
        }
        next(null, data);
      }
      return es.map(sync);
    }

    // Middleware to format any response involving entries.
    function format_entries (req, res) {
      var type_params = {
        type: (req.query && req.query.find && req.query.find.type
            && req.query.find.type !== req.params.model)
            ? req.query.find.type : req.params.model
      };
      var output = es.readArray(res.entries || [ ]);
      if (res.entries_err) {
        return res.sendJSONStatus(res, consts.HTTP_INTERNAL_ERROR, 'Mongo Error', res.entries_err);
      }
      return res.format({
        text: function ( ) {
          es.pipeline(output, sgvdata.format( ), res);
        },
        json: function ( ) {
          es.pipeline(output, force_typed_data(type_params), entries.map( ), es.writeArray(function (err, out) {
            res.json(out);
          }));
        }
      });
    }

    // middleware to process "uploads" of sgv data
    function insert_entries (req, res, next) {
      // list of incoming records
      var incoming = [ ];
      // Potentially a single json encoded body.
      // This can happen from either an url-encoded or json content-type.
      if ('date' in req.body) {
        // add it to the incoming list
        incoming.push(req.body);
      }
      // potentially a list of json entries
      if (req.body.length) {
        // add them to the list
        incoming = incoming.concat(req.body);
      }

      /*
       * inputs -> <ReadableStream>
       * in node, pipe is the most interoperable interface
       * inputs returns a readable stream representing all the potential
       * records from the HTTP body.
       * Most content-types are handled by express middeware.
       * However, text/* types are given to us as a raw buffer, this
       * function switches between these two variants to find the
       * correct input stream.
       * stream, so use svgdata to handle those.
       * The inputs stream always emits sgv json objects.
       */
      function inputs ( ) {
        var input;
        // handle all text types
        if (req.is('text/*')) {
          // re-use the svgdata parsing stream
          input = es.pipeline(req, sgvdata.parse( ));
          return input;
        }
        // use established list
        return es.readArray(incoming);
      }

      // return a writable persistent storage stream
      function persist (fn) {
        if (req.persist_entries) {
          // store everything
          return entries.persist(fn);
        }
        // support a preview mode, just lint everything
        return es.pipeline(entries.map( ), es.writeArray(fn));
      }

      // store results and move to the next middleware
      function done (err, result) {
        res.entries = result;
        res.entries_err = err;
        return next( );
      }

      // pipe everything to persistent storage
      // when finished, pass to the next piece of middleware
      es.pipeline(inputs( ), persist(done));
    }

    function prepReqModel(req, model) {
      var find = { };
      switch (model) {
        case 'treatments':
        case 'devicestatus':
          //TODO: profile not working now, maybe profiles are special
          //case 'profile':
          req.model = ctx[model];
          break;

        case 'meter':
        case 'mbg':
          find.type = 'mbg';
          req.model = ctx.entries;
          break;
        case 'cal':
          find.type = 'cal';
          req.model = ctx.entries;
          break;
        case 'sensor':
          find.type = 'sensor';
          req.model = ctx.entries;
          break;
        case 'sgv':
          find.type = 'sgv';
          req.model = ctx.entries;
          break;
        default:
          req.model = ctx.entries;
          break;
      }

      if (!req.query.find) {
        req.query.find = find;
      } else {
        req.query.find.type = find.type;
      }
    }

    api.param('model', function (req, res, next, model) {
      prepReqModel(req, model);
      next( );
    });

    api.get('/entries/current', function(req, res, next) {
      //assume sgv
      req.params.model = 'sgv';
      entries.list({count: 1}, function(err, records) {
        res.entries = records;
        res.entries_err = err;
        return next( );
      });
    }, format_entries);

    // Fetch one entry by id
    api.get('/entries/:id', function(req, res, next) {
      var ID_PATTERN = /^[a-f\d]{24}$/;
      if (ID_PATTERN.test(req.params.id)) {
        //assume sgv
        req.params.model = 'sgv';
        entries.getEntry(req.params.id, function(err, entry) {
          res.entries = [entry];
          res.entries_err = err;
          next();
        });
      } else {
        //TODO: /entries/:id is blocking /entries/:model
        req.params.model = req.params.id;
        prepReqModel(req, req.params.model);
        query_models(req, res, next);
      }
    }, format_entries);

    api.get('/entries/:model', query_models, format_entries);
    api.get('/entries', query_models, format_entries);

    function query_models (req, res, next) {
      // If "?count=" is present, use that number to decided how many to return.
      if (!req.model) {
        req.model = ctx.entries;
      }
      var query = req.query;
      if (!query.count) { query.count = 10 }
      req.model.list(query, function(err, entries) {
        res.entries = entries;
        res.entries_err = err;
        return next( );
      });
    }

    // Allow previewing your post content, just echos everything you
    // posted back out.
    api.post('/entries/preview', function (req, res, next) {
      req.persist_entries = false;
      next( );
    }, insert_entries, format_entries);

    if (app.enabled('api')) {
      // Create and store new sgv entries
      api.post('/entries/', wares.verifyAuthorization, function (req, res, next) {
        req.persist_entries = true;
        next( );
      }, insert_entries, format_entries);
    }

    return api;
}
module.exports = configure;
<commit_msg>remove false warning<commit_after>'use strict';

var consts = require('../../constants');
var es = require('event-stream');
var sgvdata = require('sgvdata');

/**********\
 * Entries
\**********/
function configure (app, wares, ctx) {
  var entries = ctx.entries;
  var express = require('express'),
      api = express.Router( )
    ;

    // invoke common middleware
    api.use(wares.sendJSONStatus);
    // text body types get handled as raw buffer stream
    api.use(wares.bodyParser.raw());
    // json body types get handled as parsed json
    api.use(wares.bodyParser.json());
    // shortcut to use extension to specify output content-type
    // api.use(require('express-extension-to-accept')([
    api.use(wares.extensions([
      'json', 'svg', 'csv', 'txt', 'png', 'html', 'tsv'
    ]));
    // also support url-encoded content-type
    api.use(wares.bodyParser.urlencoded({ extended: true }));

    function force_typed_data (opts) {
      function sync (data, next) {
        if (data.type !== opts.type) {
          data.type = opts.type;
        }
        next(null, data);
      }
      return es.map(sync);
    }

    // Middleware to format any response involving entries.
    function format_entries (req, res) {
      var type_params = {
        type: (req.query && req.query.find && req.query.find.type
            && req.query.find.type !== req.params.model)
            ? req.query.find.type : req.params.model
      };
      var output = es.readArray(res.entries || [ ]);
      if (res.entries_err) {
        return res.sendJSONStatus(res, consts.HTTP_INTERNAL_ERROR, 'Mongo Error', res.entries_err);
      }
      return res.format({
        text: function ( ) {
          es.pipeline(output, sgvdata.format( ), res);
        },
        json: function ( ) {
          es.pipeline(output, force_typed_data(type_params), entries.map( ), es.writeArray(function (err, out) {
            res.json(out);
          }));
        }
      });
    }

    // middleware to process "uploads" of sgv data
    function insert_entries (req, res, next) {
      // list of incoming records
      var incoming = [ ];
      // Potentially a single json encoded body.
      // This can happen from either an url-encoded or json content-type.
      if ('date' in req.body) {
        // add it to the incoming list
        incoming.push(req.body);
      }
      // potentially a list of json entries
      if (req.body.length) {
        // add them to the list
        incoming = incoming.concat(req.body);
      }

      /*
       * inputs -> <ReadableStream>
       * in node, pipe is the most interoperable interface
       * inputs returns a readable stream representing all the potential
       * records from the HTTP body.
       * Most content-types are handled by express middeware.
       * However, text/* types are given to us as a raw buffer, this
       * function switches between these two variants to find the
       * correct input stream.
       * stream, so use svgdata to handle those.
       * The inputs stream always emits sgv json objects.
       */
      function inputs ( ) {
        var input;
        // handle all text types
        if (req.is('text/*')) {
          // re-use the svgdata parsing stream
          input = es.pipeline(req, sgvdata.parse( ));
          return input;
        }
        // use established list
        return es.readArray(incoming);
      }

      // return a writable persistent storage stream
      function persist (fn) {
        if (req.persist_entries) {
          // store everything
          return entries.persist(fn);
        }
        // support a preview mode, just lint everything
        return es.pipeline(entries.map( ), es.writeArray(fn));
      }

      // store results and move to the next middleware
      function done (err, result) {
        res.entries = result;
        res.entries_err = err;
        return next( );
      }

      // pipe everything to persistent storage
      // when finished, pass to the next piece of middleware
      es.pipeline(inputs( ), persist(done));
    }

    function prepReqModel(req, model) {
      var find = { };
      switch (model) {
        case 'treatments':
        case 'devicestatus':
          //TODO: profile not working now, maybe profiles are special
          //case 'profile':
          req.model = ctx[model];
          break;

        case 'meter':
        case 'mbg':
          find.type = 'mbg';
          req.model = ctx.entries;
          break;
        case 'cal':
          find.type = 'cal';
          req.model = ctx.entries;
          break;
        case 'sensor':
          find.type = 'sensor';
          req.model = ctx.entries;
          break;
        case 'sgv':
          find.type = 'sgv';
          req.model = ctx.entries;
          break;
        default:
          req.model = ctx.entries;
          break;
      }

      if (!req.query.find) {
        req.query.find = find;
      } else {
        req.query.find.type = find.type;
      }
    }

    api.param('model', function (req, res, next, model) {
      prepReqModel(req, model);
      next( );
    });

    api.get('/entries/current', function(req, res, next) {
      //assume sgv
      req.params.model = 'sgv';
      entries.list({count: 1}, function(err, records) {
        res.entries = records;
        res.entries_err = err;
        return next( );
      });
    }, format_entries);

    // Fetch one entry by id
    api.get('/entries/:id', function(req, res, next) {
      var ID_PATTERN = /^[a-f\d]{24}$/;
      if (ID_PATTERN.test(req.params.id)) {
        //assume sgv
        req.params.model = 'sgv';
        entries.getEntry(req.params.id, function(err, entry) {
          res.entries = [entry];
          res.entries_err = err;
          next();
        });
      } else {
        //TODO: /entries/:id is blocking /entries/:model
        req.params.model = req.params.id;
        prepReqModel(req, req.params.model);
        query_models(req, res, next);
      }
    }, format_entries);

    api.get('/entries/:model', query_models, format_entries);
    api.get('/entries', query_models, format_entries);

    function query_models (req, res, next) {
      // If "?count=" is present, use that number to decided how many to return.
      if (!req.model) {
        req.model = ctx.entries;
      }
      var query = req.query;
      if (!query.count) { query.count = 10 }
      req.model.list(query, function(err, entries) {
        res.entries = entries;
        res.entries_err = err;
        return next( );
      });
    }

    // Allow previewing your post content, just echos everything you
    // posted back out.
    api.post('/entries/preview', function (req, res, next) {
      req.persist_entries = false;
      next( );
    }, insert_entries, format_entries);

    if (app.enabled('api')) {
      // Create and store new sgv entries
      api.post('/entries/', wares.verifyAuthorization, function (req, res, next) {
        req.persist_entries = true;
        next( );
      }, insert_entries, format_entries);
    }

    return api;
}
module.exports = configure;
<|endoftext|>


<commit_before>'use strict';

var fs = require("fs");
var utils = require("../../../utils/utils.js");

var BL = {
	model: null,

	/**
	 * List all cluster nodes from cluster
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"listNodes": function (config, soajs, deployer, cbMain) {
		utils.getEnvironment(soajs, BL.model, process.env.SOAJS_ENV || 'dashboard', function (error, envRecord) {
			utils.checkErrorReturn(soajs, cbMain, {config: config, error: error || !envRecord, code: 402}, function () {
				var options = utils.buildDeployerOptions(envRecord, soajs, BL);
				utils.checkErrorReturn(soajs, cbMain, {config: config, error: !options, code: 825}, function () {
					deployer.listNodes(options, function (error, nodes) {
						utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {

							var opts = {
								collection: 'nodes'
							};
							BL.model.findEntry(soajs, opts, function(error, nodesInfo){
								utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
									if(nodesInfo && Object.keys(nodesInfo).length > 0){
										nodes.forEach(function(oneNode){
											oneNode.labels = {
												provider: nodesInfo[oneNode.id]
											};
										});
									}
									return cbMain(null, nodes);
								});
							});
						});
					});
				});
			});
		});
	},

	/**
	 * Add a new node to the cluster, only applicable in case of swarm deployment
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"addNode": function (config, soajs, deployer, cbMain) {
		function getEnv(cb) {
			utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (error, envRecord) {
				utils.checkErrorReturn(soajs, cbMain, {
					config: config,
					error: error || !envRecord,
					code: 402
				}, function () {
					return cb(envRecord);
				});
			});
		}

		function addNodeToSwarm(envRecord, cb) {
			var options = utils.buildDeployerOptions(envRecord, soajs, BL);
			utils.checkErrorReturn(soajs, cbMain, {config: config, error: !options, code: 825}, function () {
				options.params = {
					host: soajs.inputmaskData.host,
					port: soajs.inputmaskData.port,
					role: soajs.inputmaskData.role
				};

				deployer.addNode(options, function (error) {
					utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
						return cb();
					});
				});
			});
		}

		utils.checkErrorReturn(soajs, cbMain, {
			config: config,
			error: soajs.inputmaskData.env.toLowerCase() !== 'dashboard',
			code: 818
		}, function () {
			getEnv(function (envRecord) {
				addNodeToSwarm(envRecord, function () {
					return cbMain(null, true);
				});
			});
		});
	},

	/**
	 * Remove a node from a cluster
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"removeNode": function (config, soajs, deployer, cbMain) {
		function getEnvRecord(cb) {
			utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (error, envRecord) {
				utils.checkErrorReturn(soajs, cbMain, {
					config: config,
					error: error || !envRecord,
					code: 402
				}, function () {
					return cb(envRecord);
				});
			});
		}

		function removeNodeFromSwarm(envRecord, cb) {
			var options = utils.buildDeployerOptions(envRecord, soajs, BL);
			options.params = {
				id: soajs.inputmaskData.nodeId
			};

			deployer.removeNode(options, function (error) {
				utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, cb);
			});
		}

		utils.checkErrorReturn(soajs, cbMain, {
			config: config,
			error: soajs.inputmaskData.env.toLowerCase() !== 'dashboard',
			code: 818
		}, function () {
			getEnvRecord(function (envRecord) {
				removeNodeFromSwarm(envRecord, function () {
					return cbMain(null, true);
				});
			});
		});
	},

	/**
	 * Update the role or availability of a node (role updates only applicable for swarm deployment)
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"updateNode": function (config, soajs, deployer, cbMain) {
		utils.checkErrorReturn(soajs, cbMain, {
			config: config,
			error: soajs.inputmaskData.env.toLowerCase() !== 'dashboard',
			code: 818
		}, function () {
			utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (error, envRecord) {
				utils.checkErrorReturn(soajs, cbMain, {
					config: config,
					error: error || !envRecord,
					code: 402
				}, function () {
					var options = utils.buildDeployerOptions(envRecord, soajs, BL);
					options.params = {};
					options.params.id = soajs.inputmaskData.nodeId;
					options.params[soajs.inputmaskData.type] = soajs.inputmaskData.value;

					deployer.updateNode(options, function (error) {
						utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
							return cbMain(null, true);
						});
					});
				});
			});
		});
	},

	/**
	 * Add / Update the node tag and specify which provider hosts it.
	 * @param {Object} config
	 * @param {Object} soajs
	 * @param {Callback} cbMain
	 */
	"tagNode": function(config, soajs, cbMain){
		var fields = {};
		fields[soajs.inputmaskData.id] = soajs.inputmaskData.tag;

		var opts = {
			collection: 'nodes',
			conditions: {},
			options: {
				upsert: true,
				safe: true,
				multi: false
			},
			fields: fields
		};
		BL.model.updateEntry(soajs, opts, function(error){
			utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
				return cbMain(null, true);
			});
		});
	}
};

module.exports = {
	"init": function (modelName, cb) {
		var modelPath;

		if (!modelName) {
			return cb(new Error("No Model Requested!"));
		}

		modelPath = __dirname + "/../../../models/" + modelName + ".js";
		return requireModel(modelPath, cb);

		/**
		 * checks if model file exists, requires it and returns it.
		 * @param filePath
		 * @param cb
		 */
		function requireModel(filePath, cb) {
			//check if file exist. if not return error
			fs.exists(filePath, function (exists) {
				if (!exists) {
					return cb(new Error("Requested Model Not Found!"));
				}

				BL.model = require(filePath);
				return cb(null, BL);
			});
		}
	}
};
<commit_msg>bug fix<commit_after>'use strict';

var fs = require("fs");
var utils = require("../../../utils/utils.js");

var BL = {
	model: null,

	/**
	 * List all cluster nodes from cluster
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"listNodes": function (config, soajs, deployer, cbMain) {
		utils.getEnvironment(soajs, BL.model, process.env.SOAJS_ENV || 'dashboard', function (error, envRecord) {
			utils.checkErrorReturn(soajs, cbMain, {config: config, error: error || !envRecord, code: 402}, function () {
				var options = utils.buildDeployerOptions(envRecord, soajs, BL);
				utils.checkErrorReturn(soajs, cbMain, {config: config, error: !options, code: 825}, function () {
					deployer.listNodes(options, function (error, nodes) {
						utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {

							var opts = {
								collection: 'nodes'
							};
							BL.model.findEntry(soajs, opts, function(error, nodesInfo){
								utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
									if(nodesInfo && Object.keys(nodesInfo).length > 0){
										nodes.forEach(function(oneNode){
											oneNode.labels = {
												provider: nodesInfo[oneNode.id]
											};
										});
									}
									return cbMain(null, nodes);
								});
							});
						});
					});
				});
			});
		});
	},

	/**
	 * Add a new node to the cluster, only applicable in case of swarm deployment
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"addNode": function (config, soajs, deployer, cbMain) {
		function getEnv(cb) {
			utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (error, envRecord) {
				utils.checkErrorReturn(soajs, cbMain, {
					config: config,
					error: error || !envRecord,
					code: 402
				}, function () {
					return cb(envRecord);
				});
			});
		}

		function addNodeToSwarm(envRecord, cb) {
			var options = utils.buildDeployerOptions(envRecord, soajs, BL);
			utils.checkErrorReturn(soajs, cbMain, {config: config, error: !options, code: 825}, function () {
				options.params = {
					host: soajs.inputmaskData.host,
					port: soajs.inputmaskData.port,
					role: soajs.inputmaskData.role
				};

				deployer.addNode(options, function (error) {
					utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
						return cb();
					});
				});
			});
		}

		utils.checkErrorReturn(soajs, cbMain, {
			config: config,
			error: soajs.inputmaskData.env.toLowerCase() !== 'dashboard',
			code: 818
		}, function () {
			getEnv(function (envRecord) {
				addNodeToSwarm(envRecord, function () {
					return cbMain(null, true);
				});
			});
		});
	},

	/**
	 * Remove a node from a cluster
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"removeNode": function (config, soajs, deployer, cbMain) {
		function getEnvRecord(cb) {
			utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (error, envRecord) {
				utils.checkErrorReturn(soajs, cbMain, {
					config: config,
					error: error || !envRecord,
					code: 402
				}, function () {
					return cb(envRecord);
				});
			});
		}

		function removeNodeFromSwarm(envRecord, cb) {
			var options = utils.buildDeployerOptions(envRecord, soajs, BL);
			options.params = {
				id: soajs.inputmaskData.nodeId
			};

			deployer.removeNode(options, function (error) {
				utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, cb);
			});
		}

		utils.checkErrorReturn(soajs, cbMain, {
			config: config,
			error: soajs.inputmaskData.env.toLowerCase() !== 'dashboard',
			code: 818
		}, function () {
			getEnvRecord(function (envRecord) {
				removeNodeFromSwarm(envRecord, function () {
					return cbMain(null, true);
				});
			});
		});
	},

	/**
	 * Update the role or availability of a node (role updates only applicable for swarm deployment)
	 *
	 * @param {Object} config
	 * @param {Object} SOAJS
	 * @param {Callback} cbMain
	 */
	"updateNode": function (config, soajs, deployer, cbMain) {
		utils.checkErrorReturn(soajs, cbMain, {
			config: config,
			error: soajs.inputmaskData.env.toLowerCase() !== 'dashboard',
			code: 818
		}, function () {
			utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env, function (error, envRecord) {
				utils.checkErrorReturn(soajs, cbMain, {
					config: config,
					error: error || !envRecord,
					code: 402
				}, function () {
					var options = utils.buildDeployerOptions(envRecord, soajs, BL);
					options.params = {};
					options.params.id = soajs.inputmaskData.nodeId;
					options.params[soajs.inputmaskData.type] = soajs.inputmaskData.value;

					deployer.updateNode(options, function (error) {
						utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
							return cbMain(null, true);
						});
					});
				});
			});
		});
	},

	/**
	 * Add / Update the node tag and specify which provider hosts it.
	 * @param {Object} config
	 * @param {Object} soajs
	 * @param {Callback} cbMain
	 */
	"tagNode": function(config, soajs, cbMain){
		BL.model.findEntry(soajs, {
			collection: 'nodes',
			conditions: {}
		}, function(error, tagRecord){
			utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {

				tagRecord[soajs.inputmaskData.id] = soajs.inputmaskData.tag;

				BL.model.saveEntry(soajs, {
					collection: 'nodes',
					record:tagRecord
				}, function(error){
					utils.checkErrorReturn(soajs, cbMain, {config: config, error: error}, function () {
						return cbMain(null, true);
					});
				});
			});
		});
	}
};

module.exports = {
	"init": function (modelName, cb) {
		var modelPath;

		if (!modelName) {
			return cb(new Error("No Model Requested!"));
		}

		modelPath = __dirname + "/../../../models/" + modelName + ".js";
		return requireModel(modelPath, cb);

		/**
		 * checks if model file exists, requires it and returns it.
		 * @param filePath
		 * @param cb
		 */
		function requireModel(filePath, cb) {
			//check if file exist. if not return error
			fs.exists(filePath, function (exists) {
				if (!exists) {
					return cb(new Error("Requested Model Not Found!"));
				}

				BL.model = require(filePath);
				return cb(null, BL);
			});
		}
	}
};
<|endoftext|>


<commit_before>Games = new Mongo.Collection('games');

var Schemas = {};

Schemas.Games = new SimpleSchema({
	player1: {
		type: String,
		label: 'User ID of player1'
	},
	player2: {
		type: String,
		label: 'User ID of player2'
	},
	gameDate: {
		type: Date,
		label: 'Date of the game'
	},
	scorePlayer1: {
		type: Number,
		label: 'Player1 score',
		min: 0
	},
	scorePlayer2: {
		type: Number,
		label: 'player2 score',
		min: 0
	},
	practiceGame: {
		type: Boolean,
		label: 'Is a practice game'
	}
});

Games.attachSchema(Schemas.Games);

Games.helpers({
	player1Data: function() {
		return Meteor.users.findOne(this.player1);
	},
	player2Data: function() {
		return Meteor.users.findOne(this.player2);
	},
	scoreGap: function() {
		if (this.scorePlayer1 > this.scorePlayer2) {
			return this.scorePlayer1 - this.scorePlayer2;
		} else {
			return this.scorePlayer2 - this.scorePlayer1;
		}
	},
	over10: function() {
		if (this.scorePlayer1 > 10 || this.scorePlayer2 > 10) {
			return true;
		} else {
			return false;
		}
	},
	winner: function() {
		if (this.scorePlayer1 > this.scorePlayer2) {
			return player1;
		} else {
			return player2;
		}
	}
});

Meteor.methods({
	addAGame: function(gameData) {
		var player1Infos = Meteor.users.findOne({ _id: gameData.player1 });
		var player2Infos = Meteor.users.findOne({ _id: gameData.player2 });
		var lastPoints1 = player1Infos.profile.points.pop();
		var lastPoints2 = player2Infos.profile.points.pop();
		var pointsToAdd = 0;
		var pointsToLoose = 0;
		var pointBase = 40;
		var winner = function() {
			if (gameData.scorePlayer1 > gameData.scorePlayer2) {
				return gameData.player1;
			} else {
				return gameData.player2;
			}
		};
		if (lastPoints1 - lastPoints2 < 400 && lastPoints2 - lastPoints1 > -400) {
			if (winner() === gameData.player1) {
				pointsToAdd = Math.round(lastPoints1 + pointBase * (1 - 1 / (1 + Math.pow(10, (lastPoints1 - lastPoints2) / 400))));
				pointsToLoose = Math.round(lastPoints2 - pointBase * (1 - 1 / (1 + Math.pow(10, (lastPoints2 - lastPoints1) / 400))));
				Meteor.users.update({ _id: gameData.player1 }, {
					$push: {
						'profile.points': pointsToAdd
					}
				});
				Meteor.users.update({ _id: gameData.player2 }, {
					$push: {
						'profile.points': pointsToLoose
					}
				});
			} else if (winner() === gameData.player2) {
				pointsToAdd = Math.round(lastPoints2 + pointBase * (1 - 1 / (1 + Math.pow(10, (lastPoints2 - lastPoints1) / 400))));
				pointsToLoose = Math.round(lastPoints1 - pointBase * (1 - 1 / (1 + Math.pow(10, (lastPoints1 - lastPoints2) / 400))));
				Meteor.users.update({ _id: gameData.player2 }, {
					$push: {
						'profile.points': pointsToAdd
					}
				});
				Meteor.users.update({ _id: gameData.player1 }, {
					$push: {
						'profile.points': pointsToLoose
					}
				});
			}
			gameData.practiceGame = false;
			return Games.insert(gameData);
		} else {
			gameData.practiceGame = true;
			return Games.insert(gameData);
		}
	}
});
<commit_msg>Fix method to add a game<commit_after>Games = new Mongo.Collection('games');

var Schemas = {};

Schemas.Games = new SimpleSchema({
	player1: {
		type: String,
		label: 'User ID of player1'
	},
	player2: {
		type: String,
		label: 'User ID of player2'
	},
	gameDate: {
		type: Date,
		label: 'Date of the game'
	},
	scorePlayer1: {
		type: Number,
		label: 'Player1 score',
		min: 0
	},
	scorePlayer2: {
		type: Number,
		label: 'player2 score',
		min: 0
	},
	practiceGame: {
		type: Boolean,
		label: 'Is a practice game'
	}
});

Games.attachSchema(Schemas.Games);

Games.helpers({
	player1Data: function() {
		return Meteor.users.findOne(this.player1);
	},
	player2Data: function() {
		return Meteor.users.findOne(this.player2);
	},
	scoreGap: function() {
		if (this.scorePlayer1 > this.scorePlayer2) {
			return this.scorePlayer1 - this.scorePlayer2;
		} else {
			return this.scorePlayer2 - this.scorePlayer1;
		}
	},
	over10: function() {
		if (this.scorePlayer1 > 10 || this.scorePlayer2 > 10) {
			return true;
		} else {
			return false;
		}
	},
	winner: function() {
		if (this.scorePlayer1 > this.scorePlayer2) {
			return player1;
		} else {
			return player2;
		}
	}
});

Meteor.methods({
	addAGame: function(gameData) {
		var player1Infos = Meteor.users.findOne({ _id: gameData.player1 });
		var player2Infos = Meteor.users.findOne({ _id: gameData.player2 });
		var lastPoints1 = player1Infos.profile.points.pop();
		var lastPoints2 = player2Infos.profile.points.pop();
		var pointsToAdd = 0;
		var pointsToLoose = 0;
		var pointBase = 40;
		var winner = function() {
			if (Number(gameData.scorePlayer1) > Number(gameData.scorePlayer2)) {
				return gameData.player1;
			} else {
				return gameData.player2;
			}
		};
		if (lastPoints1 - lastPoints2 < 400 && lastPoints2 - lastPoints1 > -400) {
			if (winner() === gameData.player1) {
				pointsToAdd = Math.round(lastPoints1 + pointBase * (1 - 1 / (1 + Math.pow(10, (lastPoints1 - lastPoints2) / 400))));
				pointsToLoose = Math.round(lastPoints2 + pointBase * (0 - 1 / (1 + Math.pow(10, (lastPoints2 - lastPoints1) / 400))));
				Meteor.users.update({ _id: gameData.player1 }, {
					$push: {
						'profile.points': pointsToAdd
					}
				});
				Meteor.users.update({ _id: gameData.player2 }, {
					$push: {
						'profile.points': pointsToLoose
					}
				});
			} else if (winner() === gameData.player2) {
				pointsToAdd = Math.round(lastPoints2 + pointBase * (1 - 1 / (1 + Math.pow(10, (lastPoints2 - lastPoints1) / 400))));
				pointsToLoose = Math.round(lastPoints1 + pointBase * (0 - 1 / (1 + Math.pow(10, (lastPoints1 - lastPoints2) / 400))));
				Meteor.users.update({ _id: gameData.player2 }, {
					$push: {
						'profile.points': pointsToAdd
					}
				});
				Meteor.users.update({ _id: gameData.player1 }, {
					$push: {
						'profile.points': pointsToLoose
					}
				});
			}
			gameData.practiceGame = false;
			return Games.insert(gameData);
		} else {
			gameData.practiceGame = true;
			return Games.insert(gameData);
		}
	}
});
<|endoftext|>


<commit_before>Posts = new Mongo.Collection('posts');

Posts.allow({
	update: function(userId, post) { return ownsDocument(userId, post); },
	remove: function(userId, post) { return ownsDocument(userId, post); }
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String
    });

    var postWithSameLink = Posts.findOne({url: postAttributes.url});
    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      }
    }

    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.username,
      submitted: new Date()
    });

    var postId = Posts.insert(post);

    return {
      _id: postId
    };
  }
});<commit_msg>Only allow changing certain fields of posts<commit_after>Posts = new Mongo.Collection('posts');

Posts.allow({
	update: function(userId, post) { return ownsDocument(userId, post); },
	remove: function(userId, post) { return ownsDocument(userId, post); }
});

Posts.deny({
	update: function(userId, post, fieldNames) {
		// may only edit the following two fields:
		return (_.without(fieldNames, 'url', 'title').length > 0);
	}
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String
    });

    var postWithSameLink = Posts.findOne({url: postAttributes.url});
    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      }
    }

    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.username,
      submitted: new Date()
    });

    var postId = Posts.insert(post);

    return {
      _id: postId
    };
  }
});<|endoftext|>


<commit_before>module.exports = function(data, Bot, Config, Helpers) {

  if(data.userID == Bot.id)
    return;

  if(!data)
    throw new Error('\'data\' doesn\'t exist.');

  if(!data.user)
    throw new Error('No username defined');

  if(!data.userID)
    throw new Error('No user id defined.');

  if(!data.channelID)
    throw new Error('No channel id defined.');

  if(!data.rawEvent)
    throw new Error('No \'rawEvent\' defined.');

  if(!Helpers.checkIsCommand(data.message, Config))
    return;

  var key = Helpers.getCommandPart(data.message, '1', Config);

  try {

    Bot.deleteMessage({
      channel: data.channelID,
      messageID: data.rawEvent.d.id
    });

    require('./'+key)(data, Bot, Config, Helpers);

  }catch (e) {

    console.log(e);

    Bot.deleteMessage({
      channel: data.channelID,
      messageID: data.rawEvent.d.id
    });

	Bot.sendMessage({
        'to': data.userID,
        'message': "Désolé, cette commande n'existe pas."
      });

      require('./help')(data, Bot, Config, Helpers);

  }

};
<commit_msg>False update<commit_after>module.exports = function(data, Bot, Config, Helpers) {

  if(data.userID == Bot.id)
    return;

  if(!data)
    throw new Error('\'data\' doesn\'t exist.');

  if(!data.user)
    throw new Error('No username defined');

  if(!data.userID)
    throw new Error('No user id defined.');

  if(!data.channelID)
    throw new Error('No channel id defined.');

  if(!data.rawEvent)
    throw new Error('No \'rawEvent\' defined.');

  if(!Helpers.checkIsCommand(data.message, Config))
    return;

  var key = Helpers.getCommandPart(data.message, '1', Config);

  try {

    Bot.deleteMessage({
      channel: data.channelID,
      messageID: data.rawEvent.d.id
    });

    require('./'+key)(data, Bot, Config, Helpers);

  }catch (e) {

    console.log(e);

    Bot.deleteMessage({
      channel: data.channelID,
      messageID: data.rawEvent.d.id
    });

	Bot.sendMessage({
        'to': data.userID,
        'message': "Désolé, cette commande n'existe pas."
      });

      require('./help')(data, Bot, Config, Helpers);

  }

};
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash')
const chalk = require('chalk')

module.exports = function (client) {
  client
    .command(':practice [lists...]')
    .alias(':p')
    .option('-s --score <score>', 'minimum score of words, default is 0')
    .option('-o --order <order>', 'order of words, if not specify, will keep the default order', ['ASC', 'DESC', 'RANDOM', 'DEFAULT'])
    .option('-n --number <number>', 'maxium number of words, unlimited if not specified')
    .description('practice specified lists of words in selected collection.')
    .validate(function() {
      if (!client.context.collection) return 'no selected collection'
    })
    .action(function(args, callback) {
      try {
        const collection = client.context.collection
        const lists = parseListsInput(args.lists, collection)

        const score = args.options.score || 0
        const order = args.options.order || 'DEFAULT'
        const number = args.options.number

        let selectedWords = {}

        for (let list of lists) {
          Object.assign(selectedWords, collection.filterWords({list: list, score: score}))
        }

        let words = Object.keys(selectedWords)

        if (number) words = words.slice(0, number)

        switch (order) {
          case 'ASC':
            words.sort()
            break;
          case 'DESC':
            words.sort((a, b) => a > b ? -1 : 1)
            break;
          case 'RANDOM':
            words = _.shuffle(words)
            break;
          case 'DEFAULT':
          default:
            break;
        }

        if (!words.length) {
          this.log('No macthed words')
          return callback()
        }
        this.log('-------------------------------------------')
        this.log('Practice Start')
        this.log(`selected lists: ${lists.join(', ')}\nminimum score: ${score}\nin ${order} order`)
        this.log('number of words:', words.length)
        this.log('-------------------------------------------')
        this.log('Enter to see meaning & Type Y/y for knowing the word')
        this.log('Type ABANDON to quit :)')
        this.log('-------------------------------------------')
        this.log('\n')

        startPractice(this, collection, words).then(stats => {
          var seconds = Math.round((stats.end - stats.start)/1000)

          this.log('-------------------------------------------')
          this.log('Practice Stats')
          this.log('number of words:', stats.y + stats.n)
          this.log('time consuming:', seconds < 60 ? seconds + ' s' : Math.round(seconds/60) + ' mins')
          this.log('knew:', stats.y)
          this.log('don\'t know:', stats.n)
          this.log('-------------------------------------------')

          callback()
        })
      } catch (error) {
        this.log(error)
        callback()
      }
    });
}

function startPractice(commandInstance, collection, words) {
  const stats = {
    y: 0,
    n: 0,
    start: new Date()
  }

  function promptWord(index) {
    index = index || 0
    const word = words[index]
    const wordEntity = collection.get(word)

    return commandInstance.prompt([{
      type: 'input',
      name: 'seeMeaning',
      message: `${word} <${wordEntity.score || 0}> `
    }, {
      type: 'input',
      name: 'response',
      message: `${wordEntity.meaning}\n[?]: `
    }]).then(function (answers){
      const response = answers.response || ''

      if (response === 'ABANDON') return

      if (response === word || response.toUpperCase() === 'Y') {
        stats.y++
      } else {
        stats.n++
        collection.increaseScore(word)
        const newWordEnity = collection.get(word)
        commandInstance.log(chalk.red(`[!]: ${word} <${newWordEnity.score || 0}> `))
      }

      if (++index === words.length) return
      return promptWord(index)
    })
  }

  return promptWord()
    .catch(e => console.log('Error happened. Practice will stop', e))
    .then(() => {
      stats.end = new Date()
      return stats
    })
}

function parseListsInput(lists, collection) {
  const listNumbers = collection.getListNumbers()

  if (!lists) return listNumbers

  let parsedLists = []

  for (let list of lists) {
    let parsedList
    if (/^\d+$/.test(list)) {
      parsedList = Number.parseInt(list)
      if (listNumbers.indexOf(parsedList) === -1) {
        throw `${list} is not a valid list`
      }

      parsedLists.push(parsedList)
    } else if (/^\d+-\d+$/.test(list)) {
      // cannot list.split('-').map(Number.parseInt) since map will pass value & index
      parsedList = list.split('-').map(n => Number.parseInt(n))

      if (parsedList[0] > parsedList[1]) {
        throw `${list} is not a valid lists range`
      }

      for (let i = parsedList[0]; i <= parsedList[1]; i++) {
        if (listNumbers.indexOf(i) === -1) {
          throw `${i} in ${list} is not a valid list`
        }
        parsedLists.push(i)
      }
    } else {
      throw `${list} is not a valid input, space separated integer, or hyphen linked integers for range`
    }
  }

  parsedLists = _.uniq(parsedLists)

  return parsedLists
}
<commit_msg>fix bug of number option of practice<commit_after>'use strict';

const _ = require('lodash')
const chalk = require('chalk')

module.exports = function (client) {
  client
    .command(':practice [lists...]')
    .alias(':p')
    .option('-s --score <score>', 'minimum score of words, default is 0')
    .option('-o --order <order>', 'order of words, if not specify, will keep the default order', ['ASC', 'DESC', 'RANDOM', 'DEFAULT'])
    .option('-n --number <number>', 'maxium number of words, unlimited if not specified')
    .description('practice specified lists of words in selected collection.')
    .validate(function() {
      if (!client.context.collection) return 'no selected collection'
    })
    .action(function(args, callback) {
      try {
        const collection = client.context.collection
        const lists = parseListsInput(args.lists, collection)

        const score = args.options.score || 0
        const order = args.options.order || 'DEFAULT'
        const number = args.options.number

        let selectedWords = {}

        for (let list of lists) {
          Object.assign(selectedWords, collection.filterWords({list: list, score: score}))
        }

        let words = Object.keys(selectedWords)

        switch (order) {
          case 'ASC':
            words.sort()
            break;
          case 'DESC':
            words.sort((a, b) => a > b ? -1 : 1)
            break;
          case 'RANDOM':
            words = _.shuffle(words)
            break;
          case 'DEFAULT':
          default:
            break;
        }

        if (number) words = words.slice(0, number)

        if (!words.length) {
          this.log('No macthed words')
          return callback()
        }
        this.log('-------------------------------------------')
        this.log('Practice Start')
        this.log(`selected lists: ${lists.join(', ')}\nminimum score: ${score}\nin ${order} order`)
        this.log('number of words:', words.length)
        this.log('-------------------------------------------')
        this.log('Enter to see meaning & Type Y/y for knowing the word')
        this.log('Type ABANDON to quit :)')
        this.log('-------------------------------------------')
        this.log('\n')

        startPractice(this, collection, words).then(stats => {
          var seconds = Math.round((stats.end - stats.start)/1000)

          this.log('-------------------------------------------')
          this.log('Practice Stats')
          this.log('number of words:', stats.y + stats.n)
          this.log('time consuming:', seconds < 60 ? seconds + ' s' : Math.round(seconds/60) + ' mins')
          this.log('knew:', stats.y)
          this.log('don\'t know:', stats.n)
          this.log('-------------------------------------------')

          callback()
        })
      } catch (error) {
        this.log(error)
        callback()
      }
    });
}

function startPractice(commandInstance, collection, words) {
  const stats = {
    y: 0,
    n: 0,
    start: new Date()
  }

  function promptWord(index) {
    index = index || 0
    const word = words[index]
    const wordEntity = collection.get(word)

    return commandInstance.prompt([{
      type: 'input',
      name: 'seeMeaning',
      message: `${word} <${wordEntity.score || 0}> `
    }, {
      type: 'input',
      name: 'response',
      message: `${wordEntity.meaning}\n[?]: `
    }]).then(function (answers){
      const response = answers.response || ''

      if (response === 'ABANDON') return

      if (response === word || response.toUpperCase() === 'Y') {
        stats.y++
      } else {
        stats.n++
        collection.increaseScore(word)
        const newWordEnity = collection.get(word)
        commandInstance.log(chalk.red(`[!]: ${word} <${newWordEnity.score || 0}> `))
      }

      if (++index === words.length) return
      return promptWord(index)
    })
  }

  return promptWord()
    .catch(e => console.log('Error happened. Practice will stop', e))
    .then(() => {
      stats.end = new Date()
      return stats
    })
}

function parseListsInput(lists, collection) {
  const listNumbers = collection.getListNumbers()

  if (!lists) return listNumbers

  let parsedLists = []

  for (let list of lists) {
    let parsedList
    if (/^\d+$/.test(list)) {
      parsedList = Number.parseInt(list)
      if (listNumbers.indexOf(parsedList) === -1) {
        throw `${list} is not a valid list`
      }

      parsedLists.push(parsedList)
    } else if (/^\d+-\d+$/.test(list)) {
      // cannot list.split('-').map(Number.parseInt) since map will pass value & index
      parsedList = list.split('-').map(n => Number.parseInt(n))

      if (parsedList[0] > parsedList[1]) {
        throw `${list} is not a valid lists range`
      }

      for (let i = parsedList[0]; i <= parsedList[1]; i++) {
        if (listNumbers.indexOf(i) === -1) {
          throw `${i} in ${list} is not a valid list`
        }
        parsedLists.push(i)
      }
    } else {
      throw `${list} is not a valid input, space separated integer, or hyphen linked integers for range`
    }
  }

  parsedLists = _.uniq(parsedLists)

  return parsedLists
}
<|endoftext|>


<commit_before>/*
 * Connect middleware that uses wwwhisper service to authorize visitors.
 * Copyright (C) 2013, 2014 Jan Wrobel <wrr@mixedbit.org>
 *
 * This program is freely distributable under the terms of the
 * Simplified BSD License. See COPYING.
 *
 * The middleware is based on wwwhisper Rack middleware:
 * https://github.com/wrr/rack-wwwhisper Functionality and test cases
 * are identical. The only difference is that the Connect middleware
 * does not attempt to change public caching to private caching for
 * wwwhisper-protected content served over HTTP. Serious wwwhisper
 * deployments need to use HTTPS anyway, and returning correct cache
 * control headers should be better left as a responsibility of the
 * application.
 */

var url = require('url');
var URI = require('URIjs');

var http = null;
var wwwhisper_url = null;
var AUTH_COOKIES_PREFIX = 'wwwhisper';

// Headers that are forwarded to the wwwhisper backend with wwwhisper
// authorization requests (in addition wwwhisper cookies are
// forwarded).
var AUTH_REQUEST_FORWARDED_HEADERS = [
  'Accept', 'Accept-Language'
];

// Headers that are forwarded to the wwwhisper backend with requests
// that are proxied to wwwhisper (wwwhisper admin, wwwhisper login
// resources).
var PROXY_REQUEST_FORWARDED_HEADERS = [
  'Accept', 'Accept-Language', 'Origin', 'X-Csrftoken',
  'X-Requested-With', 'Content-Type', 'Content-Length'
];
var AUTH_COOKIE_REGEXP = new RegExp(AUTH_COOKIES_PREFIX + '-[^;]*(?:;|$)', 'g');

function copy_auth_cookies(req, headers) {
  if (req.headers.hasOwnProperty('cookie')) {
    var cookies = req.headers['cookie'];
    var auth_cookies = cookies.match(AUTH_COOKIE_REGEXP);
    if (auth_cookies !== null) {
      headers['Cookie'] = auth_cookies.join(' ');
    }
  }
}

function copy_headers(req, headers, headers_to_forward) {
  for (var idx in headers_to_forward) {
    var h = headers_to_forward[idx], h_low = h.toLowerCase();
    if (req.headers.hasOwnProperty(h_low)) {
      headers[h] = req.headers[h_low];
    }
  }
}

function sub_request_options(req, method, path, headers_to_forward) {
  var headers = {};
  var scheme;
  copy_headers(req, headers, headers_to_forward);
  copy_auth_cookies(req, headers)

  if (req.connection.encrypted) {
    scheme = 'https';
  } else if (req.headers.hasOwnProperty('x-forwarded-proto')) {
    scheme = req.headers['x-forwarded-proto'];
  } else {
    scheme = 'http';
  }

  headers['Site-Url'] = scheme + '://' + req.headers['host'];
  headers['User-Agent'] = 'node-1.1.1';

  return {
    hostname: wwwhisper_url.hostname,
    port: wwwhisper_url.port,
    path: path,
    auth: wwwhisper_url.auth,
    headers: headers,
    method: method,
  };
}

function should_inject(req, res) {
  var contentType = res.getHeader('content-type');
  return (contentType !== undefined &&
          contentType.indexOf('text/html') !== -1);
}

function inject(callback, data, req, res) {
  var newData = data.toString().replace(
     /(.*)<\/body>/,
    '$1\n');
  callback(null, newData);
}

var injector = require('connect-injector-frk')(should_inject, inject);

function auth_query(queried_path) {
  return '/wwwhisper/auth/api/is-authorized/?path=' + queried_path;
}

function chain(req, res, handlers) {
  var idx = -1;
  function next() {
    idx += 1;
    if (idx === handlers.length) {
      return;
    } else if (idx === handlers.length - 1) {
      handlers[idx]();
    } else {
      handlers[idx](req, res, next);
    }
  }
  next();
}

// To avoid problems with middlewares that do not handle headers
// passed as arguments to the writeHead method. See:
// https://github.com/expressjs/compression/issues/6
// Uses setHeader instead.
function writeHead(res, status, headers) {
  var header;
  for (header in headers) {
    res.setHeader(header, headers[header]);
  }
  res.writeHead(status);
}

function report_error(res, msg) {
  return function() {
    writeHead(res, 500, {'Content-Type': 'text/plain'});
    res.write(msg);
    res.end();
  };
}

function authorized(req, res, next) {
  if (req.url.search(/^\/wwwhisper\//) !== -1) {
    var options = sub_request_options(req, req.method, req.url,
                                      PROXY_REQUEST_FORWARDED_HEADERS);
    var sub_req = http.request(options, function(sub_res) {
      sub_res.setEncoding('utf8');
      writeHead(res, sub_res.statusCode, sub_res.headers);
      sub_res.on('data', function(chunk) {
        res.write(chunk);
      });
      sub_res.on('end', function() {
        res.end();
      });
    });
    // Pipe request body to the sub request.
    req.pipe(sub_req, {end: true});
    sub_req.on('error', report_error(res, 'request to wwwhisper failed'));
  } else {
    next();
  }
}

function normalized_uri(url) {
  return URI(url).normalizePath();
}

function configure() {
  var url_str = process.env.WWWHISPER_URL;
  if  (url_str === undefined) {
    if (process.env.WWWHISPER_DISABLE !== undefined) {
      wwwhisper_url = null;
      return;
    }
    throw new Error(
      'WWWHISPER_URL nor WWWHISPER_DISABLE environment variable set');
  }
  if (!process.version.match('0.1(0|1).*')) {
    throw new Error(
      'wwwhipsper requires node version 0.10 or 0.11');
  }
  wwwhisper_url = url.parse(url_str);
  if (wwwhisper_url.protocol === 'http:') {
    http = require('http');
  } else {
    http = require('https');
  }
  http.globalAgent.maxSockets = 500;

}

/**
 * Initializes wwwhisper middleware.
 *
 * Deployment specific options are configure via environment variables:
 *
 *  WWWHISPER_URL: an address of a wwwhisper service (including basic
 *  auth credentials).
 *  WWWHISPER_DISABLE: useful for a local development environment.
 *
 * An optional inject_logout_iframe param allows to disable injection
 * of a wwwhisper iframe into HTML documents. The iframe contains a
 * current user email and a logout button. If inject_logout_iframe is
 * not passed, it defaults to true.
 *
 * Example usage:
 *   var wwwhisper = require('connect-wwwhisper');
 *   app.use(wwwhisper());
 * or to disable wwwhisper iframe injection:
 *   app.user(wwwhisper(false));
 *
 * Make sure wwwhisper middleware is put before any middleware that
 * writes sensitive responses.
 */
function wwwhisper(inject_logout_iframe) {
  configure();
  if (wwwhisper_url === null) {
    return function wwwhisper_disabled(req, res, next) {
      next();
    };
  }
  if (inject_logout_iframe  === undefined) {
    inject_logout_iframe = true;
  }

  return function is_authorized(req, res, next) {
    // A reason why node <= 0.8.* is not supported is that starting from
    // node 0.10, req is a readable stream that does not emit data until
    // a reader is ready. With node 0.8 req emits 'data' events
    // immediately (req.readable becomes false).
    var uri = normalized_uri(req.url);
    req.url = uri.toString();
    if (req.url.search(/^\/wwwhisper\/auth\//) !== -1) {
      authorized(req, res, next);
    } else {
      var options = sub_request_options(req, 'GET', auth_query(uri.path()),
                                        AUTH_REQUEST_FORWARDED_HEADERS);
      var auth_req = http.request(options, function(auth_res) {
        if (auth_res.statusCode === 200) {
          var user = auth_res.headers['user'];
          if (user !== undefined) {
            req.remoteUser =  user;
            res.setHeader('User', user);
          }
          var call_chain = inject_logout_iframe ? [injector, authorized, next] :
            [authorized, next];
          chain(req, res, call_chain);
        } else {
          writeHead(res, auth_res.statusCode, auth_res.headers);
          auth_res.on('data', function(chunk) {
            res.write(chunk);
          });
          auth_res.on('end', function() {
            res.end();
          });
        }
      });
      auth_req.on('error', report_error(res, 'auth request failed'));
      auth_req.end();
    }
  };
}
module.exports = wwwhisper;
<commit_msg>Fix lint warning<commit_after>/*
 * Connect middleware that uses wwwhisper service to authorize visitors.
 * Copyright (C) 2013, 2014 Jan Wrobel <wrr@mixedbit.org>
 *
 * This program is freely distributable under the terms of the
 * Simplified BSD License. See COPYING.
 *
 * The middleware is based on wwwhisper Rack middleware:
 * https://github.com/wrr/rack-wwwhisper Functionality and test cases
 * are identical. The only difference is that the Connect middleware
 * does not attempt to change public caching to private caching for
 * wwwhisper-protected content served over HTTP. Serious wwwhisper
 * deployments need to use HTTPS anyway, and returning correct cache
 * control headers should be better left as a responsibility of the
 * application.
 */

var url = require('url');
var URI = require('URIjs');

var http = null;
var wwwhisper_url = null;
var AUTH_COOKIES_PREFIX = 'wwwhisper';

// Headers that are forwarded to the wwwhisper backend with wwwhisper
// authorization requests (in addition wwwhisper cookies are
// forwarded).
var AUTH_REQUEST_FORWARDED_HEADERS = [
  'Accept', 'Accept-Language'
];

// Headers that are forwarded to the wwwhisper backend with requests
// that are proxied to wwwhisper (wwwhisper admin, wwwhisper login
// resources).
var PROXY_REQUEST_FORWARDED_HEADERS = [
  'Accept', 'Accept-Language', 'Origin', 'X-Csrftoken',
  'X-Requested-With', 'Content-Type', 'Content-Length'
];
var AUTH_COOKIE_REGEXP = new RegExp(AUTH_COOKIES_PREFIX + '-[^;]*(?:;|$)', 'g');

function copy_auth_cookies(req, headers) {
  if (req.headers.hasOwnProperty('cookie')) {
    var cookies = req.headers['cookie'];
    var auth_cookies = cookies.match(AUTH_COOKIE_REGEXP);
    if (auth_cookies !== null) {
      headers['Cookie'] = auth_cookies.join(' ');
    }
  }
}

function copy_headers(req, headers, headers_to_forward) {
  for (var idx in headers_to_forward) {
    var h = headers_to_forward[idx], h_low = h.toLowerCase();
    if (req.headers.hasOwnProperty(h_low)) {
      headers[h] = req.headers[h_low];
    }
  }
}

function sub_request_options(req, method, path, headers_to_forward) {
  var headers = {};
  var scheme;
  copy_headers(req, headers, headers_to_forward);
  copy_auth_cookies(req, headers);

  if (req.connection.encrypted) {
    scheme = 'https';
  } else if (req.headers.hasOwnProperty('x-forwarded-proto')) {
    scheme = req.headers['x-forwarded-proto'];
  } else {
    scheme = 'http';
  }

  headers['Site-Url'] = scheme + '://' + req.headers['host'];
  headers['User-Agent'] = 'node-1.1.1';

  return {
    hostname: wwwhisper_url.hostname,
    port: wwwhisper_url.port,
    path: path,
    auth: wwwhisper_url.auth,
    headers: headers,
    method: method,
  };
}

function should_inject(req, res) {
  var contentType = res.getHeader('content-type');
  return (contentType !== undefined &&
          contentType.indexOf('text/html') !== -1);
}

function inject(callback, data, req, res) {
  var newData = data.toString().replace(
     /(.*)<\/body>/,
    '$1\n');
  callback(null, newData);
}

var injector = require('connect-injector-frk')(should_inject, inject);

function auth_query(queried_path) {
  return '/wwwhisper/auth/api/is-authorized/?path=' + queried_path;
}

function chain(req, res, handlers) {
  var idx = -1;
  function next() {
    idx += 1;
    if (idx === handlers.length) {
      return;
    } else if (idx === handlers.length - 1) {
      handlers[idx]();
    } else {
      handlers[idx](req, res, next);
    }
  }
  next();
}

// To avoid problems with middlewares that do not handle headers
// passed as arguments to the writeHead method. See:
// https://github.com/expressjs/compression/issues/6
// Uses setHeader instead.
function writeHead(res, status, headers) {
  var header;
  for (header in headers) {
    res.setHeader(header, headers[header]);
  }
  res.writeHead(status);
}

function report_error(res, msg) {
  return function() {
    writeHead(res, 500, {'Content-Type': 'text/plain'});
    res.write(msg);
    res.end();
  };
}

function authorized(req, res, next) {
  if (req.url.search(/^\/wwwhisper\//) !== -1) {
    var options = sub_request_options(req, req.method, req.url,
                                      PROXY_REQUEST_FORWARDED_HEADERS);
    var sub_req = http.request(options, function(sub_res) {
      sub_res.setEncoding('utf8');
      writeHead(res, sub_res.statusCode, sub_res.headers);
      sub_res.on('data', function(chunk) {
        res.write(chunk);
      });
      sub_res.on('end', function() {
        res.end();
      });
    });
    // Pipe request body to the sub request.
    req.pipe(sub_req, {end: true});
    sub_req.on('error', report_error(res, 'request to wwwhisper failed'));
  } else {
    next();
  }
}

function normalized_uri(url) {
  return URI(url).normalizePath();
}

function configure() {
  var url_str = process.env.WWWHISPER_URL;
  if  (url_str === undefined) {
    if (process.env.WWWHISPER_DISABLE !== undefined) {
      wwwhisper_url = null;
      return;
    }
    throw new Error(
      'WWWHISPER_URL nor WWWHISPER_DISABLE environment variable set');
  }
  if (!process.version.match('0.1(0|1).*')) {
    throw new Error(
      'wwwhipsper requires node version 0.10 or 0.11');
  }
  wwwhisper_url = url.parse(url_str);
  if (wwwhisper_url.protocol === 'http:') {
    http = require('http');
  } else {
    http = require('https');
  }
  http.globalAgent.maxSockets = 500;

}

/**
 * Initializes wwwhisper middleware.
 *
 * Deployment specific options are configure via environment variables:
 *
 *  WWWHISPER_URL: an address of a wwwhisper service (including basic
 *  auth credentials).
 *  WWWHISPER_DISABLE: useful for a local development environment.
 *
 * An optional inject_logout_iframe param allows to disable injection
 * of a wwwhisper iframe into HTML documents. The iframe contains a
 * current user email and a logout button. If inject_logout_iframe is
 * not passed, it defaults to true.
 *
 * Example usage:
 *   var wwwhisper = require('connect-wwwhisper');
 *   app.use(wwwhisper());
 * or to disable wwwhisper iframe injection:
 *   app.user(wwwhisper(false));
 *
 * Make sure wwwhisper middleware is put before any middleware that
 * writes sensitive responses.
 */
function wwwhisper(inject_logout_iframe) {
  configure();
  if (wwwhisper_url === null) {
    return function wwwhisper_disabled(req, res, next) {
      next();
    };
  }
  if (inject_logout_iframe  === undefined) {
    inject_logout_iframe = true;
  }

  return function is_authorized(req, res, next) {
    // A reason why node <= 0.8.* is not supported is that starting from
    // node 0.10, req is a readable stream that does not emit data until
    // a reader is ready. With node 0.8 req emits 'data' events
    // immediately (req.readable becomes false).
    var uri = normalized_uri(req.url);
    req.url = uri.toString();
    if (req.url.search(/^\/wwwhisper\/auth\//) !== -1) {
      authorized(req, res, next);
    } else {
      var options = sub_request_options(req, 'GET', auth_query(uri.path()),
                                        AUTH_REQUEST_FORWARDED_HEADERS);
      var auth_req = http.request(options, function(auth_res) {
        if (auth_res.statusCode === 200) {
          var user = auth_res.headers['user'];
          if (user !== undefined) {
            req.remoteUser =  user;
            res.setHeader('User', user);
          }
          var call_chain = inject_logout_iframe ? [injector, authorized, next] :
            [authorized, next];
          chain(req, res, call_chain);
        } else {
          writeHead(res, auth_res.statusCode, auth_res.headers);
          auth_res.on('data', function(chunk) {
            res.write(chunk);
          });
          auth_res.on('end', function() {
            res.end();
          });
        }
      });
      auth_req.on('error', report_error(res, 'auth request failed'));
      auth_req.end();
    }
  };
}
module.exports = wwwhisper;
<|endoftext|>


<commit_before>'use strict'

var request = require('request')
var cheerio = require('cheerio')
var moment = require('moment')

var tracker = require('../')

var trackingInfo = function (number) {
  return {
    method: 'GET',
    url: 'https://www.royalmail.com/track-your-item?trackNumber=' + number
  }
}

var parser = {
  trace: function (body) {
    var $ = cheerio.load(body)
    var courier = {
      code: tracker.COURIER.ROYALMAIL.CODE,
      name: tracker.COURIER.ROYALMAIL.NAME
    }
    var result = {
      courier: courier,
      number: $('#edit-tracking-number').val(),
      status: tracker.STATUS.PENDING
    }

    var checkpoints = []

    var $details = $('#rml-track-trace-tracking-details-dialog-' + result.number)
    $details = $details.find('table').eq(1)

    $('tbody').find('tr').each(function (idx) {
      var cols = $(this).find('td')
      if (cols.length === 1) {
        return false
      }

      var message = [cols.eq(2).text().trim()]
      var time = moment(cols.eq(0).text().trim() + cols.eq(1).text().trim(), 'DD-MMM-YYYYHH:mm')
      var checkpoint = {
        courier: courier,
        location: cols.eq(3).text().trim(),
        message: message.join(' - '),
        status: tracker.STATUS.IN_TRANSIT,
        time: time.isValid() ? time.format('YYYY-MM-DDTHH:mm:ss') : ''
      }

      checkpoint.message.indexOf('Recipient Collected') !== -1 && (checkpoint.status = tracker.STATUS.INFO_RECEIVED)
      checkpoint.message.indexOf('NOT DELIVERED') !== -1 && (checkpoint.status = tracker.STATUS.FAIL_ATTEMPT)
      checkpoint.message.indexOf('Delivered') !== -1 && (checkpoint.status = tracker.STATUS.DELIVERED)

      checkpoints.push(checkpoint)
    })

    result.checkpoints = checkpoints
    result.status = tracker.normalizeStatus(result.checkpoints)

    return result
  }
}

module.exports = {
  trackingInfo: trackingInfo,
  trace: function (number, cb) {
    var tracking = trackingInfo(number)
    request.get({
      url: tracking.url
    }, function (err, res, body) {
      if (err) {
        return cb(err)
      }

      var result = parser.trace(body)
      cb(result ? null : tracker.error(tracker.ERROR.INVALID_NUMBER), result)
    })
  }
}
<commit_msg>* fixed standard format.<commit_after>'use strict'

var request = require('request')
var cheerio = require('cheerio')
var moment = require('moment')

var tracker = require('../')

var trackingInfo = function (number) {
  return {
    method: 'GET',
    url: 'https://www.royalmail.com/track-your-item?trackNumber=' + number
  }
}

var parser = {
  trace: function (body) {
    var $ = cheerio.load(body)
    var courier = {
      code: tracker.COURIER.ROYALMAIL.CODE,
      name: tracker.COURIER.ROYALMAIL.NAME
    }
    var result = {
      courier: courier,
      number: $('#edit-tracking-number').val(),
      status: tracker.STATUS.PENDING
    }

    var checkpoints = []

    var $details = $('#rml-track-trace-tracking-details-dialog-' + result.number)
    $details = $details.find('table').eq(0)
    $details.find('tbody').find('tr').each(function (idx) {
      var cols = $(this).find('td')
      if (cols.length === 1) {
        return false
      }

      var message = [cols.eq(2).text().trim()]
      var time = moment(cols.eq(0).text().trim() + cols.eq(1).text().trim(), 'DD-MMM-YYYYHH:mm')
      var checkpoint = {
        courier: courier,
        location: cols.eq(3).text().trim(),
        message: message.join(' - '),
        status: tracker.STATUS.IN_TRANSIT,
        time: time.isValid() ? time.format('YYYY-MM-DDTHH:mm:ss') : ''
      }

      checkpoint.message.indexOf('Recipient Collected') !== -1 && (checkpoint.status = tracker.STATUS.INFO_RECEIVED)
      checkpoint.message.indexOf('NOT DELIVERED') !== -1 && (checkpoint.status = tracker.STATUS.FAIL_ATTEMPT)
      checkpoint.message.indexOf('Delivered') !== -1 && (checkpoint.status = tracker.STATUS.DELIVERED)

      checkpoints.push(checkpoint)
    })

    result.checkpoints = checkpoints
    result.status = tracker.normalizeStatus(result.checkpoints)

    return result
  }
}

module.exports = {
  trackingInfo: trackingInfo,
  trace: function (number, cb) {
    var tracking = trackingInfo(number)
    request.get({
      url: tracking.url
    }, function (err, res, body) {
      if (err) {
        return cb(err)
      }

      var result = parser.trace(body)
      cb(result ? null : tracker.error(tracker.ERROR.INVALID_NUMBER), result)
    })
  }
}
<|endoftext|>


<commit_before>let utils = require('../utils/utils.js');
let RunCode = require('../core/runCode.js');

class Console {
  constructor(options) {
    this.events = options.events;
    this.plugins = options.plugins;
    this.version = options.version;
    this.contractsConfig = options.contractsConfig;
  }

  runCode(code) {
    RunCode.doEval(code);
  }

  processEmbarkCmd (cmd) {
    if (cmd === 'help' || cmd === __('help')) {
      let helpText = [
        __('Welcome to Embark') + ' ' + this.version,
        '',
        __('possible commands are:'),
        'versions - ' + __('display versions in use for libraries and tools like web3 and solc'),
        // TODO: only if the blockchain is actually active!
        // will need to pass te current embark state here
        'web3 - ' + __('instantiated web3.js object configured to the current environment'),
        'quit - ' + __('to immediatly exit (alias: exit)'),
        '',
        __('The web3 object and the interfaces for the deployed contracts and their methods are also available')
      ];
      return helpText.join('\n');
    } else if (['quit', 'exit', 'sair', 'sortir', __('quit')].indexOf(cmd) >= 0) {
      utils.exit();
    }
    return false;
  }

  executeCmd(cmd, callback) {
    var pluginCmds = this.plugins.getPluginsProperty('console', 'console');
    for (let pluginCmd of pluginCmds) {
      let pluginOutput = pluginCmd.call(this, cmd, {});
      //console.log("plugin output: ", pluginOutput)
      if (pluginOutput !== false && pluginOutput !== 'false' && pluginOutput !== undefined)
        return callback(pluginOutput);
    }
    //console.log("Do we hit the here?")
    let output = this.processEmbarkCmd(cmd);
    if (output) {
      return callback(output);
    }

    try {
      let result = RunCode.doEval(cmd);
      return callback(result);
    }
    catch (e) {
      if (e.message.indexOf('not defined') > 0) {
        return callback(("error: " + e.message).red + ("\n" + __("Type") + " " + "help".bold + " " + __("to see the list of available commands")).cyan);
      } else {
        return callback(e.message);
      }
    }
  }
}

module.exports = Console;
<commit_msg>concentrate undefined logic in the plugin output<commit_after>let utils = require('../utils/utils.js');
let RunCode = require('../core/runCode.js');

class Console {
  constructor(options) {
    this.events = options.events;
    this.plugins = options.plugins;
    this.version = options.version;
    this.contractsConfig = options.contractsConfig;
  }

  runCode(code) {
    RunCode.doEval(code);
  }

  processEmbarkCmd (cmd) {
    if (cmd === 'help' || cmd === __('help')) {
      let helpText = [
        __('Welcome to Embark') + ' ' + this.version,
        '',
        __('possible commands are:'),
        'versions - ' + __('display versions in use for libraries and tools like web3 and solc'),
        // TODO: only if the blockchain is actually active!
        // will need to pass te current embark state here
        'web3 - ' + __('instantiated web3.js object configured to the current environment'),
        'quit - ' + __('to immediatly exit (alias: exit)'),
        '',
        __('The web3 object and the interfaces for the deployed contracts and their methods are also available')
      ];
      return helpText.join('\n');
    } else if (['quit', 'exit', 'sair', 'sortir', __('quit')].indexOf(cmd) >= 0) {
      utils.exit();
    }
    return false;
  }

  executeCmd(cmd, callback) {
    var pluginCmds = this.plugins.getPluginsProperty('console', 'console');
    for (let pluginCmd of pluginCmds) {
      let pluginOutput = pluginCmd.call(this, cmd, {});
      if (pluginOutput !== false && pluginOutput !== 'false' && pluginOutput !== undefined)
        return callback(pluginOutput);
      if (pluginOutput === undefined) {
        return callback("");
      }
    }

    let output = this.processEmbarkCmd(cmd);
    if (output) {
      return callback(output);
    }

    try {
      let result = RunCode.doEval(cmd);
      return callback(result);
    }
    catch (e) {
      if (e.message.indexOf('not defined') > 0) {
        return callback(("error: " + e.message).red + ("\n" + __("Type") + " " + "help".bold + " " + __("to see the list of available commands")).cyan);
      } else {
        return callback(e.message);
      }
    }
  }
}

module.exports = Console;
<|endoftext|>


<commit_before>const got = require('got');

module.exports = {
  getDigest,
  getTags,
};

const registry = 'https://index.docker.io/v2';

function getRepository(pkgName) {
  return pkgName.includes('/') ? pkgName : `library/${pkgName}`;
}

async function getHeaders(repository) {
  try {
    const authUrl = `https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repository}:pull`;
    logger.debug(`Obtaining docker registry token for ${repository}`);
    const { token } = (await got(authUrl, { json: true })).body;
    if (!token) {
      logger.warn('Failed to obtain docker registry token');
      return null;
    }
    return {
      Authorization: `Bearer ${token}`,
      Accept: 'application/vnd.docker.distribution.manifest.v2+json',
    };
  } catch (err) {
    logger.info('Error obtaining docker token');
    return null;
  }
}

async function getDigest(name, tag = 'latest') {
  try {
    const repository = getRepository(name);
    const headers = await getHeaders(repository);
    const url = `${registry}/${repository}/manifests/${tag}`;
    const digest = (await got(url, { json: true, headers })).headers[
      'docker-content-digest'
    ];
    logger.debug({ digest }, 'Got docker digest');
    return digest;
  } catch (err) {
    logger.info({ err, name, tag }, 'Error looking up docker image digest');
    return null;
  }
}

async function getTags(name) {
  try {
    const repository = getRepository(name);
    const url = `${registry}/${repository}/tags/list?n=10000`;
    const headers = await getHeaders(repository);
    const { tags } = (await got(url, { json: true, headers })).body;
    logger.debug({ tags }, 'Got docker tags');
    return tags;
  } catch (err) {
    logger.warn({ err, name }, 'Error getting docker image tags');
    return null;
  }
}
<commit_msg>fix: throw registry-failure exception if docker has internal errors<commit_after>const got = require('got');

module.exports = {
  getDigest,
  getTags,
};

const registry = 'https://index.docker.io/v2';

function getRepository(pkgName) {
  return pkgName.includes('/') ? pkgName : `library/${pkgName}`;
}

async function getHeaders(repository) {
  try {
    const authUrl = `https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repository}:pull`;
    logger.debug(`Obtaining docker registry token for ${repository}`);
    const { token } = (await got(authUrl, { json: true })).body;
    if (!token) {
      logger.warn('Failed to obtain docker registry token');
      return null;
    }
    return {
      Authorization: `Bearer ${token}`,
      Accept: 'application/vnd.docker.distribution.manifest.v2+json',
    };
  } catch (err) {
    // istanbul ignore if
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn({ err }, 'docker registry failure: internal error');
      throw new Error('registry-failure');
    }
    logger.info('Error obtaining docker token');
    return null;
  }
}

async function getDigest(name, tag = 'latest') {
  try {
    const repository = getRepository(name);
    const headers = await getHeaders(repository);
    const url = `${registry}/${repository}/manifests/${tag}`;
    const digest = (await got(url, { json: true, headers })).headers[
      'docker-content-digest'
    ];
    logger.debug({ digest }, 'Got docker digest');
    return digest;
  } catch (err) {
    // istanbul ignore if
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn({ err }, 'docker registry failure: internal error');
      throw new Error('registry-failure');
    }
    logger.info({ err, name, tag }, 'Error looking up docker image digest');
    return null;
  }
}

async function getTags(name) {
  try {
    const repository = getRepository(name);
    const url = `${registry}/${repository}/tags/list?n=10000`;
    const headers = await getHeaders(repository);
    const { tags } = (await got(url, { json: true, headers })).body;
    logger.debug({ tags }, 'Got docker tags');
    return tags;
  } catch (err) {
    // istanbul ignore if
    if (err.statusCode >= 500 && err.statusCode < 600) {
      logger.warn({ err }, 'docker registry failure: internal error');
      throw new Error('registry-failure');
    }
    logger.warn({ err, name }, 'Error getting docker image tags');
    return null;
  }
}
<|endoftext|>