class Attache::VHost

Attributes

backup[RW]
bucket[RW]
download_headers[RW]
env[RW]
geometry_whitelist[RW]
headers_with_cors[RW]
remotedir[RW]
secret_key[RW]
storage[RW]

Public Class Methods

new(hash) click to toggle source
# File lib/attache/vhost.rb, line 12
def initialize(hash)
  self.env = hash || {}
  self.remotedir  = env['REMOTE_DIR'] # nil means no fixed top level remote directory, and that's fine.
  self.secret_key = env['SECRET_KEY'] # nil means no auth check; anyone can upload a file
  self.geometry_whitelist = env['GEOMETRY_WHITELIST'] # nil means everything is acceptable

  if env['FOG_CONFIG']
    self.bucket       = env['FOG_CONFIG'].fetch('bucket')
    self.storage      = Fog::Storage.new(env['FOG_CONFIG'].except('bucket').symbolize_keys)

    if env['BACKUP_CONFIG']
      backup_fog = env['FOG_CONFIG'].merge(env['BACKUP_CONFIG'])
      self.backup = Attache::VHost.new(env.except('BACKUP_CONFIG').merge('FOG_CONFIG' => backup_fog))
    end
  end
  self.download_headers = {
    "Cache-Control" => "public, max-age=31536000"
  }.merge(env['DOWNLOAD_HEADERS'] || {})
  self.headers_with_cors = {
    'Access-Control-Allow-Origin' => '*',
    'Access-Control-Allow-Methods' => 'POST, PUT',
    'Access-Control-Allow-Headers' => 'Content-Type',
  }.merge(env['UPLOAD_HEADERS'] || {})
end

Public Instance Methods

async(method, args) click to toggle source
# File lib/attache/vhost.rb, line 94
def async(method, args)
  ::Attache::Job.perform_async(method, env, args)
end
authorized?(params) click to toggle source
# File lib/attache/vhost.rb, line 98
def authorized?(params)
  secret_key.blank? || hmac_valid?(params)
end
backup_file(args) click to toggle source
# File lib/attache/vhost.rb, line 106
def backup_file(args)
  if backup
    key = File.join(*remotedir, args[:relpath])
    storage.copy_object(bucket, key, backup.bucket, key)
  end
end
hmac_for(content) click to toggle source
# File lib/attache/vhost.rb, line 37
def hmac_for(content)
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), secret_key, content)
end
hmac_valid?(params) click to toggle source
# File lib/attache/vhost.rb, line 41
def hmac_valid?(params)
  params['uuid'] &&
  params['hmac']  &&
  params['expiration'] &&
  Time.at(params['expiration'].to_i) > Time.now &&
  Rack::Utils.secure_compare(params['hmac'], hmac_for("#{params['uuid']}#{params['expiration']}"))
end
remote_api() click to toggle source
# File lib/attache/vhost.rb, line 90
def remote_api
  storage.directories.new(key: bucket).files
end
storage_create(args) click to toggle source
# File lib/attache/vhost.rb, line 66
def storage_create(args)
  Attache.logger.info "[JOB] uploading #{args[:cachekey].inspect}"
  body = begin
    Attache.cache.read(args[:cachekey])
  rescue Errno::ENOENT
    :no_entry # upload file no longer exist; likely deleted immediately after upload
  end
  unless body == :no_entry
    remote_api.create({
      key: File.join(*remotedir, args[:relpath]),
      body: body,
    })
    Attache.logger.info "[JOB] uploaded #{args[:cachekey]}"
  end
end
storage_destroy(args) click to toggle source
# File lib/attache/vhost.rb, line 82
def storage_destroy(args)
  Attache.logger.info "[JOB] deleting #{args[:relpath]}"
  remote_api.new({
    key: File.join(*remotedir, args[:relpath]),
  }).destroy
  Attache.logger.info "[JOB] deleted #{args[:relpath]}"
end
storage_get(args) click to toggle source
# File lib/attache/vhost.rb, line 62
def storage_get(args)
  open storage_url(args)
end
storage_url(args) click to toggle source
# File lib/attache/vhost.rb, line 49
def storage_url(args)
  object = remote_api.new({
    key: File.join(*remotedir, args[:relpath]),
  })
  result = if object.respond_to?(:url)
    object.url(Time.now + 600)
  else
    object.public_url
  end
ensure
  Attache.logger.info "storage_url: #{result}"
end
unauthorized() click to toggle source
# File lib/attache/vhost.rb, line 102
def unauthorized
  [401, headers_with_cors.merge('X-Exception' => 'Authorization failed'), []]
end