almrestwrapper
Version:
A Wrapper around ALM using REST API. Referenced from ddikman from GIThub
255 lines (183 loc) • 6.54 kB
JavaScript
var Promise = require('promise');
var cookies = require('cookie');
var util = require('util');
var Client = new require('node-rest-client').Client;
InvalidAuthenticationException = function(msg){
this.message = msg;
this.name = "InvalidAuthenticationException";
};
FailedRequestException = function(msg, statusCode, response, url){
this.message = msg;
this.response = response;
this.statusCode = statusCode;
this.url = url;
this.name = "FailedRequestException";
};
var qcApi = function(){
this.isAuthenticated = false;
};
qcApi.prototype.getClient = function(args){
return new Client(args);
};
qcApi.prototype.trimSlash = function(url){
if(url)
{
if(typeof(url) != 'string')
throw 'Url is not string: ' + url;
if(url.length > 0 && url[url.length - 1] == '/')
url = url.substr(0, url.length - 1);
if(url.length > 0 && url[0] == '/')
url = url.substr(1, url.length);
}
return url;
};
qcApi.prototype.prependSlash = function(url){
return url[0] == '/' ? url : "/" + url;
}
qcApi.prototype.startSession = function(){
var promise = new Promise(function(resolve, reject){
this.client.post(this.rootUrl + "/rest/site-session", { headers: { cookie : this.authCookie } }, function(data, res){
if(res.statusCode != 201)
{
reject("Session start failed, status code " + res.statusCode);
return;
}
this.authCookie += ";" + res.headers['set-cookie'].join(';');
resolve();
}.bind(this));
}.bind(this));
return promise;
}
qcApi.prototype.login = function(connInfo){
var promise = new Promise(function(resolve, reject){
this.rootUrl = this.trimSlash(connInfo.server);
this.connInfo = connInfo;
this.client = this.getClient({user: connInfo.user, password: connInfo.password});
this.domain = connInfo.domain;
this.project = connInfo.project;
this.client.get(this.rootUrl + "/authentication-point/authenticate", function handleAuthResponse(data, res){
if(res.statusCode == 200)
{
this.isAuthenticated = true;
this.authCookie = res.headers['set-cookie'].join(';');
this.startSession().then(resolve, reject);
}
else if(res.statusCode == 401)
{
this.isAuthenticated = false;
reject(new InvalidAuthenticationException(util.format("Failed to authenticate '%s' against %s, please verify username and password are correct", connInfo.user, this.rootUrl)));
}
else
{
this.isAuthenticated = false;
var error = new InvalidAuthenticationException(util.format("Failed to authenticate '%s' against %s: status code %s", connInfo.user, this.rootUrl, res.statusCode));
error.response = data.toString('utf8');
reject(error);
}
}.bind(this));
}.bind(this));
return promise;
};
qcApi.prototype.verifyAuthenticated = function(){
if(!this.isAuthenticated)
throw new InvalidAuthenticationException("Not yet logged in, please call login to authenticate.");
}
qcApi.prototype.getALMDomains = function(){
var promise = new Promise(function (resolve, reject){
this.client.get(this.rootUrl + '/rest/domains', { headers: { cookie: this.authCookie } }, function handleGetResponse(data, res){
if(res.statusCode != 200)
reject(new FailedRequestException("Failed to process url", res.statusCode, data.toString('utf8'), url));
else
resolve(this.convertResult(data));
}.bind(this));
}.bind(this));
return promise;
}
qcApi.prototype.logoff = function(){
var promise = new Promise(function(resolve, reject){
this.rootUrl = this.trimSlash(connInfo.server);
this.client.get(this.rootUrl + "/authentication-point/logout", function handleAuthResponse(data, res){
if(res.statusCode == 200)
{
this.isAuthenticated = false;
this.authCookie = null;
}
else
{
var error = new InvalidAuthenticationException(util.format("Error while logout", connInfo.user, this.rootUrl, res.statusCode));
error.response = data.toString('utf8');
reject(error);
}
}.bind(this));
}.bind(this));
return promise;
}
/**
* If the REST call response is an entity, some processing is performed on the resulting javascript object, such as putting each field as a property
* on the object instead of an object in the entities property list
* @param {obj} Should be a javascript object returned from the node-rest-client, parsed from a REST call xml or json response
*/
qcApi.prototype.convertResult = function(obj){
if(obj.Entities == undefined)
return obj;
var result = [];
result.totalResults = parseInt(obj.Entities['$'].TotalResults);
if(result.totalResults == 0)
return result;
obj.Entities.Entity.forEach(function(entity){
var convertedEntity = {
type: entity['$'].Type
};
entity.Fields[0].Field.forEach(function(field){
var name = field['$'].Name;
var value = field.Value ? field.Value[0] : null;
convertedEntity[name] = value;
});
result.push(convertedEntity);
});
return result;
};
qcApi.prototype.buildUrl = function(url, options){
targetUrl = this.rootUrl + "/rest";
if(this.domain)
{
targetUrl += "/domains/" + this.domain;
if(this.project)
targetUrl += "/projects/" + this.project;
}
targetUrl += this.prependSlash(url);
if(options)
{
if(typeof(options) != 'object')
throw 'Expected parameter options to be an object but got ' + typeof(options);
var queryString = [];
if(options.pageSize)
queryString.push('page-size=' + options.pageSize);
if(options.fields && options.fields.length != undefined)
queryString.push('fields=' + options.fields.join(','));
if(queryString.length > 0)
{
var appendCharacter = url.indexOf('?') >= 0 ? '&' : '?';
targetUrl = targetUrl + appendCharacter + queryString.join('&');
}
}
return targetUrl;
};
qcApi.prototype.get = function(url, options) {
var promise = new Promise(function(resolve, reject){
this.verifyAuthenticated();
url = this.buildUrl(url, options);
this.client.get(url, { headers: { cookie: this.authCookie } }, function handleGetResponse(data, res){
if(res.statusCode != 200)
reject(new FailedRequestException("Failed to process url", res.statusCode, data.toString('utf8'), url));
else
resolve(this.convertResult(data));
}.bind(this));
}.bind(this));
return promise;
};
module.exports = {
create: function(){
return new qcApi();
}
};