From 027d694aff072ac66a14316a9d90b7f2fa23ddd3 Mon Sep 17 00:00:00 2001 From: timtch Date: Fri, 1 May 2015 18:14:39 +0200 Subject: [PATCH 01/12] Support Content-Disposition non ASCII characters in file name, S3 --- services/aws-s3.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/aws-s3.js b/services/aws-s3.js index 01c6b98..3c0bcb6 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -89,7 +89,8 @@ Slingshot.S3Storage = { "Cache-Control": directive.cacheControl, "Content-Disposition": directive.contentDisposition || file.name && - "inline; filename=" + quoteString(file.name, '"') + "inline; filename=" + quoteString(file.name, '"') + + "; filename*=utf-8''" + encodeURIComponent(file.name) }, bucketUrl = _.isFunction(directive.bucketUrl) ? From 1edaa610548367de7fa43d7c44fb6600d2aadaad Mon Sep 17 00:00:00 2001 From: Jessica Graham Date: Tue, 12 May 2015 14:51:50 -0400 Subject: [PATCH 02/12] Add AWS session token as optional parameter for S3 --- README.md | 2 ++ services/aws-s3.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/README.md b/README.md index 106b88f..ba71b12 100644 --- a/README.md +++ b/README.md @@ -469,6 +469,8 @@ authorization will expire after the request was made. Default is 5 minutes. `AWSSecretAccessKey` String (**required**) - Can also be set in `Meteor.settings`. +`AWSSessionToken` String (optional) - Session token included in temporary security credentials. + #### Google Cloud Storage `bucket` String (**required**) - Name of bucket to use. The default is diff --git a/services/aws-s3.js b/services/aws-s3.js index 01c6b98..b56d449 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -2,6 +2,7 @@ Slingshot.S3Storage = { accessId: "AWSAccessKeyId", secretKey: "AWSSecretAccessKey", + sessionToken: "AWSSessionToken", directiveMatch: { bucket: String, @@ -15,6 +16,7 @@ Slingshot.S3Storage = { AWSAccessKeyId: String, AWSSecretAccessKey: String, + AWSSessionToken: Match.Optional(String), acl: Match.Optional(Match.Where(function (acl) { check(acl, String); @@ -145,6 +147,10 @@ Slingshot.S3Storage = { "x-amz-date": today + "T000000Z" }); + if (directive[this.sessionToken]) { + payload["x-amz-security-token"] = directive[this.sessionToken]; + } + payload.policy = policy.match(payload).stringify(); payload["x-amz-signature"] = this.signAwsV4(payload.policy, directive[this.secretKey], today, directive.region, service); From b007bc7491bcd4a2f870427d7bca568a861bd566 Mon Sep 17 00:00:00 2001 From: Jessica Graham Date: Tue, 12 May 2015 17:30:08 -0400 Subject: [PATCH 03/12] Use two-space indentation --- services/aws-s3.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/aws-s3.js b/services/aws-s3.js index b56d449..81ad919 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -148,7 +148,7 @@ Slingshot.S3Storage = { }); if (directive[this.sessionToken]) { - payload["x-amz-security-token"] = directive[this.sessionToken]; + payload["x-amz-security-token"] = directive[this.sessionToken]; } payload.policy = policy.match(payload).stringify(); From e11f3e75f68c86a4ec2855e14433c90b9d8e3fb5 Mon Sep 17 00:00:00 2001 From: Jessica Graham Date: Wed, 13 May 2015 08:11:55 -0400 Subject: [PATCH 04/12] Allow access key id, secret access key, and session token to be functions --- README.md | 11 +++++++---- services/aws-s3.js | 14 ++++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ba71b12..781444b 100644 --- a/README.md +++ b/README.md @@ -465,11 +465,14 @@ authorization will expire after the request was made. Default is 5 minutes. `region` String (optional) - Default is `Meteor.settings.AWSRegion` or "us-east-1". [See AWS Regions](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region) -`AWSAccessKeyId` String (**required**) - Can also be set in `Meteor.settings`. +`AWSAccessKeyId` String or Function (**required**) - Can also be set in `Meteor.settings`. If it is a function, there +are no arguments and the key (a string) is returned. -`AWSSecretAccessKey` String (**required**) - Can also be set in `Meteor.settings`. +`AWSSecretAccessKey` String or Function (**required**) - Can also be set in `Meteor.settings`. If it is a function, +there are no arguments and the key (a string) is returned. -`AWSSessionToken` String (optional) - Session token included in temporary security credentials. +`AWSSessionToken` String or Function (optional) - Session token included in temporary security credentials. If it is a +function, there are no arguments and the token (a string) is returned. #### Google Cloud Storage @@ -512,7 +515,7 @@ Default is the uploaded file's name (inline). Use null to disable. `region` String (optional) - Data Center region. The default is `"iad3"`. [See other regions](http://docs.rackspace.com/files/api/v1/cf-devguide/content/Service-Access-Endpoints-d1e003.html) -`pathPrefix` String or Function (**required**) - Simlar to `key` for S3, but will always be appended by `file.name` that is provided by the client. +`pathPrefix` String or Function (**required**) - Similar to `key` for S3, but will always be appended by `file.name` that is provided by the client. `deleteAt` Date (optional) - Absolute time when the uploaded file is to be deleted. _This attribute is not enforced at all. It can be easily altered by the client_ diff --git a/services/aws-s3.js b/services/aws-s3.js index 81ad919..b7d9fc4 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -14,9 +14,9 @@ Slingshot.S3Storage = { return /^[a-z]{2}-\w+-\d+$/.test(region); }), - AWSAccessKeyId: String, - AWSSecretAccessKey: String, - AWSSessionToken: Match.Optional(String), + AWSAccessKeyId: Match.OneOf(String, Function), + AWSSecretAccessKey: Match.OneOf(String, Function), + AWSSessionToken: Match.Optional(Match.OneOf(String, Function)), acl: Match.Optional(Match.Where(function (acl) { check(acl, String); @@ -138,7 +138,7 @@ Slingshot.S3Storage = { _.extend(payload, { "x-amz-algorithm": "AWS4-HMAC-SHA256", "x-amz-credential": [ - directive[this.accessId], + _.isFunction(directive[this.accessId]) ? directive[this.accessId]() : directive[this.accessId], today, directive.region, service, @@ -148,12 +148,14 @@ Slingshot.S3Storage = { }); if (directive[this.sessionToken]) { - payload["x-amz-security-token"] = directive[this.sessionToken]; + payload["x-amz-security-token"] = _.isFunction(directive[this.sessionToken]) ? directive[this.sessionToken]() : + directive[this.sessionToken]; } payload.policy = policy.match(payload).stringify(); payload["x-amz-signature"] = this.signAwsV4(payload.policy, - directive[this.secretKey], today, directive.region, service); + _.isFunction(directive[this.secretKey]) ? directive[this.secretKey]() : directive[this.secretKey], + today, directive.region, service); }, /** Generate a AWS Signature Version 4 From a4c10ef992cac93a49dac455168efabe36ff064a Mon Sep 17 00:00:00 2001 From: Jessica Graham Date: Wed, 13 May 2015 10:35:21 -0400 Subject: [PATCH 05/12] Require AWSSessionToken to be a function --- README.md | 4 ++-- services/aws-s3.js | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 781444b..68ffa68 100644 --- a/README.md +++ b/README.md @@ -471,8 +471,8 @@ are no arguments and the key (a string) is returned. `AWSSecretAccessKey` String or Function (**required**) - Can also be set in `Meteor.settings`. If it is a function, there are no arguments and the key (a string) is returned. -`AWSSessionToken` String or Function (optional) - Session token included in temporary security credentials. If it is a -function, there are no arguments and the token (a string) is returned. +`AWSSessionToken` Function (optional) - Takes no arguments and returns the session token from temporary security +credentials (a string). #### Google Cloud Storage diff --git a/services/aws-s3.js b/services/aws-s3.js index b7d9fc4..10d8ab9 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -16,7 +16,7 @@ Slingshot.S3Storage = { AWSAccessKeyId: Match.OneOf(String, Function), AWSSecretAccessKey: Match.OneOf(String, Function), - AWSSessionToken: Match.Optional(Match.OneOf(String, Function)), + AWSSessionToken: Match.Optional(Function), acl: Match.Optional(Match.Where(function (acl) { check(acl, String); @@ -148,8 +148,7 @@ Slingshot.S3Storage = { }); if (directive[this.sessionToken]) { - payload["x-amz-security-token"] = _.isFunction(directive[this.sessionToken]) ? directive[this.sessionToken]() : - directive[this.sessionToken]; + payload["x-amz-security-token"] = directive[this.sessionToken](); } payload.policy = policy.match(payload).stringify(); From 07461015d4bb4d7b5c8ef36326ea6ad9629bf2ff Mon Sep 17 00:00:00 2001 From: Jessica Graham Date: Wed, 13 May 2015 10:35:48 -0400 Subject: [PATCH 06/12] jshint --- services/aws-s3.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/aws-s3.js b/services/aws-s3.js index 10d8ab9..5dd2044 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -138,7 +138,8 @@ Slingshot.S3Storage = { _.extend(payload, { "x-amz-algorithm": "AWS4-HMAC-SHA256", "x-amz-credential": [ - _.isFunction(directive[this.accessId]) ? directive[this.accessId]() : directive[this.accessId], + _.isFunction(directive[this.accessId]) ? directive[this.accessId]() : + directive[this.accessId], today, directive.region, service, @@ -153,7 +154,8 @@ Slingshot.S3Storage = { payload.policy = policy.match(payload).stringify(); payload["x-amz-signature"] = this.signAwsV4(payload.policy, - _.isFunction(directive[this.secretKey]) ? directive[this.secretKey]() : directive[this.secretKey], + _.isFunction(directive[this.secretKey]) ? directive[this.secretKey]() : + directive[this.secretKey], today, directive.region, service); }, From b92d6f00d377f4c98d3f01e3db6839747354b71a Mon Sep 17 00:00:00 2001 From: gsuess Date: Mon, 18 May 2015 17:35:00 +0200 Subject: [PATCH 07/12] Added expiry date as argument to session token. --- README.md | 14 +++++++++----- services/aws-s3.js | 3 ++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 68ffa68..f1295dc 100644 --- a/README.md +++ b/README.md @@ -471,8 +471,8 @@ are no arguments and the key (a string) is returned. `AWSSecretAccessKey` String or Function (**required**) - Can also be set in `Meteor.settings`. If it is a function, there are no arguments and the key (a string) is returned. -`AWSSessionToken` Function (optional) - Takes no arguments and returns the session token from temporary security -credentials (a string). +`AWSSessionToken` Function (optional) - Takes an expiry date argumnet and +returns the session token from temporary security credentials (a string). #### Google Cloud Storage @@ -513,11 +513,15 @@ Default is the uploaded file's name (inline). Use null to disable. `container` String (**required**) - Name of container to use. -`region` String (optional) - Data Center region. The default is `"iad3"`. [See other regions](http://docs.rackspace.com/files/api/v1/cf-devguide/content/Service-Access-Endpoints-d1e003.html) +`region` String (optional) - Data Center region. The default is `"iad3"`. +[See other regions](http://docs.rackspace.com/files/api/v1/cf-devguide/content/Service-Access-Endpoints-d1e003.html) -`pathPrefix` String or Function (**required**) - Similar to `key` for S3, but will always be appended by `file.name` that is provided by the client. +`pathPrefix` String or Function (**required**) - Similar to `key` for S3, but +will always be appended by `file.name` that is provided by the client. -`deleteAt` Date (optional) - Absolute time when the uploaded file is to be deleted. _This attribute is not enforced at all. It can be easily altered by the client_ +`deleteAt` Date (optional) - Absolute time when the uploaded file is to be +deleted. _This attribute is not enforced at all. It can be easily altered by the +client_ `deleteAfter` Number (optional) - Same as `deleteAt`, but relative. diff --git a/services/aws-s3.js b/services/aws-s3.js index 2acb224..0f1318c 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -150,7 +150,8 @@ Slingshot.S3Storage = { }); if (directive[this.sessionToken]) { - payload["x-amz-security-token"] = directive[this.sessionToken](); + payload["x-amz-security-token"] = + directive[this.sessionToken](directive.expire); } payload.policy = policy.match(payload).stringify(); From c1c92bced0536288ee6c98754a66a9cff7ee3bce Mon Sep 17 00:00:00 2001 From: gsuess Date: Mon, 18 May 2015 19:28:51 +0200 Subject: [PATCH 08/12] #95 Single getter for all temporary credentials. Added `Slingshot.S3Storage.TempCredentials`. --- services/aws-s3.js | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/services/aws-s3.js b/services/aws-s3.js index 0f1318c..838e71b 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -2,7 +2,6 @@ Slingshot.S3Storage = { accessId: "AWSAccessKeyId", secretKey: "AWSSecretAccessKey", - sessionToken: "AWSSessionToken", directiveMatch: { bucket: String, @@ -14,9 +13,8 @@ Slingshot.S3Storage = { return /^[a-z]{2}-\w+-\d+$/.test(region); }), - AWSAccessKeyId: Match.OneOf(String, Function), - AWSSecretAccessKey: Match.OneOf(String, Function), - AWSSessionToken: Match.Optional(Function), + AWSAccessKeyId: String, + AWSSecretAccessKey: String, acl: Match.Optional(Match.Where(function (acl) { check(acl, String); @@ -74,9 +72,7 @@ Slingshot.S3Storage = { */ upload: function (method, directive, file, meta) { - var url = Npm.require("url"), - - policy = new Slingshot.StoragePolicy() + var policy = new Slingshot.StoragePolicy() .expireIn(directive.expire) .contentLength(0, Math.min(file.size, directive.maxSize || Infinity)), @@ -149,11 +145,6 @@ Slingshot.S3Storage = { "x-amz-date": today + "T000000Z" }); - if (directive[this.sessionToken]) { - payload["x-amz-security-token"] = - directive[this.sessionToken](directive.expire); - } - payload.policy = policy.match(payload).stringify(); payload["x-amz-signature"] = this.signAwsV4(payload.policy, _.isFunction(directive[this.secretKey]) ? directive[this.secretKey]() : @@ -181,6 +172,37 @@ Slingshot.S3Storage = { } }; +Slingshot.S3Storage.TempCredentials = _.defaults({ + + directiveMatch: _.chain(Slingshot.S3Storage.directiveMatch) + .omit("AWSAccessKeyId", "AWSSecretAccessKey") + .extend({ + sessionCredentials: Function + }) + .value(), + + directiveDefault: _.omit(Slingshot.S3Storage.directiveDefault, + "AWSAccessKeyId", "AWSSecretAccessKey"), + + applySignature: function (payload, policy, directive) { + var credentials = directive.sessionCredentials(directive.expire); + + check(credentials, Match.ObjectIncluding({ + AccessKeyId: Slingshot.S3Storage.directiveMatch.AWSAccessKeyId, + SecretAccessKey: Slingshot.S3Storage.directiveMatch.AWSSecretAccessKey, + SessionToken: String + })); + + payload["x-amz-security-token"] = credentials.SessionToken; + + return Slingshot.S3Storage.applySignature + .call(this, payload, policy, _.defaults({ + AWSAccessKeyId: credentials.AccessKeyId, + AWSSecretAccessKey: credentials.SecretAccessKey + }, directive)); + } +}, Slingshot.S3Storage); + function quoteString(string, quotes) { return quotes + string.replace(quotes, '\\' + quotes) + quotes; } From dbceecbd3601aec46691c12b79501bd290e1c755 Mon Sep 17 00:00:00 2001 From: gsuess Date: Mon, 18 May 2015 20:22:49 +0200 Subject: [PATCH 09/12] #95 Updated README --- README.md | 73 ++++++++++++++++++++++++++++++++++++++-------- services/aws-s3.js | 11 +++---- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index f1295dc..4224331 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,53 @@ Slingshot.createDirective("aws-s3-example", Slingshot.S3Storage, { }); ``` +#### S3 with temporary AWS Credentials (Advanced) + +For extra security you can use +[temporary credentials](http://docs.aws.amazon.com/STS/latest/UsingSTS/CreatingSessionTokens.html) to sign upload requests. + +```JavaScript +var sts = new AWS.STS(); // Using the AWS SDK to retrieve temporary credentials + +Slingshot.createDirective('myUploads', Slingshot.S3Storage.TempCredentials, { + bucket: 'myBucket', + temporaryCredentials: Meteor.wrapAsync(function (expire, callback) { + //AWS dictates that the minimum duration must be 900 seconds: + var duration = Math.max(Math.round(expire / 1000), 900); + + sts.getSessionToken({ + DurationSeconds: duration + }, function (error, result) { + callback(error, result && result.Credentials); + }); + }) +}); +``` + +If you are running slingshot on an EC2 instance, you can conveniantly retreive +your access keys with [`AWS.EC2MetadataCredentials`](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/EC2MetadataCredentials.html): + +```JavaScript +var credentials = new AWS.EC2MetadataCredentials(); + +var updateCredentials = Meteor.wrapAsync(credentials.get, credentials); + +Slingshot.createDirective('myUploads', Slingshot.S3Storage.TempCredentials, { + bucket: 'myBucket', + temporaryCredentials: function () { + if (credentials.needsRefresh()) { + updateCredentials(); + } + + return { + AccessKeyId: credentials.accessKeyId, + SecretAccessKey: credentials.secretAccessKey, + SessionToken: credentials.sessionToken + }; + }) +}); +``` + ### Google Cloud [Generate a private key](http://goo.gl/kxt5qz) and convert it to a `.pem` file @@ -457,24 +504,26 @@ i.e. `"https://d111111abcdef8.cloudfront.net"` `expire` Number (optional) - Number of milliseconds in which an upload authorization will expire after the request was made. Default is 5 minutes. -#### AWS S3 - -`bucket` String (**required**) - Name of bucket to use. The default is -`Meteor.settings.S3Bucket`. +#### AWS S3 (`Slingshot.S3Storage`) `region` String (optional) - Default is `Meteor.settings.AWSRegion` or "us-east-1". [See AWS Regions](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region) -`AWSAccessKeyId` String or Function (**required**) - Can also be set in `Meteor.settings`. If it is a function, there -are no arguments and the key (a string) is returned. +`AWSAccessKeyId` String (**required**) - Can also be set in `Meteor.settings`. + +`AWSSecretAccessKey` String (**required**) - Can also be set in `Meteor.settings`. -`AWSSecretAccessKey` String or Function (**required**) - Can also be set in `Meteor.settings`. If it is a function, -there are no arguments and the key (a string) is returned. +#### AWS S3 with Temporary Credentials (`Slingshot.S3Storage.TempCredentials`) + +`region` String (optional) - Default is `Meteor.settings.AWSRegion` or +"us-east-1". [See AWS Regions](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region) -`AWSSessionToken` Function (optional) - Takes an expiry date argumnet and -returns the session token from temporary security credentials (a string). +`temporaryCredentials` Function (**required**) - Function that generates temporary +credentials. It takes a signle argument, which is the minumum desired expiration +time in milli-seconds and it returns an object that contains `AccessKeyId`, +`SecretAccessKey` and `SessionToken`. -#### Google Cloud Storage +#### Google Cloud Storage (`Slingshot.GoogleCloud`) `bucket` String (**required**) - Name of bucket to use. The default is `Meteor.settings.GoogleCloudBucket`. @@ -505,7 +554,7 @@ the second is the meta-information that can be passed by the client. `contentDisposition` String (optional) - RFC 2616 Content-Disposition directive. Default is the uploaded file's name (inline). Use null to disable. -#### Rackspace Cloud +#### Rackspace Cloud (`Slingshot.RackspaceFiles`) `RackspaceAccountId` String (**required**) - Can also be set in `Meteor.settings`. diff --git a/services/aws-s3.js b/services/aws-s3.js index 838e71b..55d2ac5 100644 --- a/services/aws-s3.js +++ b/services/aws-s3.js @@ -135,8 +135,7 @@ Slingshot.S3Storage = { _.extend(payload, { "x-amz-algorithm": "AWS4-HMAC-SHA256", "x-amz-credential": [ - _.isFunction(directive[this.accessId]) ? directive[this.accessId]() : - directive[this.accessId], + directive[this.accessId], today, directive.region, service, @@ -147,9 +146,7 @@ Slingshot.S3Storage = { payload.policy = policy.match(payload).stringify(); payload["x-amz-signature"] = this.signAwsV4(payload.policy, - _.isFunction(directive[this.secretKey]) ? directive[this.secretKey]() : - directive[this.secretKey], - today, directive.region, service); + directive[this.secretKey], today, directive.region, service); }, /** Generate a AWS Signature Version 4 @@ -177,7 +174,7 @@ Slingshot.S3Storage.TempCredentials = _.defaults({ directiveMatch: _.chain(Slingshot.S3Storage.directiveMatch) .omit("AWSAccessKeyId", "AWSSecretAccessKey") .extend({ - sessionCredentials: Function + temporaryCredentials: Function }) .value(), @@ -185,7 +182,7 @@ Slingshot.S3Storage.TempCredentials = _.defaults({ "AWSAccessKeyId", "AWSSecretAccessKey"), applySignature: function (payload, policy, directive) { - var credentials = directive.sessionCredentials(directive.expire); + var credentials = directive.temporaryCredentials(directive.expire); check(credentials, Match.ObjectIncluding({ AccessKeyId: Slingshot.S3Storage.directiveMatch.AWSAccessKeyId, From 945a4599a96a4887d3426d438e1ce99eed8bb859 Mon Sep 17 00:00:00 2001 From: gsuess Date: Mon, 18 May 2015 20:24:54 +0200 Subject: [PATCH 10/12] #95 Fixed readme Removed extra bracket. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4224331..6913899 100644 --- a/README.md +++ b/README.md @@ -273,7 +273,7 @@ Slingshot.createDirective('myUploads', Slingshot.S3Storage.TempCredentials, { SecretAccessKey: credentials.secretAccessKey, SessionToken: credentials.sessionToken }; - }) + } }); ``` From 36ee40355237639125bb093806ff678dac056e0e Mon Sep 17 00:00:00 2001 From: Garik Suess Date: Mon, 18 May 2015 20:39:47 +0200 Subject: [PATCH 11/12] Changelog for 0.7.0 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1acc5b2..03bc10d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ Slingshot Changelog =================== + +## Version 0.7.0 + +### Enhancements + + * Added `Slingshot.S3Storage.TempCredentials`. Thanks @jossoco + +### Bug Fixes + + * Fixed character encoding for content-disposition for AWS-S3 based directives ([#95](https://github.com/CulturalMe/meteor-slingshot/issues/95)). Thanks @timtch. + ## Version 0.6.2 Removed debugging log. From d9e7e7260760b73139da42052ca69bdf0616ac81 Mon Sep 17 00:00:00 2001 From: Garik Suess Date: Mon, 18 May 2015 20:44:17 +0200 Subject: [PATCH 12/12] Bump Version --- package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.js b/package.js index 696278d..c8f3db7 100644 --- a/package.js +++ b/package.js @@ -1,7 +1,7 @@ Package.describe({ name: "edgee:slingshot", summary: "Directly post files to cloud storage services, such as AWS-S3.", - version: "0.6.2", + version: "0.7.0", git: "https://github.com/CulturalMe/meteor-slingshot" });