module Shrine::Plugins::Lambda::AttacherMethods

Public Instance Methods

lambda_process(data) click to toggle source

Triggers AWS Lambda processing defined by the user in the uploader's `Shrine#lambda_process`, first checking if the specified Lambda function is available (raising an error if not).

Generates a random key, stores the key into the cached file metadata, and passes the key to the Lambda function for signing the request.

Stores the DB record class and name, attacher data atribute and uploader class names, into the context attribute of the Lambda function invokation payload. Also stores the cached file hash object and the generated path into the payload.

After the AWS Lambda function invocation, a `Shrine::Error` will be raised if the response is containing errors. No more response analysis is performed, because Lambda is invoked asynchronously (note the `invocation_type`: 'Event' in the `invoke` call). The results will be sent by Lambda by HTTP requests to the specified `callbackUrl`.

# File lib/shrine/plugins/shrine-lambda.rb, line 140
def lambda_process(data)
  cached_file = uploaded_file(data['attachment'])
  assembly = lambda_default_values
  assembly.merge!(store.lambda_process_versions(cached_file, context))
  function = assembly.delete(:function)
  raise Error, 'No Lambda function specified!' unless function
  raise Error, "Function #{function} not available on Lambda!" unless function_available?(function)

  prepare_assembly(assembly, cached_file, context)
  assembly[:context] = data.except('attachment', 'action', 'phase')
  response = lambda_client.invoke(function_name:   function,
                                  invocation_type: 'Event',
                                  payload:         assembly.to_json)
  raise Error, "#{response.function_error}: #{response.payload.read}" if response.function_error

  swap(cached_file) || _set(cached_file)
end
lambda_save(result) click to toggle source

Receives the `result` hash after Lambda request was authorized. The result could contain an array of processed file versions data hashes, or a single file data hash, if there were no versions and the original attached file was just moved to the target storage bucket.

Deletes the signing key, if it is present in the original file's metadata, converts the result to a JSON string, and writes this string into the `data_attribute` of the Shrine attacher's record.

Chooses the `save_method` either for the ActiveRecord or for Sequel, and saves the record. @param [Hash] result

# File lib/shrine/plugins/shrine-lambda.rb, line 167
def lambda_save(result)
  versions = result['versions']
  attr_content = if versions
                   tmp_hash = versions.inject(:merge!)
                   tmp_hash.dig('original', 'metadata')&.delete('key')
                   tmp_hash.to_json
                 else
                   result['metadata']&.delete('key')
                   result.to_json
                 end

  record.__send__(:"#{data_attribute}=", attr_content)
  save_method = if record.is_a?(ActiveRecord::Base)
                  :save
                elsif record.is_a?(::Sequel::Model)
                  :save_changes
                end
  record.__send__(save_method, validate: false)
end

Private Instance Methods

buckets_to_use(buckets) click to toggle source

@param [Array] buckets that will be sent to Lambda function for use

# File lib/shrine/plugins/shrine-lambda.rb, line 197
def buckets_to_use(buckets)
  buckets.map do |b|
    { b.to_s => { name: Shrine.storages[b].bucket.name, prefix: Shrine.storages[b].prefix } }
  end.inject(:merge!)
end
function_available?(function) click to toggle source

Checks if the specified Lambda function is available. @param [Symbol] function name

# File lib/shrine/plugins/shrine-lambda.rb, line 210
def function_available?(function)
  Shrine.opts[:lambda_function_list].map(&:function_name).include?(function.to_s)
end
get_upload_options(cached_file, context, storage) click to toggle source
# File lib/shrine/plugins/shrine-lambda.rb, line 224
def get_upload_options(cached_file, context, storage)
  options = store.opts[:upload_options][storage[0].to_sym]
  options = options.call(cached_file, context) if options.respond_to?(:call)
  options
end
lambda_client() click to toggle source

A cached instance of an AWS Lambda client.

# File lib/shrine/plugins/shrine-lambda.rb, line 204
def lambda_client
  @lambda_client ||= Shrine.lambda_client
end
lambda_default_values() click to toggle source
# File lib/shrine/plugins/shrine-lambda.rb, line 189
def lambda_default_values
  { callbackURL:    Shrine.opts[:callback_url],
    copy_original:  true,
    storages:       buckets_to_use(%i[cache store]),
    target_storage: :store }
end
prepare_assembly(assembly, cached_file, context) click to toggle source
# File lib/shrine/plugins/shrine-lambda.rb, line 214
def prepare_assembly(assembly, cached_file, context)
  assembly[:path] = store.generate_location(cached_file, context)
  assembly[:storages].each do |s|
    upload_options = get_upload_options(cached_file, context, s)
    s[1][:upload_options] = upload_options if upload_options
  end
  cached_file.metadata['key'] = SecureRandom.base64(12)
  assembly[:attachment] = cached_file
end