whitesource
Version:
Whitesource Node Module
248 lines (207 loc) • 10.4 kB
JavaScript
var cli = require('cli');
var fs = require('fs');
var request = require('request');
var circularJSON = require('circular-json');
var pluginVersion = require('./version');
var WsHelper = require('./ws_helper');
var constants = require('./constants');
var StatusCode = require('./status_code');
var colon = ":";
var WsPost = exports;
exports.constructor = function WsPost() {
};
var defaultBaseURL = 'saas.whitesourcesoftware.com';
WsPost.getPostOptions = function (confJson, report, isBower) {
//TODO: make this better - if this is bower then report is an object.report node.
if (isBower) {
var report = report.report;
}
var useHttps = true;
if (typeof(confJson.https) !== "undefined") {
useHttps = confJson.https;
}
var options = {
isHttps: useHttps,
protocol: ( (useHttps) ? "https://" : "http://"),
checkPol: ((confJson.checkPolicies === true || confJson.checkPolicies === "true") ? confJson.checkPolicies : false),
forceCheckAllDependencies: ((confJson.checkPolicies == true && confJson.forceCheckAllDependencies) ? confJson.forceCheckAllDependencies : false),
myReqType: 'UPDATE',
reqHost: ( (confJson.baseURL) ? confJson.baseURL : defaultBaseURL),
port: ( (confJson.port) ? confJson.port : "443"),
productName: ( (confJson.productName) ? confJson.productName : ((confJson.productToken) ? confJson.productToken : "")),
productVer: ( (confJson.productVer) ? confJson.productVer : report.version),
productToken: ( (confJson.productToken) ? confJson.productToken : "" ),
projectName: ( (confJson.projectName) ? confJson.projectName : ((confJson.projectToken) ? "" : report.name) ),
projectVer: ( (confJson.projectVer) ? confJson.projectVer : report.version ),
projectToken: ( (confJson.projectToken) ? confJson.projectToken : "" ),
apiKey: confJson.apiKey || process.env.WHITESOURCE_API_KEY,
userKey: ((confJson.userKey) ? confJson.userKey : ""),
ts: new Date().valueOf()
};
options.postURL = (options.protocol + options.reqHost + colon + options.port + "/agent");
//add proxy if set.
var proxy = confJson.proxy;
if (proxy) {
process.env.http_proxy = proxy;
process.env.https_proxy = proxy;
cli.ok('Using proxy: ' + proxy);
}
return options;
};
WsPost.postBowerJson = function (report, confJson, isCheckPolicies, postCallback, timeout, isDebugMode, connectionRetries, isIgnoreCertificateCheck) {
cli.ok('Getting ready to post -bower- report to WhiteSource...');
var reqOpt = WsPost.getPostOptions(confJson, report, true);
if (isCheckPolicies) {
reqOpt.myReqType = "CHECK_POLICY_COMPLIANCE";
}
if (!reqOpt.apiKey) {
cli.error('Cant find API Key, please make sure you input your whitesource API token in the whitesource.config file or as an environment variable WHITESOURCE_API_KEY');
return false
}
if (reqOpt.projectToken && reqOpt.productToken) {
cli.error('Cant use both project Token & product Token please select use only one token,to fix this open the whitesource.config file and remove one of the tokens.');
return false
}
var myRequest = WsPost.buildRequest(report, reqOpt, "bower-plugin", null, confJson);
// If both Project-Token and ProductToken send the Project-Token
if (reqOpt.projectToken) {
myRequest.myPost.projectToken = reqOpt.projectToken;
} else if (reqOpt.productToken) {
myRequest.myPost.productToken = reqOpt.productToken;
}
if (isDebugMode) {
WsHelper.saveReportFile(myRequest.json, constants.BOWER_REPORT_JSON);
WsHelper.saveReportFile(myRequest.myPost, constants.BOWER_REPORT_POST_JSON);
}
postRequest(reqOpt.postURL, postCallback, isCheckPolicies, myRequest.myPost, timeout, connectionRetries, isIgnoreCertificateCheck);
return true;
};
WsPost.postNpmJson = function (report, confJson, isCheckPolicies, postCallback, timeout, isDebugMode, connectionRetries, isIgnoreCertificateCheck) {
var reqOpt = WsPost.getPostOptions(confJson, report);
if (isCheckPolicies) {
reqOpt.myReqType = "CHECK_POLICY_COMPLIANCE";
}
try {
var modJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
if (typeof (modJson.version) == "undefined") {
modJson.version = "0.00";
}
} catch (e) {
cli.error('Problem reading Package.json, please check the file is a valid JSON');
return false;
}
if (!modJson.name || !modJson.version) {
cli.error('Node package -Name- and -Version- must be specified in module Package.json file');
return false;
}
if (!reqOpt.apiKey) {
//console.log(confJson.apiKey)
cli.error('Could not retrieve apiKey property from the configuration');
return false
}
if (reqOpt.projectToken && reqOpt.productToken) {
cli.error('Cant use both project Token & product Token please select use only one token,to fix this open the whitesource.config file and remove one of the tokens.');
return false
}
var myRequest = WsPost.buildRequest(report, reqOpt, "npm-plugin", modJson, confJson);
//if both Project-Token and ProductToken send the Project-Token
if (reqOpt.projectToken) {
myRequest.myPost.projectToken = reqOpt.projectToken;
} else if (reqOpt.productToken) {
myRequest.myPost.productToken = reqOpt.productToken;
}
if (isDebugMode) {
WsHelper.saveReportFile(myRequest.json, constants.NPM_REPORT_JSON);
WsHelper.saveReportFile(myRequest.myPost, constants.NPM_REPORT_POST_JSON);
}
postRequest(reqOpt.postURL, postCallback, isCheckPolicies, myRequest.myPost, timeout, connectionRetries, isIgnoreCertificateCheck);
return true;
};
WsPost.buildRequest = function (report, reqOpt, agent, modJson, confJson) {
//TODO: make this better - if this is bower then report is an object.report node.
var dependencies = (modJson) ? report.children : report.deps;
var name = (modJson) ? modJson.name : report.report.name;
var version = (modJson) ? modJson.version : report.report.version;
if (confJson.projectName) {
name = confJson.projectName;
}
var json = [{
dependencies: dependencies
}];
if (reqOpt.projectToken) {
json[0].projectToken = reqOpt.projectToken
} else {
json[0].coordinates = {
"artifactId": name,
"version": version
}
}
var stringifiedJson = stringifyJson(json);
var myPost = {
'type': reqOpt.myReqType,
'agent': agent,
'agentVersion': '1.0',
'pluginVersion': pluginVersion,
'forceCheckAllDependencies': reqOpt.forceCheckAllDependencies,
'product': reqOpt.productName,
'productVersion': reqOpt.productVer,
'token': reqOpt.apiKey,
'userKey': reqOpt.userKey,
'timeStamp': reqOpt.ts,
'diff': stringifiedJson
};
return {myPost: myPost, json: json};
};
function stringifyJson(json){
// this piece of code takes care of 'circular' json structure. the 'stringify' function replaces those circular dependencies
// with a string beginning with "~0~dependencies". identifying those strings and removing them
let stringifiedJson = circularJSON.stringify(json);
while (stringifiedJson.indexOf(constants.CIRCULAR_JSON_STRING) > -1){
let indexStart = stringifiedJson.indexOf(constants.CIRCULAR_JSON_STRING);
let indexEnd = stringifiedJson.indexOf("\"", indexStart) + 1;
if (stringifiedJson.charAt(indexEnd) == constants.COMMA){
indexEnd++;
} else if (stringifiedJson.charAt(indexStart - 2) == constants.COMMA){
indexStart--;
}
let replacement = stringifiedJson.substring(indexStart-1, indexEnd);
stringifiedJson = stringifiedJson.replace(replacement,constants.EMPTY_STRING);
}
return stringifiedJson;
}
function postRequest(postUrl, postCallback, isCheckPolicies, postBody, timeout, connectionRetries, isIgnoreCertificateCheck) {
cli.ok((isCheckPolicies ? "Check Policies: " : "Update: ") + "Posting to :" + postUrl);
if (isIgnoreCertificateCheck) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
}
request.post(postUrl, {timeout: timeout}, function optionalCallback(err, httpResponse, body) {
if (err && connectionRetries < 1) {
if (postCallback) {
postCallback(false, err, StatusCode.CONNECTION_FAILURE);
} else {
console.error('upload failed:', err);
console.error(JSON.stringify(httpResponse));
console.error(JSON.stringify(body));
}
} else if (err && connectionRetries >= 1) {
cli.error(err);
cli.info("Attempting to reconnect to WhiteSource");
setTimeout(postRequest, constants.DEFAULT_CONNECTION_DELAY_TIME_MILLISECONDS, postUrl, postCallback, isCheckPolicies, postBody, timeout, connectionRetries - 1, isIgnoreCertificateCheck);
} else {
if ((httpResponse.statusCode == 301 || httpResponse.statusCode == 302 || httpResponse.statusCode == 307) && httpResponse.headers.location) {
postRequest(httpResponse.headers.location, postCallback, isCheckPolicies, postBody, timeout, connectionRetries, isIgnoreCertificateCheck);
} else if (httpResponse.statusCode >= 400) {
cli.error("Http request failed with status code: " + httpResponse.statusCode + ". Message: " + httpResponse.statusMessage);
if (connectionRetries >= 1) {
cli.info("Attempting to reconnect to WhiteSource");
setTimeout(postRequest, constants.DEFAULT_CONNECTION_DELAY_TIME_MILLISECONDS, postUrl, postCallback, isCheckPolicies, postBody, timeout, connectionRetries - 1, isIgnoreCertificateCheck);
} else {
postCallback(false, err, StatusCode.SERVER_FAILURE);
}
} else {
cli.ok("Code: " + httpResponse.statusCode + " Message: " + httpResponse.statusMessage);
postCallback(true, body, null);
}
}
}).form(postBody);
}