Skip to content

Instantly share code, notes, and snippets.

@tdegrunt
Created December 11, 2011 22:08
Show Gist options
  • Save tdegrunt/1463057 to your computer and use it in GitHub Desktop.
Save tdegrunt/1463057 to your computer and use it in GitHub Desktop.
Batman - SecureRestStorage, using HMAC Authorization
# Needs
# http://crypto-js.googlecode.com/files/2.3.0-crypto-sha256-hmac.js
pad = (n) -> if n < 10 then "0" + n else n
# Sat, 08 Oct 2011 16:55:39 GMT
timestamp = () ->
now = new Date()
year = now.getUTCFullYear()
month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][now.getUTCMonth()]
dow = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][now.getUTCDay()]
day = pad(now.getUTCDate())
hours = pad(now.getUTCHours())
minutes = pad(now.getUTCMinutes())
seconds = pad(now.getUTCSeconds())
"#{dow}, #{day} #{month} #{year} #{hours}:#{minutes}:#{seconds} GMT"
sign_request = (options, key, secret) ->
options.headers ?= {}
options.headers.Date ?= timestamp()
canonical_string = options.method + "\n"
# TODO
canonical_string += (options.headers['Content-Type'] || '') + "\n"
# TODO (Need to do this as close to the jQuery call as possible)
canonical_string += (options.headers['Content-MD5'] || '') + "\n"
canonical_string += options.headers.Date + "\n"
canonical_string += options.url || ''
hmac_signature_base64 = Crypto.HMAC Crypto.SHA256, canonical_string, secret, canonical_string
options.headers['Authorization'] = "AuthHMAC #{key}:#{hmac_signature_base64}"
options
applyExtra = (Batman) ->
Batman.mixin Batman.Encoders,
railsDate:
encode: (value) -> value
decode: (value) ->
a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value)
if a
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]))
else
Batman.developer.warn "Unrecognized rails date #{value}!"
return Date.parse(value)
# Secure Rest Storage, based on RailsStorage
class Batman.SecureRestStorage extends Batman.RestStorage
recordJsonNamespace: (record) ->
false
collectionJsonNamespace: (proto) ->
false
#_addJsonExtension: (options) ->
#options.url += '.json'
optionsForRecord: (args..., callback) ->
super args..., (err, options) ->
#@_addJsonExtension(options) unless err
callback.call @, err, options
optionsForCollection: (args..., callback) ->
super args..., (err, options) ->
#@_addJsonExtension(options) unless err
callback.call @, err, options
@::before 'readAll', 'read', 'create', 'update', 'destroy', @skipIfError (env, next) ->
sign_request env.options, 'username', 'secret'
next()
@::after 'update', 'create', ([err, record, response, recordOptions]) ->
console.log response
# Rails validation errors
console.log err
console.dir err
if err
if err.request.get('status') is 422
for key, validationErrors of JSON.parse(err.request.get('response'))
record.get('errors').add(key, "#{key} #{validationError}") for validationError in validationErrors
return [record.get('errors'), record, response, recordOptions]
return arguments[0]
if (module? && require?)
module.exports = applyExtra
else
applyExtra(Batman)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment