flocore-node/lib/services/wallet-api/validators.js
2017-01-13 13:44:38 -05:00

252 lines
6.5 KiB
JavaScript

'use strict';
var assert = require('assert');
var bitcore = require('bitcore-lib');
var _ = require('lodash');
var utils = require('./utils');
var MAX_INT = 0xffffffff; // Math.pow(2, 32) - 1
exports.sanitizeRangeOptions = function(options) {
if (!options) {
options = {};
}
options.height = options.height || 0;
options.index = options.index || 0;
if (!options.limit) {
options.limit = 10;
} else if (options.limit > 500) {
throw new Error('Limit exceeds maximum');
}
assert(bitcore.util.js.isNaturalNumber(options.height), '"height" is expected to be a natural number');
assert(bitcore.util.js.isNaturalNumber(options.index), '"index" is expected to be a natural number');
assert(bitcore.util.js.isNaturalNumber(options.limit), '"limit" is expected to be a natural number');
assert(options.limit <= 500, '"limit" exceeds maximum');
if (options.end) {
assert(bitcore.util.js.isNaturalNumber(options.end.height), '"end height" is expected to be a natural number');
}
return options;
};
exports.checkRangeParams = function(req, res, next) {
assert(req.bitcoinHeight, '"bitcoinHeight" is expected to be set on the request');
var range = {
height: parseInt(req.query.height),
index: parseInt(req.query.index),
limit: parseInt(req.query.limit),
end: {
height: req.bitcoinHeight,
index: MAX_INT
}
};
if (req.query.end) {
range.end.height = parseInt(req.query.end) || req.bitcoinHeight;
}
try {
range = exports.sanitizeRangeOptions(range);
} catch(e) {
return utils.sendError({
message: 'Invalid params: ' + e.message,
statusCode: 400
}, res);
}
assert(range.height <= range.end.height, '\'Height\' param required to be less than \'End\' param.');
req.range = range;
next();
};
exports.checkAddress = function(req, res, next) {
var address;
var addressStr;
if (req.body.address) {
addressStr = req.body.address;
} else {
addressStr = req.params.address;
}
if(!addressStr) {
return utils.sendError({
message: 'Address param is expected',
statusCode: 400
}, res);
}
assert(req.network, '"network" is expected to be set on the request');
try {
address = new bitcore.Address(addressStr, req.network);
} catch(e) {
return utils.sendError({
message: 'Invalid address: ' + e.message,
statusCode: 400
}, res);
}
req.address = address;
next();
};
//exports.checkAddresses = function(req, res, next) {
// var addresses = [];
//
// if (!req.body.addresses || !req.body.addresses.length || !Array.isArray(req.body.addresses)) {
// return utils.sendError({
// message: 'Addresses param is expected',
// statusCode: 400
// }, res);
// }
//
// assert(req.network, '"network" is expected to be set on the request');
//
// for (var i = 0; i < req.body.addresses.length; i++) {
// var address;
// try {
// address = new bitcore.Address(req.body.addresses[i], req.network);
// } catch(e) {
// return utils.sendError({
// message: 'Invalid address: ' + e.message,
// statusCode: 400
// }, res);
// }
// addresses.push(address);
// }
//
// req.addresses = addresses;
// next();
//};
exports.checkWalletId = function(req, res, next) {
if (!req.params.walletId) {
return utils.sendError({
message: 'Wallet id is expected',
statusCode: 400
}, res);
}
if (req.params.walletId.length !== 64 || !bitcore.util.js.isHexa(req.params.walletId)) {
return utils.sendError({
message: 'Wallet id is expected to be a hexadecimal string with length of 64',
statusCode: 400
}, res);
}
req.walletId = new Buffer(req.params.walletId, 'hex');
next();
};
exports.checkAddresses = function(req, res, next) {
if (!req.file && req.body) {
req.addresses = req.body;
return next();
}
if (!req.file || !req.file.buffer) {
generateError(406, 'Content-Type must be set to multipart/form' +
' and addresses key and value must be given.');
return;
}
var buf = req.file.buffer;
var bufString = buf.toString();
req.addresses = parse(bufString);
if (!req.addresses) {
generateError(415, 'Could not parse addresses buffer into something meaningful.');
return;
}
next();
function generateError(status, msg) {
res.status(status).jsonp({
error: msg
});
}
//we are able to deal with json/jsonl, possibly others
function parse(string) {
var ret = false;
var delims = [null, '\n', ' '];
for(var i = 0; i < delims.length; i++) {
ret = utils.delimitedStringParse(delims[i], string);
if (_.isArray(ret)) {
return ret;
}
}
return ret;
}
};
exports.checkAuthHeaders = function(req, res) {
var identity = req.header('x-identity');
var signature = req.header('x-signature');
var nonce = req.header('x-nonce');
if (identity && (identity.length > 130 || !bitcore.util.js.isHexa(identity))) {
utils.sendError({
message: 'x-identity is expected to be a hexadecimal string with length of less than 131',
statusCode: 400
}, res);
return false;
}
if (signature && (signature.length > 142 || !bitcore.util.js.isHexa(signature))) {
utils.sendError({
message: 'x-signature is expected to be a hexadecimal string with length of less than 143',
statusCode: 400
}, res);
return false;
}
if (nonce && (nonce.length > 128 || nonce.length % 2 !== 0 || !bitcore.util.js.isHexa(nonce))) {
utils.sendError({
message: 'x-nonce is expected to be a hexadecimal string with length of less than 129',
statusCode: 400
}, res);
return false;
}
return true;
};
exports.checkDate = function(dateStrings) {
var errors = [];
if (!Array.isArray(dateStrings)) {
dateStrings = [dateStrings];
}
for(var i = 0; i < dateStrings.length; i++) {
internalDateCheck(dateStrings[i]);
}
function internalDateCheck(dateString) {
var date = new Date(utils.toIntIfNumberLike(dateString));
if (date.toString() === 'Invalid Date') {
errors.push('The date supplied: \'' + dateString +
'\' is not a valid date string. A valid date could be: \'2016-09-01\'.');
}
}
return errors;
};
exports.checkDateFunction = function(callback) {
var self = this;
return function() {
var args = Array.prototype.slice.call(arguments);
var errors = self.checkDate([args[1], args[2]]);
if (errors.length > 0) {
args.unshift(errors);
} else {
args.unshift(null);
}
callback.apply(null, args);
};
};
module.exports = exports;