¶ AwsS3Form |
|
¶ extends NPM:MPBasic |
|
¶ Exports: ClassGenerate a signed and reday to use formdata to put files to s3 directly from teh browser. Signing is done by using AWS Signature Version 4. |
|
npm modules |
|
internal modules Utils |
|
20
21 cryptoAdapter = require( "./cryptoAdapter" )
22
23 class AwsS3Form extends require( "mpbasic" )()
24
25 validation:
26 cryptoModules: [ "crypto", "crypto-js" ]
27 acl: [ "private", "public-read", "public-read-write", "authenticated-read", "bucket-owner-read", "bucket-owner-full-control" ]
28 successActionStatus: [200, 201, 204]
29
30
31 |
|
¶ defaults |
|
AwsS3Form.accessKeyId String AWS access key |
|
AwsS3Form.secretAccessKey String AWS access secret |
|
AwsS3Form.region String AWS region |
|
AwsS3Form.bucket String AWS bucket name |
|
AwsS3Form.secure Boolean Define if the action uses ssl. |
|
AwsS3Form.redirectUrlTemplate String|Function a redirect url template. |
|
AwsS3Form.redirectUrlTemplate Number HTTP code to return when no redirectUrlTemplate is defined. |
|
AwsS3Form.policyExpiration Date|Number Add time in seconds to now to define the expiration of the policy. Or set a hard Date. |
|
AwsS3Form.keyPrefix String Key prefix to define a policy that the key has to start with this value |
|
AwsS3Form.acl String The standard acl type. Only |
|
AwsS3Form.useUuid Boolean Use a uuid for better security |
|
AwsS3Form.cryptoModule String( enum: crypto|crypto-js) You can switch between the node internal crypo-module or the browser module cryptojs |
|
¶ create
create a new form object Params
filename
String
The S3 file key/filename to use.
[options]
Object
Create options
[options.acl]
String
Option to overwrite the general
acl
[options.secure]
String
Option to overwrite the general
secure
[options.keyPrefix]
String
Option to overwrite the general
keyPrefix
[options.contentType]
String
Boolean
Option to set the content type of the uploaded file. This could be a string with a fixed mime or a boolean to decide if the mime will be guessed by the filename.
[options.redirectUrlTemplate]
String
Option to overwrite the general
redirectUrlTemplate
[options.successActionStatus]
String
Option to overwrite the general
successActionStatus
[options.policyExpiration]
Number
Date
Option to overwrite the general
policyExpiration
API
public
|
|
contentType = mime.lookup( filename ) |
92
93
94 options.now = new Date()
95 if @config.useUuid
96 options.uuid = uuid.v4()
97
98 if options.contentType? and _.isString( options.contentType )
99 _cType = options.contentType
100 else if options.contentType
101 _cType = mime.lookup( filename )
102
103 _data =
104 acl: @_acl( options.acl )
105 credential: @_createCredential( options.now )
106 amzdate: @_shortDate( options.now )
107 contentType: _cType
108
109 if options.redirectUrlTemplate?
110 _data.success_action_redirect = @_redirectUrl( options.redirectUrlTemplate, filename: filename )
111 else
112 if _.isString( options.successActionStatus )
113 options.successActionStatus = parseInt( options.successActionStatus, 10 )
114 _data.success_action_status = @_successActionStatus( options.successActionStatus )
115
116 _policyB64 = @_obj2b64( @policy( filename, options, _data ) )
117
118 _signature = @sign( _policyB64, options )
119
120 if options.secure?
121 _secure = options.secure
122 else
123 _secure = @config.secure
124
125 data =
126 action: "#{ if _secure then "https" else "http" }://s3-#{@config.region}.amazonaws.com/#{ @config.bucket }"
127 filefield: "file"
128 fields:
129 key: "#{( options.keyPrefix or @config.keyPrefix )}#{filename}"
130 acl: _data.acl
131 "X-Amz-Credential": _data.credential
132 "X-Amz-Algorithm": "AWS4-HMAC-SHA256"
133 "X-Amz-Date": _data.amzdate
134 "Policy": _policyB64
135 "X-Amz-Signature": _signature.toString()
136
137 if options.redirectUrlTemplate?
138 data.fields.success_action_redirect = @_redirectUrl( options.redirectUrlTemplate, filename: filename )
139 else
140 data.fields.success_action_status = @_successActionStatus( options.successActionStatus )
141
142 if options.uuid?
143 data.fields[ "x-amz-meta-uuid" ] = options.uuid
144
145 if _cType?
146 data.fields[ "Content-Type" ] = _cType
147
148 return data
149
150
151 |
¶ policy
Create a new policy object based on AWS Signature Version 4. Params
filename
String
The S3 file key/filename to use.
[options]
Object
Policy options
[options.now]
String
The current date-time for this policy
[options.uuid]
String
The uuid to add to the policy
[options.acl]
String
Option to overwrite the general
acl
[options.keyPrefix]
String
Option to overwrite the general
keyPrefix
[options.customConditions]
Array
Option to set s3 upload conditions. For details see http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
[options.redirectUrlTemplate]
String
Option to overwrite the general
redirectUrlTemplate
[options.policyExpiration]
Number
Date
Option to overwrite the general
policyExpiration
API
public
|
168
169 policy: ( filename, options = {}, _predef = {} )=>
170 _date = options.now or new Date()
171
172 policy =
173 expiration: @_calcDate( options.policyExpiration or @config.policyExpiration, _date )
174 conditions: [
175 { "bucket": @config.bucket }
176 [ "starts-with", "$key", ( options.keyPrefix or @config.keyPrefix ) ]
177 { "acl": _predef.acl or @_acl( options.acl ) }
178 { "x-amz-credential": _predef.credential or @_createCredential( _date ) }
179 { "x-amz-algorithm": "AWS4-HMAC-SHA256" }
180 { "x-amz-date": _predef.amzdate or @_shortDate( _date ) }
181
182 |
[ "starts-with", "$Content-Type", contentType ] ["content-length-range", 0, @settings.maxFileSize ] |
182
183 ]
184
185 if _predef.success_action_status?
186 policy.conditions.push { "success_action_status": _predef.success_action_status.toString()}
187 else
188 policy.conditions.push { "success_action_redirect": _predef.success_action_redirect or @_redirectUrl( options.redirectUrlTemplate, filename: filename ) }
189
190 _ctypeCondition = false
191 if options.customConditions?
192 for ccond in options.customConditions
193 policy.conditions.push ccond
194 if ( _.isArray( ccond ) and _.isString( ccond[ 1 ] ) and ccond[ 1 ].toLowerCase() is "$content-type" ) or ( _.isObject( ccond ) and ccond["content-type"]? )
195 _ctypeCondition = true
196
197 if not _ctypeCondition and _predef?.contentType?
198 policy.conditions.push { "content-type": _predef.contentType }
199
200 @debug "generated policy", policy
201 if options.uuid?
202 policy.conditions.push { "x-amz-meta-uuid": options.uuid }
203
204 return policy
205
206
207 |
¶ sign
Create a AWS Signature Version 4. This is used to create the signature out of the policy. Params
policyB64
String
Base64 encoded policy
[options]
Object
sign options
[options.now=`new
String
Date()`] The current date-time for this signature
[options.signdate=converted
String
options.now ] signature date
[options.secretAccessKey]
String
Change the configured standard
secretAccessKey type.
[options.region]
String
Option to overwrite the general
region
API
public
|
221
222 sign: ( policyB64, options )=>
223 _date = options.now or new Date()
224 _signdate = options.signdate or @_shortDate( _date, true )
225
226 _h1 = cryptoAdapter.hmacSha256( "AWS4" + ( options.secretAccessKey or @config.secretAccessKey ), _signdate, "utf8" )
227 _h2 = cryptoAdapter.hmacSha256( _h1, ( options.region or @config.region ) )
228 _h3 = cryptoAdapter.hmacSha256( _h2, "s3" )
229 _key = cryptoAdapter.hmacSha256( _h3, "aws4_request" )
230
231 return cryptoAdapter.hmacSha256( _key, policyB64 )
232
233
234 |
¶ _acl
validate the given acl or get the default Params
[acl=`config.acl`]
String
the S3 acl
Returns
String
A valid acl
API
private
|
|
¶ _redirectUrl
Get the default redirect template or process the given sting as lodash template or call teh given function Params
tmpl
String
Function
A lodash template or function to generate the redirect url. If
null general redirectUrlTemplate will be used.
data
Object
The data object for template or function args. Usual example:
{ "filename": "the-filename-from-create-or-policy.jpg" }
Returns
String
A redirect url
API
private
|
264
265 _redirectUrl: ( tmpl = @config.redirectUrlTemplate, data = {} )=>
266 if not tmpl?
267 return @_handleError( null, "ENOREDIR" )
268
269 if _.isString( tmpl )
270 return _.template( tmpl )( data )
271 else if _.isFunction( tmpl )
272 return tmpl( data )
273 else
274 return @_handleError( null, "EINVALIDREDIR" )
275
276
277 |
¶ _successActionStatus
Gets the HTTP status code that AWS will return if a redirectUrlTemplate is not defined. Params
status
Number
The status code that should be set on successful upload
Returns
Number
A redirect url
API
private
|
|
¶ _calcDate
Calculate and validate a date Params
addSec
Number
Date
A date to convert or a number in seconds to add to the date out of the
date arg.
[date=`new
Date
Date()
] A base date for adding if the first argument addSec` is a number.
Returns
String
A date ISO String
API
private
|
307
308 _calcDate: ( addSec, date = new Date() )=>
309 _msAdd = 0
310 _now = Date.now()
311
312 if _.isNumber( addSec )
313 _msAdd = addSec * 1000
314 if _.isDate( date )
315 _ts = date.valueOf()
316 else if _.isNumber( date )
317 _ts = date
318 else
319 return @_handleError( null, "ENOTDATE", val: date )
320 else if _.isDate( addSec )
321 _ts = addSec.valueOf()
322 else
323 return @_handleError( null, "ENOTDATE", val: addSec )
324
325
326 |
use a 10s time space to the past to check the date |
|
¶ _createCredential
Generate a AWS Signature Version 4 conform credential string Params
date
Date
the credential date
Returns
String
a valid AWS Signature Version 4 credential string
API
private
|
|
¶ _shortDate
Create a AWS valid date string Params
[date=`new
Date
Date()`] The date to process
[onlyDate=false]
Boolean
Return only the date and cut the time
Returns
String
a AWS valid date string
API
private
|
|
¶ _setCryptoModule
Define the crypto module type Params
cryptoModule
String
The secret module to require. ( Enum:
crypto , crypto-js )
API
private
|
|
¶ _obj2b64
Srtingify a object and return it base64 encoded. Used to convert the policy result to the base64 string required by the Params
obj
Object
A object to stringify
Returns
String
Base64 encoded JSON
API
private
|
399
400 _obj2b64: ( obj )->
401 return new Buffer( JSON.stringify( obj ) ).toString('base64')
402
403 ERRORS: =>
404 "EINVALIDCRYPTOMODULE": [ 500, "The given cryptoModule `<%= val %>` is not valid. Only `#{@validation.cryptoModules.join('`, `')}` is allowed." ]
405 "ENOTDATE": [ 500, "Invalid date `<%= val %>`. Please use a valid date object or number as timestamp" ]
406 "EOLDDATE": [ 500, "Date `<%= val %>` to old. Only dates in the future are allowed" ]
407 "EINVALIDACL": [ 500, "The given acl `<%= val %>` is not valid. Only `#{@validation.acl.join('`, `')}` is allowed." ]
408 "EINVALIDSTATUS": [ 500, "The given successActionStatus `<%= val %>` is not valid. Only `#{@validation.successActionStatus.join('`, `')}` is allowed." ]
409 "ENOREDIR": [ 500, "You have to define a `redirectUrlTemplate` as config or `.create()` option." ]
410 "EINVALIDREDIR": [ 500, "Only a string or function is valid as redirect url." ]
411
412
413
414 |
export this class |