Skip to content

Commit

Permalink
Merge pull request #12 from emartech/ES6
Browse files Browse the repository at this point in the history
ES6 fixes
  • Loading branch information
jcsongor committed Mar 4, 2019
2 parents 82aa0c7 + 45c8593 commit 3703d95
Show file tree
Hide file tree
Showing 12 changed files with 434 additions and 457 deletions.
11 changes: 7 additions & 4 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
"boss" : false, // true: Tolerate assignments where comparisons would be expected
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
"eqnull" : false, // true: Tolerate use of `== null`
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
"es5" : true, // true: Allow ES5 syntax (ex: getters and setters)
"esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`)
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
// (ex: `for each`, multiple try/catch, function expression…)
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
Expand Down Expand Up @@ -72,5 +72,8 @@
"yui" : false, // Yahoo User Interface

// Custom Globals
"globals" : {} // additional predefined global variables
}
"globals" : {}, // additional predefined global variables

// Others
"jasmine" : true
}
138 changes: 65 additions & 73 deletions lib/authhelper.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
'use strict';

var Signer = require('./signer');
var Canonicalizer = require('./canonicalizer');
var utils = require('./utils');
const Signer = require('./signer');
const Canonicalizer = require('./canonicalizer');
const Utils = require('./utils');

var AuthHelper = function(config, currentDate) {
class AuthHelper {

function buildAuthParts(requestOptions, requestBody, headersToSign) {
var signer = new Signer(config, currentDate);
constructor(config, currentDate) {
this._config = config;
this._currentDate = currentDate;
}

buildAuthParts(requestOptions, requestBody, headersToSign) {
const signer = new Signer(this._config, this._currentDate);

return {
shortDate: utils.toShortDate(currentDate),
shortDate: Utils.toShortDate(this._currentDate),
signedHeaders: new Canonicalizer().getCanonicalizedSignedHeaders(requestOptions.headers, headersToSign),
signature: signer.calculateSignature(signer.getStringToSign(requestOptions, requestBody, headersToSign), signer
.calculateSigningKey())
};
}

function buildHeader(authParts) {
return [config.algoPrefix, 'HMAC', config.hashAlgo].join('-') +
' Credential=' + generateFullCredentials() +
', SignedHeaders=' + formatSignedHeaders(authParts.signedHeaders) +
_buildHeader(authParts) {
return [this._config.algoPrefix, 'HMAC', this._config.hashAlgo].join('-') +
' Credential=' + this._generateFullCredentials() +
', SignedHeaders=' + this._formatSignedHeaders(authParts.signedHeaders) +
', Signature=' + authParts.signature;
}

function generateHeader(requestOptions, body, headersToSign) {
return buildHeader(buildAuthParts(requestOptions, body, headersToSign));
generateHeader(requestOptions, body, headersToSign) {
return this._buildHeader(this.buildAuthParts(requestOptions, body, headersToSign));
}

function generatePreSignedUrl(requestUrl, expires) {
var parsedUrl = utils.parseUrl(requestUrl, true); // TODO apply fixed parse here too (?)
var requestOptions = {
generatePreSignedUrl(requestUrl, expires) {
const parsedUrl = Utils.parseUrl(requestUrl, true); // TODO apply fixed parse here too (?)
const requestOptions = {
host: parsedUrl.host,
method: 'GET',
url: parsedUrl.path,
Expand All @@ -39,82 +44,77 @@ var AuthHelper = function(config, currentDate) {
]
};

var headersToSign = ['host'];
var params = {
Algorithm: [config.algoPrefix, 'HMAC', config.hashAlgo].join('-'),
Credentials: generateFullCredentials(),
Date: utils.toLongDate(currentDate),
const headersToSign = ['host'];
const params = {
Algorithm: [this._config.algoPrefix, 'HMAC', this._config.hashAlgo].join('-'),
Credentials: this._generateFullCredentials(),
Date: Utils.toLongDate(this._currentDate),
Expires: expires,
SignedHeaders: formatSignedHeaders(new Canonicalizer().getCanonicalizedSignedHeaders(requestOptions.headers,
SignedHeaders: this._formatSignedHeaders(new Canonicalizer().getCanonicalizedSignedHeaders(requestOptions.headers,
headersToSign))
};

Object.keys(params).forEach(function(key) {
requestUrl = appendQueryParamToUrl(requestUrl, getParamKey(key), params[key]);
Object.keys(params).forEach(key => {
requestUrl = this._appendQueryParamToUrl(requestUrl, this._getParamKey(key), params[key]);
});

requestOptions.url = utils.parseUrl(requestUrl, true).path;
var signer = new Signer(config, currentDate);
var signature = signer.calculateSignature(signer.getStringToSign(requestOptions, 'UNSIGNED-PAYLOAD',
requestOptions.url = Utils.parseUrl(requestUrl, true).path;
const signer = new Signer(this._config, this._currentDate);
const signature = signer.calculateSignature(signer.getStringToSign(requestOptions, 'UNSIGNED-PAYLOAD',
headersToSign), signer.calculateSigningKey());
return appendQueryParamToUrl(requestUrl, getParamKey('Signature'), signature);
return this._appendQueryParamToUrl(requestUrl, this._getParamKey('Signature'), signature);
}

function getParamKey(paramName) {
return ['X', config.vendorKey, paramName].join('-');
_getParamKey(paramName) {
return ['X', this._config.vendorKey, paramName].join('-');
}

function appendQueryParamToUrl(url, key, value) {
if (url.indexOf('?') !== -1) {
url = url + '&';
} else {
url = url + '?';
}

return url + encodeURIComponent(key) + '=' + encodeURIComponent(value);
_appendQueryParamToUrl(url, key, value) {
const separator = url.includes('?') ? '&' : '?';
return url + separator + encodeURIComponent(key) + '=' + encodeURIComponent(value);
}

function generateFullCredentials() {
return [config.accessKeyId, utils.toShortDate(currentDate), config.credentialScope].join('/');
_generateFullCredentials() {
return [this._config.accessKeyId, Utils.toShortDate(this._currentDate), this._config.credentialScope].join('/');
}

function formatSignedHeaders(signedHeaders) {
_formatSignedHeaders(signedHeaders) {
return signedHeaders.map(Function.prototype.call, String.prototype.toLowerCase).sort().join(';');
}

function algoRegExp() {
return config.algoPrefix + '-HMAC-([A-Za-z0-9\\,]+)';
_algoRegExp() {
return this._config.algoPrefix + '-HMAC-([A-Za-z0-9\\,]+)';
}

function credentialRegExp() {
_credentialRegExp() {
return '([A-Za-z0-9\\-_]+)\/([0-9]{8})\/([A-Za-z0-9\\-_ \/]+)';
}

function signedHeadersRegExp() {
_signedHeadersRegExp() {
return '([A-Za-z\\-;]+)';
}

function signatureRegExp() {
_signatureRegExp() {
return '([0-9a-f]+)';
}

function getQueryPart(query, key) {
return query['X-' + config.vendorKey + '-' + key] || '';
_getQueryPart(query, key) {
return query['X-' + this._config.vendorKey + '-' + key] || '';
}

function parseAuthHeader(authHeader, requestDate, keyDB) {
var regex = new RegExp('^' + algoRegExp() + ' Credential=' + credentialRegExp() + ', SignedHeaders=' +
signedHeadersRegExp() + ', Signature=' + signatureRegExp() + '$'
parseAuthHeader(authHeader, requestDate, keyDB) {
const regex = new RegExp('^' + this._algoRegExp() + ' Credential=' + this._credentialRegExp() + ', SignedHeaders=' +
this._signedHeadersRegExp() + ', Signature=' + this._signatureRegExp() + '$'
);
var matches = authHeader.match(regex);
const matches = authHeader.match(regex);

if (!matches) {
throw new Error('Invalid auth header format');
}

var parsedConfig = {
vendorKey: config.vendorKey,
algoPrefix: config.algoPrefix,
const parsedConfig = {
vendorKey: this._config.vendorKey,
algoPrefix: this._config.algoPrefix,
date: requestDate,
hashAlgo: matches[1],
accessKeyId: matches[2],
Expand All @@ -134,13 +134,13 @@ var AuthHelper = function(config, currentDate) {
};
}

function parseFromQuery(query, requestDate, keyDB) {
var credentialParts = getQueryPart(query, 'Credentials').match(new RegExp(credentialRegExp()));
var parsedConfig = {
vendorKey: config.vendorKey,
algoPrefix: config.algoPrefix,
parseFromQuery(query, requestDate, keyDB) {
const credentialParts = this._getQueryPart(query, 'Credentials').match(new RegExp(this._credentialRegExp()));
const parsedConfig = {
vendorKey: this._config.vendorKey,
algoPrefix: this._config.algoPrefix,
date: requestDate,
hashAlgo: getQueryPart(query, 'Algorithm').match(new RegExp(algoRegExp()))[1],
hashAlgo: this._getQueryPart(query, 'Algorithm').match(new RegExp(this._algoRegExp()))[1],
accessKeyId: credentialParts[1],
apiSecret: keyDB(credentialParts[1]),
credentialScope: credentialParts[3]
Expand All @@ -153,19 +153,11 @@ var AuthHelper = function(config, currentDate) {
return {
shortDate: credentialParts[2],
config: parsedConfig,
signedHeaders: getQueryPart(query, 'SignedHeaders').split(';'),
signature: getQueryPart(query, 'Signature'),
expires: getQueryPart(query, 'Expires')
signedHeaders: this._getQueryPart(query, 'SignedHeaders').split(';'),
signature: this._getQueryPart(query, 'Signature'),
expires: this._getQueryPart(query, 'Expires')
};
}

return {
generateHeader: generateHeader,
generatePreSignedUrl: generatePreSignedUrl,
buildAuthParts: buildAuthParts,
parseAuthHeader: parseAuthHeader,
parseFromQuery: parseFromQuery
};
};
}

module.exports = AuthHelper;
63 changes: 29 additions & 34 deletions lib/canonicalizer.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
'use strict';

var path = require('path').posix;
var utils = require('./utils');
const path = require('path').posix;
const Utils = require('./utils');

var Canonicalizer = function(hashAlgo) {
// node 0.11 urlencodes caret as %5E
var haveToFixCaretAtUrlParser = utils.parseUrl('^').href !== '^';
// node 0.11 urlencodes caret as %5E
const haveToFixCaretAtUrlParser = Utils.parseUrl('^').href !== '^';

// PRIVATE METHODS
class Canonicalizer {

function canonicalizeHeaders(headers) {
constructor(hashAlgo) {
this._hashAlgo = hashAlgo;
}

_canonicalizeHeaders(headers) {
return Object.keys(headers).map(function(key) {
return key + ':' + headers[key];
});
}

function canonicalizeQuery(query) {
canonicalizeQuery(query) {
function encodeComponent(component) {
return encodeURIComponent(component).replace(/\(/g, "%28").replace(/\)/g, "%29")
return encodeURIComponent(component).replace(/\(/g, "%28").replace(/\)/g, "%29");
}

function join(key, value) {
Expand All @@ -30,7 +33,7 @@ var Canonicalizer = function(hashAlgo) {
}

return Object.keys(query).map(function(key) {
var value = query[key];
const value = query[key];
if (typeof value === 'string') {
return join(key, value);
} else {
Expand All @@ -41,53 +44,45 @@ var Canonicalizer = function(hashAlgo) {
}).sort().join('&');
}

function prepareUri(uri) {
_prepareUri(uri) {
// https://github.com/joyent/node/blob/4b59db008cec1bfcca2783f4b27c630c9c3fdd73/lib/url.js#L113-L117
return uri.replace('#', '%23').replace('\\', '%5C');
}

function filterHeaders(headers, headersToSign) {
var filteredHeaders = {};
var normalizedSignedHeaders = headersToSign
.map(Function.prototype.call, String.prototype.toLowerCase);
_filterHeaders(headers, headersToSign) {
const filteredHeaders = {};
const normalizedSignedHeaders = headersToSign
.map(header => header.toLowerCase());

Object.keys(headers).forEach(function(headerName) {
if (normalizedSignedHeaders.indexOf(headerName) !== -1) {
if (normalizedSignedHeaders.includes(headerName)) {
filteredHeaders[headerName] = headers[headerName];
}
});

return filteredHeaders;
}

// PUBLIC METHODS

function canonicalizeRequest(requestOptions, body, headersToSign) {
var parsedUrl = utils.parseUrl(prepareUri(requestOptions.url), true);
var headers = filterHeaders(utils.normalizeHeaders(requestOptions.headers), headersToSign);
var lines = [
canonicalizeRequest(requestOptions, body, headersToSign) {
const parsedUrl = Utils.parseUrl(this._prepareUri(requestOptions.url), true);
const headers = this._filterHeaders(Utils.normalizeHeaders(requestOptions.headers), headersToSign);
const lines = [
requestOptions.method,
path.normalize(parsedUrl.pathname),
canonicalizeQuery(parsedUrl.query),
canonicalizeHeaders(headers).join('\n'),
this.canonicalizeQuery(parsedUrl.query),
this._canonicalizeHeaders(headers).join('\n'),
'',
Object.keys(headers).join(';'),
utils.hash(hashAlgo, body)
Utils.hash(this._hashAlgo, body)
];
return lines.join('\n');
}

function getCanonicalizedSignedHeaders(headers, headersToSign) {
var normalizedHeaders = filterHeaders(utils.normalizeHeaders(headers), headersToSign);
getCanonicalizedSignedHeaders(headers, headersToSign) {
const normalizedHeaders = this._filterHeaders(Utils.normalizeHeaders(headers), headersToSign);
return Object.keys(normalizedHeaders);
}

return {
canonicalizeQuery: canonicalizeQuery,
canonicalizeRequest: canonicalizeRequest,
getCanonicalizedSignedHeaders: getCanonicalizedSignedHeaders
};

};
}

module.exports = Canonicalizer;
Loading

0 comments on commit 3703d95

Please sign in to comment.