'use strict';
/**
* Linerate module
*/
var request = require('request');
var url = require('url');
var config = require('../config.json');
/**
* @class
*/
function Linerate() {
this.jar;
this.rest_url = '/lrs/api/v1.0';
this.defaults = {
rest_url: '/lrs/api/v1.0',
headers: {
'content-type': 'application/json'
}
};
// wrap request with defaults
this.request = request.defaults({
rejectUnauthorized: false
});
}
/**
* Create a session with LineRate
* @function
* @param {Object} opts - The connection options object. Supported object properties:
* @param {string} opts.host - Hostname or IP address
* @param {integer} opts.port - Port number
* @param {string} opts.username - Username
* @param {string} opts.password - Password
* @param {function} callback
*
* @example
* connect({
* host: '127.0.0.1',
* port: 8443,
* username: 'admin',
* password: 'changeme'
* }, function() {
* // code here
* });
*
*/
Linerate.prototype.connect = function(opts, callback) {
var self = this;
this.base_url = 'https://' + opts.host + ':' + opts.port;
this.jar = request.jar();
var options = {
url: this.base_url + '/login',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
body: 'username=' + opts.username + '&password=' + opts.password,
jar: self.jar
};
this.request.post(options, function(error, response) {
if (error) {
//throw new Error('connection error: ' + error);
callback(error);
}
// successful login always returns a 302
if (response.statusCode !== 302) {
//throw new Error('Login failure: ' + response.statusCode);
callback(error);
}
// and, conveniently, a failed login attempt returns a 302.
// check for 302 and redirect back to login page for failed login
if (response.statusCode === 302 &&
url.parse(response.headers.location).pathname === '/login') {
callback('Login failed');
}
//console.log(self.jar.getCookies(options.url));
callback(null, 'connected');
});
};
/**
* Initiate a GET request
* @param {Object} opts - The connection options object. Supported object properties:
* @param {string} opts.host - Hostname or IP address
* @param {integer} opts.port - Port number
* @param {string} opts.username - Username
* @param {string} opts.password - Password
* @param {function} callback
*
* @example
* connect({
* host: '127.0.0.1',
* port: 8443,
* username: 'admin',
* password: 'changeme'
* }, function() {
* // code here
* });
*
*/
Linerate.prototype.get = function(node, opts, callback) {
// arguments fixup
if (typeof opts === 'function') {
callback = opts;
opts = null;
}
var path = this.rest_url + node;
if (opts) {
if (opts.query) {
path += '?' + opts.query;
}
}
this.request({
url: this.base_url + path,
jar: this.jar,
headers: this.defaults.headers,
json: true
},
function(error, response) {
if (error) {
throw new Error('err');
}
// pass callback in case of error, we can return
// directly from check_response
check_response(response, callback);
callback(null, format_response(response.body));
});
};
// opts should be:
// opts = {
// 'data': data
// 'type: type - default to string
// 'default': default - default to false
// 'query': k:v pair that will get added to uri - some
// ... nodes accept a query string, like /exec/system/util/backup (key)
// ... should maybe consider using an object so we can just use request.qs
// }
Linerate.prototype.put = function(node, opts, callback) {
var path = this.rest_url + node;
// arguments fixup
// TODO: do we need this here? I think opts will always be required
// for PUT
if (typeof opts === 'function') {
callback = opts;
}
if (opts) {
// if opts is a string, assuming all defaults except 'data'
if (typeof opts === 'string') {
opts = {
data: opts,
type: 'string',
default: false
};
}
else if (typeof opts === 'object') {
if (!opts.data) {
callback('missing data');
}
if (opts.query) {
path += '?' + opts.query;
}
opts.type = opts.type || 'string';
opts.default = opts.default || false;
}
else {
callback('unrecognized opts argument');
}
}
// note that json: true does 3 things:
// formats body data as json
// sets content-type header to application/json
// parses response body as JSON
this.request.put(
{
url: this.base_url + path,
jar: this.jar,
headers: this.defaults.headers,
json: true,
body: opts
},
function(error, response) {
if (error) {
throw new Error('err');
}
check_response(response);
callback(null, format_response(response.body));
});
};
function check_response(response) {
if (response.statusCode !== 200) {
// TODO: change to callback error
throw new Error('Non-200 response: ' +
response.statusCode +
', ' +
JSON.stringify(response.body)
);
}
if (response.body.httpResponseCode !== 200) {
// TODO: change to callback error
throw new Error('Non-200 response 2: ' +
response.httpResponseCode +
', ' +
JSON.stringify(response.body)
);
}
}
function format_response(response) {
// remember, response is already parsed JSON
// let's just return the full output for now
return response;
//return response[response.requestPath].data;
}
Linerate.prototype.util_delete = function(file, callback) {
var node = '/exec/system/util/delete';
this.put(node, file, callback);
};
Linerate.prototype.backup_list = function(callback) {
var node = '/status/system/util/backup/list';
this.get(node, callback);
};
Linerate.prototype.backup_home = function(callback) {
var node = '/exec/system/util/backup/home';
this.put(node, callback);
};
module.exports = Linerate;