Permalink
Browse files

Added a bit of encapsulation

  • Loading branch information...
1 parent db337dc commit c77969d82a269ee69bb5b6d59c13eb59fd02d262 @maxnachlinger committed Feb 25, 2013
Showing with 79 additions and 74 deletions.
  1. +79 −74 lib/index.js
View
@@ -1,94 +1,99 @@
var crypto = require('crypto');
var querystring = require('querystring');
-var _config, _url, policyType, privateKey;
-module.exports.signUrl = function (url, config, signCb) {
- policyType = 'canned';
+module.exports = new Generator();
- var argErrors = sanityCheckArgs(url, config);
- if (argErrors) return signCb(new Error(argErrors));
+function Generator() {
+ var _config, _url, policyType, privateKey;
- _url = url;
- privateKey = config.privateKey;
- // since config is a reference, this ensures we don't introduce some side-effect in the calling code
- _config = JSON.parse(JSON.stringify(config), function (key, value) {
- if (['dateLessThan', 'dateGreaterThan'].indexOf(key) !== -1)
- value = new Date(value).getTime();
- return value;
- });
-
- var policy = JSON.stringify(buildPolicy());
- var signature = crypto.createSign('RSA-SHA1').update(policy).sign(privateKey, 'base64');
+ function _buildPolicy() {
+ _config.dateLessThan = Math.round(_config.dateLessThan / 1000);
+ var condition = {
+ "DateLessThan": {
+ "AWS:EpochTime": _config.dateLessThan
+ }
+ };
- var query = {
- "Signature": sanitizeForUrl(signature),
- "Key-Pair-Id": _config.keyPairId
- };
+ if (_config.dateGreaterThan) {
+ policyType = 'custom';
+ condition.DateGreaterThan = {
+ "AWS:EpochTime": Math.round(_config.dateGreaterThan / 1000)
+ };
+ }
+ if (_config.ipAddress) {
+ policyType = 'custom';
+ condition.IpAddress = {
+ "AWS:SourceIp": _config.ipAddress
+ };
+ }
- if (policyType === 'custom') {
- policy = new Buffer(policy, 'utf8').toString('base64');
- query.Policy = sanitizeForUrl(policy);
- } else {
- query.Expires = _config.dateLessThan;
+ return {
+ "Statement": [
+ {
+ "Resource": _url,
+ "Condition": condition
+ }
+ ]
+ };
}
- var newUrl = _url + (_url.indexOf('?') === -1 ? '?' : '&') + querystring.stringify(query);
- signCb(null, newUrl);
-};
-
-function buildPolicy() {
- _config.dateLessThan = Math.round(_config.dateLessThan / 1000);
- var condition = {
- "DateLessThan": {
- "AWS:EpochTime": _config.dateLessThan
+ function _sanityCheckArgs(url, config) {
+ var errors = [];
+ if (!url) errors.push('Error: url parameter is required');
+ if (!config) {
+ errors.push('Error: config parameter is required');
+ return errors.join(', ');
}
- };
- if (_config.dateGreaterThan) {
- policyType = 'custom';
- condition.DateGreaterThan = {
- "AWS:EpochTime": Math.round(_config.dateGreaterThan / 1000)
- };
+ ['privateKey', 'keyPairId', 'dateLessThan'].forEach(function (val) {
+ if (typeof config[val] === "undefined")
+ errors.push('Error: config.' + val + ' is required');
+ });
+
+ ['dateLessThan', 'dateGreaterThan'].forEach(function (val) {
+ if (!config[val]) return;
+ if (['[object Date]', '[object Number]'].indexOf(Object.prototype.toString.call(config[val])) === -1)
+ errors.push('Error: config.' + val + ' should be a Date object or a Number');
+ });
+
+ return errors.length > 0 ? errors.join(', ') : null;
}
- if (_config.ipAddress) {
- policyType = 'custom';
- condition.IpAddress = {
- "AWS:SourceIp": _config.ipAddress
- };
+
+ function _sanitizeForUrl(value) {
+ return value.replace(/\+/g, '-').replace(/\=/g, '_').replace(/\//g, '~');
}
- return {
- "Statement": [
- {
- "Resource": _url,
- "Condition": condition
- }
- ]
- };
-}
+ this.signUrl = function (url, config, signCb) {
+ policyType = 'canned';
-function sanityCheckArgs(url, config) {
- var errors = [];
- if (!url) errors.push('Error: url parameter is required');
- if (!config) {
- errors.push('Error: config parameter is required');
- return errors.join(', ');
- }
+ var argErrors = _sanityCheckArgs(url, config);
+ if (argErrors) return signCb(new Error(argErrors));
- ['privateKey', 'keyPairId', 'dateLessThan'].forEach(function (val) {
- if (typeof config[val] === "undefined")
- errors.push('Error: config.' + val + ' is required');
- });
+ _url = url;
+ privateKey = config.privateKey;
+ // since config is a reference, this ensures we don't introduce some side-effect in the calling code
+ _config = JSON.parse(JSON.stringify(config), function (key, value) {
+ if (['dateLessThan', 'dateGreaterThan'].indexOf(key) !== -1)
+ value = new Date(value).getTime();
+ return value;
+ });
- ['dateLessThan', 'dateGreaterThan'].forEach(function (val) {
- if (!config[val]) return;
- if (['[object Date]', '[object Number]'].indexOf(Object.prototype.toString.call(config[val])) === -1)
- errors.push('Error: config.' + val + ' should be a Date object or a Number');
- });
+ var policy = JSON.stringify(_buildPolicy());
+ var signature = crypto.createSign('RSA-SHA1').update(policy).sign(privateKey, 'base64');
- return errors.length > 0 ? errors.join(', ') : null;
-}
+ var query = {
+ "Signature": _sanitizeForUrl(signature),
+ "Key-Pair-Id": _config.keyPairId
+ };
-function sanitizeForUrl(value) {
- return value.replace(/\+/g, '-').replace(/\=/g, '_').replace(/\//g, '~');
+ if (policyType === 'custom') {
+ policy = new Buffer(policy, 'utf8').toString('base64');
+ query.Policy = _sanitizeForUrl(policy);
+ } else {
+ query.Expires = _config.dateLessThan;
+ }
+
+ var newUrl = _url + (_url.indexOf('?') === -1 ? '?' : '&') + querystring.stringify(query);
+ signCb(null, newUrl);
+ };
}

0 comments on commit c77969d

Please sign in to comment.