class ActiveStorage::Service::OpenStackService

Attributes

client[R]
container[R]

Public Class Methods

new(container:, credentials:, connection_options: {}) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 7
def initialize(container:, credentials:, connection_options: {})
  settings =
    if connection_options.present?
      credentials.reverse_merge(connection_options: connection_options)
    else
      credentials
    end

  @client = Fog::OpenStack::Storage.new(settings)
  @container = Fog::OpenStack.escape(container)
end

Public Instance Methods

delete(key) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 48
def delete(key)
  instrument :delete, key: key do
    begin
      client.delete_object(container, key)
    rescue Fog::OpenStack::Storage::NotFound
      false
    end
  end
end
delete_prefixed(prefix) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 58
def delete_prefixed(prefix)
  instrument :delete, prefix: prefix do
    directory = client.directories.get(container)
    filtered_files = client.files(directory: directory, prefix: prefix)
    filtered_files = filtered_files.map(&:key)

    client.delete_multiple_objects(container, filtered_files)
  end
end
download(key, &block) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 30
def download(key, &block)
  if block_given?
    instrument :streaming_download, key: key do
      object_for(key, &block).body
    end
  else
    instrument :download, key: key do
      object_for(key).body
    end
  end
end
download_chunk(key, range) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 42
def download_chunk(key, range)
  instrument :download_chunk, key: key, range: range do
    object_for(key).body[range]
  end
end
exist?(key) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 68
def exist?(key)
  instrument :exist, key: key do |payload|
    begin
      answer = object_for(key)
      payload[:exist] = answer
    rescue Fog::OpenStack::Storage::NotFound
      payload[:exist] = false
    end
  end
end
headers_for_direct_upload(key, content_type:, content_length:, checksum:) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 119
def headers_for_direct_upload(key, content_type:, content_length:, checksum:)
  {
    'Content-Type' => content_type,
    'Etag' => convert_base64digest_to_hexdigest(checksum),
    'Content-Length' => content_length,
  }
end
upload(key, io, checksum: nil, **) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 19
def upload(key, io, checksum: nil, **)
  instrument :upload, key: key, checksum: checksum do
    params = {}.merge(etag: convert_base64digest_to_hexdigest(checksum))
    begin
      client.put_object(container, key, io, params)
    rescue Excon::Error::UnprocessableEntity
      raise ActiveStorage::IntegrityError
    end
  end
end
url(key, expires_in:, disposition:, filename:, content_type:) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 79
def url(key, expires_in:, disposition:, filename:, content_type:)
  instrument :url, key: key do |payload|
    expire_at = unix_timestamp_expires_at(expires_in)
    generated_url =
      client.get_object_https_url(
        container,
        key,
        expire_at,
        disposition: disposition,
        filename: filename,
        content_type: content_type
      )

    payload[:url] = generated_url
    generated_url
  end
end
url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 97
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
  instrument :url, key: key do |payload|
    expire_at = unix_timestamp_expires_at(expires_in)

    generated_url =
      client.create_temp_url(
        container,
        key,
        expire_at,
        'PUT',
        port: 443,
        scheme: "https",
        content_type: content_type,
        content_length: content_length,
        etag: convert_base64digest_to_hexdigest(checksum)
      )

    payload[:url] = generated_url
    generated_url
  end
end

Private Instance Methods

convert_base64digest_to_hexdigest(base64digest) click to toggle source

ActiveStorage sends a `Digest::MD5.base64digest` checksum OpenStack expects a `Digest::MD5.hexdigest` Etag

# File lib/active_storage/service/open_stack_service.rb, line 134
def convert_base64digest_to_hexdigest(base64digest)
  base64digest.unpack('m0').first.unpack('H*').first if base64digest
end
format_range(range) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 142
def format_range(range)
  " bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}"
end
object_for(key, &block) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 128
def object_for(key, &block)
  client.get_object(container, key, &block)
end
unix_timestamp_expires_at(seconds_from_now) click to toggle source
# File lib/active_storage/service/open_stack_service.rb, line 138
def unix_timestamp_expires_at(seconds_from_now)
  Time.current.advance(seconds: seconds_from_now).to_i
end