Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ap3

Package Overview
Dependencies
Maintainers
2
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ap3 - npm Package Compare versions

Comparing version 0.2.36 to 0.2.38

lib/internal/logger.js

184

lib/index.js

@@ -1,11 +0,11 @@

var request = require("request");
var EventEmitter = require("events").EventEmitter;
var oauth = require("./middleware/oauth");
var urls = require("url");
var config = require("./internal/config");
var Q = require("q");
var _ = require("underscore");
var colors = require("colors");
var lt = require("localtunnel").client;
var fs = require("fs");
var config = require("./internal/config");
var registration = require("./internal/registration");
var defLogger = require("./internal/logger");
var oauth = require("./middleware/oauth");
var webhookOAuth = require("./middleware/webhook-oauth");

@@ -22,8 +22,10 @@ function Plugin(app, logger) {

self.name = self.descriptor.get("name");
_.extend(self, registration);
self.on("remote_plugin_installed", function (key, settings) {
// self.logger.warn("DEBUG: plugin installed:", key, JSON.stringify(settings));
self.settings.hset(settings.clientKey, settings);
});
if(self.app.get("env") === "development") {
if (self.app.get("env") === "development") {
self.logger.info("Watching atlassian-plugin.xml for changes.");

@@ -67,5 +69,2 @@ fs.watchFile("atlassian-plugin.xml", function (curr, prev) {

var installed = self.descriptor.webhooks("remote_plugin_installed")[0];
var installedUrl = installed && basePath + installed.get("url");
// auto-register routes for each webhook in the descriptor

@@ -78,18 +77,3 @@ self.descriptor.webhooks().forEach(function (webhook) {

// auth middleware
function (req, res, next) {
var path = urls.parse(req.url).pathname;
// self.logger.warn("DEBUG: webhook auth:", JSON.stringify(installed), path, JSON.stringify(req.body));
if (!installed || path !== installedUrl) {
// self.logger.warn("DEBUG: Authenticating webhook", webhookUrl);
self.authenticate()(req, res, next);
}
else {
// @todo for the "installed" webhook, we need to handshake back with the host at a known or
// discovered url to retrieve its public key and verify the signature
// @see https://bitbucket.org/atlassian/node-ap3/issue/9/in-production-mode-whitelist-only-jiracom
// @see https://bitbucket.org/atlassian/node-ap3/issue/10/verify-host-during-remote_plugin_installed
// self.logger.warn("DEBUG: Allowing webhook", webhookUrl);
next();
}
},
webhookOAuth(self, basePath),
// request handler

@@ -113,152 +97,12 @@ function (req, res) {

proto.authenticate = function () {
return oauth(this);
proto.authenticate = function (publicKey) {
return oauth(this, publicKey);
};
// returns the best available http client given a context request
proto.httpClient = function (req) {
return (req.context && req.context.http) || require("request");
return req.context && req.context.http;
};
proto.register = function (isReregistration) {
var self = this;
var hosts = this.config.hosts();
if (hosts && hosts.length > 0) {
self._registrations = {};
if(!isReregistration){
self.logger.info("Registering plugin...");
process.once("SIGINT", function () {
function exit() { process.exit(1); }
self.deregister().then(exit, exit);
});
}
return Q.allResolved(hosts.map(_.bind(register, self))).then(
function (promises) {
promises.forEach(function (promise) {
var host = promise.valueOf();
if (host) {
self.once("remote_plugin_installed", function (key, settings) {
if (stripCredentials(host) === settings.baseUrl) {
self.logger.info("Registered with " + settings.baseUrl + ".");
self._registrations[host] = settings.clientKey;
// @todo unsubscribe this webhook listener
}
});
}
});
},
function () {
self.logger.error.apply(self.logger, arguments);
}
);
}
return Q.resolve();
};
function register(host) {
var self = this;
var dfd = Q.defer();
request.post({
uri: host + "/rest/remotable-plugins/latest/installer",
form: {url: self.config.localBaseUrl() + "/atlassian-plugin.xml"},
jar: false
}, function (err, res, body) {
if ((err && err.code !== "ECONNREFUSED") || res && res.statusCode !== 200) {
var args = ["Failed to register with host server:"];
if (err) args.push(err);
if (body) args.push(body);
self.logger.error.apply(self.logger, args);
dfd.resolve();
}
else if (res && res.statusCode === 200) {
dfd.resolve(host);
}
else {
dfd.resolve();
}
});
return dfd.promise;
}
proto.deregister = function () {
var self = this;
if (self._registrations) {
var hosts = _.keys(self._registrations);
if (hosts && hosts.length > 0) {
console.log();
self.logger.info("Deregistering plugin...");
return Q.allResolved(hosts.map(_.bind(deregister, self))).then(
function (promises) {
promises.forEach(function (promise) {
var host = promise.valueOf();
if (host) {
// @todo is there an uninstall webhook we can listen for for parity with register?
var bareHost = stripCredentials(host);
delete self._registrations[bareHost];
self.logger.info("Deregistered with host " + bareHost + ".");
}
});
},
function () {
self.logger.error(arguments.join(' '))
}
);
}
}
return Q.resolve();
};
function deregister(host) {
var self = this;
var dfd = Q.defer();
request.del({
uri: host + "/rest/remotable-plugins/latest/uninstaller/" + this.key,
jar: false
}, function (err, res) {
if ((err && err.code !== "ECONNREFUSED") || res && res.statusCode !== 204) {
var args = ["Failed to deregister with host server"];
if (err) args.push(":" + err);
self.logger.error.apply(self.logger, args);
dfd.resolve();
}
else if (res && res.statusCode === 204) {
if (host.key) {
function resolve() { dfd.resolve(host); }
self.settings.hdel(host.key).then(resolve, resolve);
}
else {
dfd.resolve(host);
}
}
else {
dfd.resolve();
}
});
return dfd.promise;
}
function Logger() {
var logger = {};
var ops = {"info": "white", "warn": "yellow", "error": "red"};
_.keys(ops).forEach(function (op) {
logger[op] = function () {
var args = [].slice.call(arguments);
console[op].apply(console, args.map(function (arg) {
// @todo stringify objects with util.inspect and then apply styles to the resulting string
return _.isObject(arg) ? arg : new String(arg)[ops[op]].bold;
}));
};
});
return logger;
}
function stripCredentials(url) {
url = urls.parse(url);
delete url.auth;
return urls.format(url);
}
module.exports = function (app, logger) {
if (!logger) logger = Logger();
return new Plugin(app, logger);
return new Plugin(app, logger || defLogger);
};

@@ -54,2 +54,11 @@ var _ = require("underscore");

return crypto.createHash("sha1").update(this.privateKey()).digest("base64");
},
whitelist: function () {
var list = get(modeValues, "whitelist", "AP3_HOST_WHITELIST");
if (!list) list = mode === "production" ? "*.jira.com" : "*";
if (_.isString(list)) list = [list];
return list.map(function (glob) {
return new RegExp(glob.replace(/\./g, "\\.").replace(/\*/g, "[^.]*"));
});
}

@@ -56,0 +65,0 @@

@@ -12,5 +12,2 @@ // modified from https://bitbucket.org/knecht_andreas/atlassian-oauth-validator

var signatureBase = createSignatureBase(options.method, options.url, normParams);
// if (options.logger) {
// options.logger.warn("DEBUG: oauth.verify:", JSON.stringify(options), normParams, signatureBase);
// }
verifier.update(signatureBase);

@@ -17,0 +14,0 @@ if (verifier.verify(ensurePem("PUBLIC", options.publicKey), options.signature, "base64")) {

@@ -6,3 +6,3 @@ // modified from https://bitbucket.org/knecht_andreas/atlassian-oauth-validator

module.exports = function (plugin) {
module.exports = function (plugin, optionalPublicKey) {

@@ -120,16 +120,20 @@ var maxTimestampAge = 5 * 60 * 1000;

plugin.settings.hget(clientKey).then(
function (consumer) {
if (!consumer) {
send(401, "OAuth consumer " + clientKey + " not approved to make requests.");
if (optionalPublicKey) {
verify(optionalPublicKey);
}
else {
plugin.settings.hget(clientKey).then(
function (consumer) {
if (!consumer) {
send(401, "OAuth consumer " + clientKey + " not approved to make requests.");
}
else {
verify(consumer.publicKey);
}
},
function (err) {
send(401, "OAuth request not authenticated due to consumer lookup failure: " + err)
}
else {
// plugin.logger.warn("DEBUG: hget consumer:", clientKey, JSON.stringify(consumer));
verify(consumer.publicKey);
}
},
function (err) {
send(401, "OAuth request not authenticated due to consumer lookup failure: " + err)
}
);
);
}

@@ -136,0 +140,0 @@ };

{
"name": "ap3",
"version": "0.2.36",
"version": "0.2.38",
"description": "Atlassian Plugins 3 library for Express",

@@ -5,0 +5,0 @@ "dependencies": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc