antfarm
Version:
File automation framework for ants.
228 lines (226 loc) • 28.2 kB
JavaScript
;
var webhookJob_1 = require("../job/webhookJob");
var express = require("express");
var cors = require("cors"), multer = require("multer"), path = require("path"), tmp = require("tmp"), async = require("async");
/**
* Webhook and logging server.
*/
var Server = (function () {
function Server(e) {
this.hookRoutes = [];
this.hookInterfaceRoutes = [];
this.config = {
hooks_prefix: "/hooks",
hooks_ui_prefix: "/hooks-ui",
log_prefix: "/log"
};
/**
* Handles request and response of the web hook interface.
* @param im {InterfaceManager}
* @param req {express.Request}
* @param res {express.Response}
* @param customHandler Custom request handler.
*/
this.handleHookInterfaceRequest = function (im, req, res, customHandler) {
var s = this;
// Job arrive
var job = new webhookJob_1.WebhookJob(s.e, req, res);
// Fill in default values
var params = job.getQueryStringValues();
// If session not set, return a fresh ui somehow
var sessionId = params["sessionId"] || job.getFormDataValue("sessionId");
var ui = im.getInterface(sessionId);
if (ui.sessionId === sessionId) {
// Fill in default values
ui.fields.forEach(function (field) {
if (field.id in params && params[field.id] !== "undefined") {
field.value = params[field.id];
}
});
// Do steps
async.each(ui.steps, function (step, cb) {
s.e.log(0, "Running UI step \"" + step.name + "\".", s);
step.callback(job, ui, step, function () {
cb();
});
}, function (err) {
if (err) {
s.e.log(3, "Error running UI steps. " + err, s);
}
else {
s.e.log(0, "Done running all UI steps.", s);
}
if (customHandler) {
customHandler(req, res, ui);
}
else {
res.json(ui.getTransportInterface());
}
});
}
else {
if (customHandler) {
customHandler(req, res, ui);
}
else {
res.json(ui.getTransportInterface());
}
}
};
var s = this;
s.e = e;
s.server = express();
s.createServer();
// let tmpDir = tmp.dirSync()._name;
var tmpDir = "./example";
s.upload = multer({
destination: tmpDir,
storage: multer.diskStorage({
filename: function (req, file, cb) {
cb(null, file.fieldname + "-" + Date.now());
}
})
});
}
/**
* Creates the server.
*/
Server.prototype.createServer = function () {
var s = this;
var port = s.e.options.port;
s.server.use(cors());
// Add index routes
s.server.get(s.config.hooks_prefix, function (req, res) {
res.json(s.hookRoutes);
});
s.server.get(s.config.hooks_ui_prefix, function (req, res) {
res.json(s.hookInterfaceRoutes);
});
// Prevent duplicate listening for tests
// if (!module.parent) {
// s.server.listen(port, () => s.e.log(1, `Server up and listening on port ${port}.`, s));
// }
s.server.listen(port, function () { return s.e.log(1, "Server up and listening on port " + port + ".", s); })
.on("error", function (err) {
s.e.log(3, "Server listen error: \"" + err.message + "\".", s);
});
};
Server.prototype.createLogServer = function (logger) {
var s = this;
var options = {
order: "desc",
fields: ["message"]
};
// Add index routes
s.server.get(s.config.log_prefix, function (req, res) {
logger.query(options, function (results) {
res.json(results);
});
});
};
/**
* Log _name
* @returns {string}
*/
Server.prototype.toString = function () {
return "Server";
};
/**
* Adds a webhook to the server.
* @param nest {WebhookNest}
*/
Server.prototype.addWebhook = function (nest) {
var s = this;
var e = s.e;
var httpMethod = nest.httpMethod;
var hook_path = s.config.hooks_prefix + nest.path;
var hook_ui_path;
var im = nest.interfaceManager;
var wi = im.getInterface();
hook_ui_path = s.config.hooks_ui_prefix + im.path;
s.e.log(1, "Watching webhook " + httpMethod.toUpperCase() + " " + hook_path, s);
s.hookRoutes.push({
id: nest.id,
path: hook_path,
nest: nest.name,
tunnel: nest.tunnel.name,
method: httpMethod,
interface_path: hook_ui_path
});
s.server[httpMethod](hook_path, s.upload.any(), function (req, res) {
var customHandler = nest.customHandleRequest;
s.handleHookRequest(nest, req, res, customHandler);
});
};
/**
* Handles request and response of the web hook, creates a new job, as well as calling the nest's arrive.
* @param nest {WebhookNest}
* @param req {express.Request}
* @param res {express.Response}
* @param customHandler Custom request handler.
*/
Server.prototype.handleHookRequest = function (nest, req, res, customHandler) {
var s = this;
// Job arrive
var job = new webhookJob_1.WebhookJob(s.e, req, res);
nest.arrive(job);
s.sendHookResponse(nest.holdResponse, job, nest, req, res, customHandler);
};
;
/**
* Sends the actual hook response.
* @param holdResponse Flag to bypass sending now for held responses.
* @param job Webhook job
* @param nest Webhook nest
* @param req
* @param res
* @param customHandler
* @param message
*/
Server.prototype.sendHookResponse = function (holdResponse, job, nest, req, res, customHandler, message) {
if (holdResponse === true) {
}
else if (customHandler) {
job.responseSent = true;
customHandler(req, res, job, nest);
}
else {
job.responseSent = true;
var response = {
message: message || "Job " + job.id + " was created!",
job: {
id: job.id,
name: job.name
},
nest: {
name: nest.name
}
};
res.json(response);
}
};
/**
* Adds a webhook interface to the webhook server.
* @param im {InterfaceManager}
*/
Server.prototype.addWebhookInterface = function (im) {
var s = this;
var nest = im.nest;
var hook_path = s.config.hooks_prefix + nest.path;
var hook_ui_path = s.config.hooks_ui_prefix + im.path;
s.e.log(1, "Watching webhook interface GET " + hook_ui_path, s);
this.hookInterfaceRoutes.push({
id: nest.id,
path: hook_ui_path,
nest: nest.name,
target: hook_path
});
s.server.get(hook_ui_path, function (req, res) {
var customHandler = im.customHandleRequest;
s.handleHookInterfaceRequest(im, req, res, customHandler);
});
};
return Server;
}());
exports.Server = Server;
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9lbnZpcm9ubWVudC9zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUVBLDJCQUF5QixtQkFBbUIsQ0FBQyxDQUFBO0FBQzdDLElBQVksT0FBTyxXQUFNLFNBQVMsQ0FBQyxDQUFBO0FBSW5DLElBQVEsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFDdEIsTUFBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFDMUIsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFDdEIsR0FBRyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFDcEIsS0FBSyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUVqQzs7R0FFRztBQUNIO0lBY0ksZ0JBQVksQ0FBYztRQVZoQixlQUFVLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLHdCQUFtQixHQUFHLEVBQUUsQ0FBQztRQUd6QixXQUFNLEdBQUc7WUFDZixZQUFZLEVBQUUsUUFBUTtZQUN0QixlQUFlLEVBQUUsV0FBVztZQUM1QixVQUFVLEVBQUUsTUFBTTtTQUNyQixDQUFDO1FBK0xGOzs7Ozs7V0FNRztRQUNPLCtCQUEwQixHQUFHLFVBQVMsRUFBb0IsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLGFBQW1CO1lBQy9GLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQztZQUViLGFBQWE7WUFDYixJQUFJLEdBQUcsR0FBRyxJQUFJLHVCQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFFeEMseUJBQXlCO1lBQ3pCLElBQUksTUFBTSxHQUFHLEdBQUcsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBRXhDLGdEQUFnRDtZQUNoRCxJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRXpFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENB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RUFBRSxDQUFDLENBQUMsQ0FBQztRQUVoRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDO1lBQzFCLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtZQUNYLElBQUksRUFBRSxZQUFZO1lBQ2xCLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNmLE1BQU0sRUFBRSxTQUFTO1NBRXBCLENBQUMsQ0FBQztRQUVILENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRyxVQUFVLEdBQUcsRUFBRSxHQUFHO1lBRTFDLElBQUksYUFBYSxHQUFHLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztZQUUzQyxDQUFDLENBQUMsMEJBQTBCLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDOUQsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBNERMLGFBQUM7QUFBRCxDQXJRQSxBQXFRQyxJQUFBO0FBclFZLGNBQU0sU0FxUWxCLENBQUEiLCJmaWxlIjoibGliL2Vudmlyb25tZW50L3NlcnZlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7RW52aXJvbm1lbnR9IGZyb20gXCIuL2Vudmlyb25tZW50XCI7XG5pbXBvcnQge1dlYmhvb2tOZXN0fSBmcm9tIFwiLi4vbmVzdC93ZWJob29rTmVzdFwiO1xuaW1wb3J0IHtXZWJob29rSm9ifSBmcm9tIFwiLi4vam9iL3dlYmhvb2tKb2JcIjtcbmltcG9ydCAqIGFzIGV4cHJlc3MgZnJvbSBcImV4cHJlc3NcIjtcbmltcG9ydCB7SW50ZXJmYWNlTWFuYWdlcn0gZnJvbSBcIi4uL3VpL2ludGVyZmFjZU1hbmFnZXJcIjtcbmltcG9ydCB7TG9nZ2VyLCBMb2dRdWVyeU9wdGlvbnN9IGZyb20gXCIuL2xvZ2dlclwiO1xuXG5jb25zdCAgIGNvcnMgPSByZXF1aXJlKFwiY29yc1wiKSxcbiAgICAgICAgbXVsdGVyID0gcmVxdWlyZShcIm11bHRlclwiKSxcbiAgICAgICAgcGF0aCA9IHJlcXVpcmUoXCJwYXRoXCIpLFxuICAgICAgICB0bXAgPSByZXF1aXJlKFwidG1wXCIpLFxuICAgICAgICBhc3luYyA9IHJlcXVpcmUoXCJhc3luY1wiKTtcblxuLyoqXG4gKiBXZWJob29rIGFuZCBsb2dnaW5nIHNlcnZlci5cbiAqL1xuZXhwb3J0IGNsYXNzIFNlcnZlciB7XG5cbiAgICBwcm90ZWN0ZWQgc2VydmVyOiBleHByZXNzLkFwcGxpY2F0aW9uO1xuICAgIHByb3RlY3RlZCBlOiBFbnZpcm9ubWVudDtcbiAgICBwcm90ZWN0ZWQgaG9va1JvdXRlcyA9IFtdO1xuICAgIHByb3RlY3RlZCBob29rSW50ZXJmYWNlUm91dGVzID0gW107XG4gICAgcHJvdGVjdGVkIHVwbG9hZDtcblxuICAgIHByb3RlY3RlZCBjb25maWcgPSB7XG4gICAgICAgIGhvb2tzX3ByZWZpeDogXCIvaG9va3NcIixcbiAgICAgICAgaG9va3NfdWlfcHJlZml4OiBcIi9ob29rcy11aVwiLFxuICAgICAgICBsb2dfcHJlZml4OiBcIi9sb2dcIlxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3RvcihlOiBFbnZpcm9ubWVudCkge1xuICAgICAgICBsZXQgcyA9IHRoaXM7XG4gICAgICAgIHMuZSA9IGU7XG4gICAgICAgIHMuc2VydmVyID0gZXhwcmVzcygpO1xuXG4gICAgICAgIHMuY3JlYXRlU2VydmVyKCk7XG5cbiAgICAgICAgLy8gbGV0IHRtcERpciA9IHRtcC5kaXJTeW5jKCkuX25hbWU7XG4gICAgICAgIGxldCB0bXBEaXIgPSBcIi4vZXhhbXBsZVwiO1xuXG4gICAgICAgIHMudXBsb2FkID0gbXVsdGVyKHtcbiAgICAgICAgICAgICAgICBkZXN0aW5hdGlvbjogdG1wRGlyLFxuICAgICAgICAgICAgICAgIHN0b3JhZ2U6IG11bHRlci5kaXNrU3RvcmFnZSh7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lOiBmdW5jdGlvbiAocmVxLCBmaWxlLCBjYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2IobnVsbCwgZmlsZS5maWVsZG5hbWUgKyBcIi1cIiArIERhdGUubm93KCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgdGhlIHNlcnZlci5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY3JlYXRlU2VydmVyKCkge1xuICAgICAgICBsZXQgcyA9IHRoaXM7XG5cbiAgICAgICAgbGV0IHBvcnQgPSBzLmUub3B0aW9ucy5wb3J0O1xuXG4gICAgICAgIHMuc2VydmVyLnVzZShjb3JzKCkpO1xuXG4gICAgICAgIC8vIEFkZCBpbmRleCByb3V0ZXNcbiAgICAgICAgcy5zZXJ2ZXIuZ2V0KHMuY29uZmlnLmhvb2tzX3ByZWZpeCwgZnVuY3Rpb24ocmVxLCByZXMpe1xuICAgICAgICAgICAgcmVzLmpzb24ocy5ob29rUm91dGVzKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHMuc2VydmVyLmdldChzLmNvbmZpZy5ob29rc191aV9wcmVmaXgsIGZ1bmN0aW9uKHJlcSwgcmVzKXtcbiAgICAgICAgICAgIHJlcy5qc29uKHMuaG9va0ludGVyZmFjZVJvdXRlcyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFByZXZlbnQgZHVwbGljYXRlIGxpc3RlbmluZyBmb3IgdGVzdHNcbiAgICAgICAgLy8gaWYgKCFtb2R1bGUucGFyZW50KSB7XG4gICAgICAgIC8vICAgICBzLnNlcnZlci5saXN0ZW4ocG9ydCwgKCkgPT4gcy5lLmxvZygxLCBgU2VydmVyIHVwIGFuZCBsaXN0ZW5pbmcgb24gcG9ydCAke3BvcnR9LmAsIHMpKTtcbiAgICAgICAgLy8gfVxuICAgICAgICBzLnNlcnZlci5saXN0ZW4ocG9ydCwgKCkgPT4gcy5lLmxvZygxLCBgU2VydmVyIHVwIGFuZCBsaXN0ZW5pbmcgb24gcG9ydCAke3BvcnR9LmAsIHMpKVxuICAgICAgICAgICAgLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIHMuZS5sb2coMywgYFNlcnZlciBsaXN0ZW4gZXJyb3I6IFwiJHtlcnIubWVzc2FnZX1cIi5gLCBzKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgfVxuXG4gICAgcHVibGljIGNyZWF0ZUxvZ1NlcnZlcihsb2dnZXI6IExvZ2dlcikge1xuICAgICAgICBsZXQgcyA9IHRoaXM7XG5cbiAgICAgICAgbGV0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICBvcmRlcjogXCJkZXNjXCIsXG4gICAgICAgICAgICBmaWVsZHM6IFtcIm1lc3NhZ2VcIl1cbiAgICAgICAgfSBhcyBMb2dRdWVyeU9wdGlvbnM7XG5cbiAgICAgICAgLy8gQWRkIGluZGV4IHJvdXRlc1xuICAgICAgICBzLnNlcnZlci5nZXQocy5jb25maWcubG9nX3ByZWZpeCwgKHJlcSwgcmVzKSA9PiB7XG5cbiAgICAgICAgICAgIGxvZ2dlci5xdWVyeShvcHRpb25zLCByZXN1bHRzID0+IHtcbiAgICAgICAgICAgICAgICByZXMuanNvbihyZXN1bHRzKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvZyBfbmFtZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gXCJTZXJ2ZXJcIjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgd2ViaG9vayB0byB0aGUgc2VydmVyLlxuICAgICAqIEBwYXJhbSBuZXN0IHtXZWJob29rTmVzdH1cbiAgICAgKi9cbiAgICBwdWJsaWMgYWRkV2ViaG9vayhuZXN0OiBXZWJob29rTmVzdCkge1xuICAgICAgICBsZXQgcyA9IHRoaXM7XG4gICAgICAgIGxldCBlID0gcy5lO1xuXG4gICAgICAgIGxldCBodHRwTWV0aG9kID0gbmVzdC5odHRwTWV0aG9kO1xuICAgICAgICBsZXQgaG9va19wYXRoID0gcy5jb25maWcuaG9va3NfcHJlZml4ICsgbmVzdC5wYXRoO1xuICAgICAgICBsZXQgaG9va191aV9wYXRoO1xuICAgICAgICBsZXQgaW0gPSBuZXN0LmludGVyZmFjZU1hbmFnZXI7XG5cbiAgICAgICAgbGV0IHdpID0gaW0uZ2V0SW50ZXJmYWNlKCk7XG4gICAgICAgIGhvb2tfdWlfcGF0aCA9IHMuY29uZmlnLmhvb2tzX3VpX3ByZWZpeCArIGltLnBhdGg7XG5cbiAgICAgICAgcy5lLmxvZygxLCBgV2F0Y2hpbmcgd2ViaG9vayAke2h0dHBNZXRob2QudG9VcHBlckNhc2UoKX0gJHtob29rX3BhdGh9YCwgcyk7XG5cbiAgICAgICAgcy5ob29rUm91dGVzLnB1c2goe1xuICAgICAgICAgICAgaWQ6IG5lc3QuaWQsXG4gICAgICAgICAgICBwYXRoOiBob29rX3BhdGgsXG4gICAgICAgICAgICBuZXN0OiBuZXN0Lm5hbWUsXG4gICAgICAgICAgICB0dW5uZWw6IG5lc3QudHVubmVsLm5hbWUsXG4gICAgICAgICAgICBtZXRob2Q6IGh0dHBNZXRob2QsXG4gICAgICAgICAgICBpbnRlcmZhY2VfcGF0aDogaG9va191aV9wYXRoXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHMuc2VydmVyW2h0dHBNZXRob2RdKGhvb2tfcGF0aCwgcy51cGxvYWQuYW55KCksIGZ1bmN0aW9uIChyZXEsIHJlcykge1xuXG4gICAgICAgICAgICBsZXQgY3VzdG9tSGFuZGxlciA9IG5lc3QuY3VzdG9tSGFuZGxlUmVxdWVzdDtcblxuICAgICAgICAgICAgIHMuaGFuZGxlSG9va1JlcXVlc3QobmVzdCwgcmVxLCByZXMsIGN1c3RvbUhhbmRsZXIpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHJlcXVlc3QgYW5kIHJlc3BvbnNlIG9mIHRoZSB3ZWIgaG9vaywgY3JlYXRlcyBhIG5ldyBqb2IsIGFzIHdlbGwgYXMgY2FsbGluZyB0aGUgbmVzdCdzIGFycml2ZS5cbiAgICAgKiBAcGFyYW0gbmVzdCB7V2ViaG9va05lc3R9XG4gICAgICogQHBhcmFtIHJlcSB7ZXhwcmVzcy5SZXF1ZXN0fVxuICAgICAqIEBwYXJhbSByZXMge2V4cHJlc3MuUmVzcG9uc2V9XG4gICAgICogQHBhcmFtIGN1c3RvbUhhbmRsZXIgICAgIEN1c3RvbSByZXF1ZXN0IGhhbmRsZXIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGhhbmRsZUhvb2tSZXF1ZXN0IChuZXN0OiBXZWJob29rTmVzdCwgcmVxLCByZXMsIGN1c3RvbUhhbmRsZXI/OiBhbnkpIHtcbiAgICAgICAgbGV0IHMgPSB0aGlzO1xuXG4gICAgICAgIC8vIEpvYiBhcnJpdmVcbiAgICAgICAgbGV0IGpvYiA9IG5ldyBXZWJob29rSm9iKHMuZSwgcmVxLCByZXMpO1xuICAgICAgICBuZXN0LmFycml2ZShqb2IpO1xuXG4gICAgICAgIHMuc2VuZEhvb2tSZXNwb25zZShuZXN0LmhvbGRSZXNwb25zZSwgam9iLCBuZXN0LCByZXEsIHJlcywgY3VzdG9tSGFuZGxlcik7XG5cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2VuZHMgdGhlIGFjdHVhbCBob29rIHJlc3BvbnNlLlxuICAgICAqIEBwYXJhbSBob2xkUmVzcG9uc2UgICAgICBGbGFnIHRvIGJ5cGFzcyBzZW5kaW5nIG5vdyBmb3IgaGVsZCByZXNwb25zZXMuXG4gICAgICogQHBhcmFtIGpvYiAgICAgICAgICAgICAgIFdlYmhvb2sgam9iXG4gICAgICogQHBhcmFtIG5lc3QgICAgICAgICAgICAgIFdlYmhvb2sgbmVzdFxuICAgICAqIEBwYXJhbSByZXFcbiAgICAgKiBAcGFyYW0gcmVzXG4gICAgICogQHBhcmFtIGN1c3RvbUhhbmRsZXJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZVxuICAgICAqL1xuICAgIHB1YmxpYyBzZW5kSG9va1Jlc3BvbnNlIChob2xkUmVzcG9uc2U6IGJvb2xlYW4sIGpvYjogV2ViaG9va0pvYiwgbmVzdDogV2ViaG9va05lc3QsIHJlcSwgcmVzLCBjdXN0b21IYW5kbGVyPzogYW55LCBtZXNzYWdlPzogc3RyaW5nKSB7XG4gICAgICAgIGlmIChob2xkUmVzcG9uc2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgICAgfSBlbHNlIGlmIChjdXN0b21IYW5kbGVyKSB7XG4gICAgICAgICAgICBqb2IucmVzcG9uc2VTZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgIGN1c3RvbUhhbmRsZXIocmVxLCByZXMsIGpvYiwgbmVzdCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBqb2IucmVzcG9uc2VTZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCByZXNwb25zZSA9IHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlIHx8IGBKb2IgJHtqb2IuaWR9IHdhcyBjcmVhdGVkIWAsXG4gICAgICAgICAgICAgICAgam9iOiB7XG4gICAgICAgICAgICAgICAgICAgIGlkOiBqb2IuaWQsXG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IGpvYi5uYW1lXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBuZXN0OiB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IG5lc3QubmFtZVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXMuanNvbihyZXNwb25zZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgd2ViaG9vayBpbnRlcmZhY2UgdG8gdGhlIHdlYmhvb2sgc2VydmVyLlxuICAgICAqIEBwYXJhbSBpbSB7SW50ZXJmYWNlTWFuYWdlcn1cbiAgICAgKi9cbiAgICBwdWJsaWMgYWRkV2ViaG9va0ludGVyZmFjZShpbTogSW50ZXJmYWNlTWFuYWdlcikge1xuICAgICAgICBsZXQgcyA9IHRoaXM7XG4gICAgICAgIGxldCBuZXN0ID0gaW0ubmVzdDtcblxuICAgICAgICBsZXQgaG9va19wYXRoID0gcy5jb25maWcuaG9va3NfcHJlZml4ICsgbmVzdC5wYXRoO1xuICAgICAgICBsZXQgaG9va191aV9wYXRoID0gcy5jb25maWcuaG9va3NfdWlfcHJlZml4ICsgaW0ucGF0aDtcblxuICAgICAgICBzLmUubG9nKDEsIGBXYXRjaGluZyB3ZWJob29rIGludGVyZmFjZSBHRVQgJHtob29rX3VpX3BhdGh9YCwgcyk7XG5cbiAgICAgICAgdGhpcy5ob29rSW50ZXJmYWNlUm91dGVzLnB1c2goe1xuICAgICAgICAgICAgaWQ6IG5lc3QuaWQsXG4gICAgICAgICAgICBwYXRoOiBob29rX3VpX3BhdGgsXG4gICAgICAgICAgICBuZXN0OiBuZXN0Lm5hbWUsXG4gICAgICAgICAgICB0YXJnZXQ6IGhvb2tfcGF0aFxuICAgICAgICAgICAgLy8gdHVubmVsOiBuZXN0LmdldFR1bm5lbCgpLm5hbWVcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcy5zZXJ2ZXIuZ2V0KGhvb2tfdWlfcGF0aCwgIGZ1bmN0aW9uIChyZXEsIHJlcykge1xuXG4gICAgICAgICAgICBsZXQgY3VzdG9tSGFuZGxlciA9IGltLmN1c3RvbUhhbmRsZVJlcXVlc3Q7XG5cbiAgICAgICAgICAgIHMuaGFuZGxlSG9va0ludGVyZmFjZVJlcXVlc3QoaW0sIHJlcSwgcmVzLCBjdXN0b21IYW5kbGVyKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyByZXF1ZXN0IGFuZCByZXNwb25zZSBvZiB0aGUgd2ViIGhvb2sgaW50ZXJmYWNlLlxuICAgICAqIEBwYXJhbSBpbSB7SW50ZXJmYWNlTWFuYWdlcn1cbiAgICAgKiBAcGFyYW0gcmVxIHtleHByZXNzLlJlcXVlc3R9XG4gICAgICogQHBhcmFtIHJlcyB7ZXhwcmVzcy5SZXNwb25zZX1cbiAgICAgKiBAcGFyYW0gY3VzdG9tSGFuZGxlciAgICAgICAgICAgICBDdXN0b20gcmVxdWVzdCBoYW5kbGVyLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBoYW5kbGVIb29rSW50ZXJmYWNlUmVxdWVzdCA9IGZ1bmN0aW9uKGltOiBJbnRlcmZhY2VNYW5hZ2VyLCByZXEsIHJlcywgY3VzdG9tSGFuZGxlcj86IGFueSkge1xuICAgICAgICBsZXQgcyA9IHRoaXM7XG5cbiAgICAgICAgLy8gSm9iIGFycml2ZVxuICAgICAgICBsZXQgam9iID0gbmV3IFdlYmhvb2tKb2Iocy5lLCByZXEsIHJlcyk7XG5cbiAgICAgICAgLy8gRmlsbCBpbiBkZWZhdWx0IHZhbHVlc1xuICAgICAgICBsZXQgcGFyYW1zID0gam9iLmdldFF1ZXJ5U3RyaW5nVmFsdWVzKCk7XG5cbiAgICAgICAgLy8gSWYgc2Vzc2lvbiBub3Qgc2V0LCByZXR1cm4gYSBmcmVzaCB1aSBzb21laG93XG4gICAgICAgIGxldCBzZXNzaW9uSWQgPSBwYXJhbXNbXCJzZXNzaW9uSWRcIl0gfHwgam9iLmdldEZvcm1EYXRhVmFsdWUoXCJzZXNzaW9uSWRcIik7XG5cbiAgICAgICAgbGV0IHVpID0gaW0uZ2V0SW50ZXJmYWNlKHNlc3Npb25JZCk7XG5cbiAgICAgICAgaWYgKHVpLnNlc3Npb25JZCA9PT0gc2Vzc2lvbklkKSB7XG4gICAgICAgICAgICAvLyBGaWxsIGluIGRlZmF1bHQgdmFsdWVzXG4gICAgICAgICAgICB1aS5maWVsZHMuZm9yRWFjaChmaWVsZCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGZpZWxkLmlkIGluIHBhcmFtcyAmJiBwYXJhbXNbZmllbGQuaWRdICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkLnZhbHVlID0gcGFyYW1zW2ZpZWxkLmlkXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gRG8gc3RlcHNcbiAgICAgICAgICAgIGFzeW5jLmVhY2godWkuc3RlcHMsIChzdGVwLCBjYikgPT4ge1xuICAgICAgICAgICAgICAgIHMuZS5sb2coMCwgYFJ1bm5pbmcgVUkgc3RlcCBcIiR7c3RlcC5uYW1lfVwiLmAsIHMpO1xuICAgICAgICAgICAgICAgIHN0ZXAuY2FsbGJhY2soam9iLCB1aSwgc3RlcCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjYigpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgcy5lLmxvZygzLCBgRXJyb3IgcnVubmluZyBVSSBzdGVwcy4gJHtlcnJ9YCwgcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcy5lLmxvZygwLCBgRG9uZSBydW5uaW5nIGFsbCBVSSBzdGVwcy5gLCBzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY3VzdG9tSGFuZGxlcikge1xuICAgICAgICAgICAgICAgICAgICBjdXN0b21IYW5kbGVyKHJlcSwgcmVzLCB1aSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzLmpzb24odWkuZ2V0VHJhbnNwb3J0SW50ZXJmYWNlKCkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY3VzdG9tSGFuZGxlcikge1xuICAgICAgICAgICAgICAgIGN1c3RvbUhhbmRsZXIocmVxLCByZXMsIHVpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzLmpzb24odWkuZ2V0VHJhbnNwb3J0SW50ZXJmYWNlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICB9O1xufSJdfQ==