class ActiveStorage::Service::HorcruxService

Attributes

prefix[R]
services[R]
shares[R]
threshold[R]

Public Class Methods

new(shares:,threshold:,prefix:,services:) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 112
def initialize(shares:,threshold:,prefix:,services:)
  @shares, @threshold, @prefix, @services = shares, threshold, prefix, services
end

Public Instance Methods

delete(keys) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 87
def delete(keys)
  shardkeys = keys.split(',')
  shards = []
  i = 0
  while i < shardkeys.count
    j = 0
    while j < services.count
      if services[j][:service].exist?(shardkeys[i])
        services[j][:service].delete(shardkeys[i])
      end
      j = j + 1
    end
    i = i + 1
  end
end
delete_prefixed(*args) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 116
def delete_prefixed(*args)
  raise ActiveStorage::UnpreviewableError, "Horcrux does not implement delete by prefix yet"
end
download(keys) { |decode64| ... } click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 45
def download(keys,&block)
  shardkeys = keys.split(',')
  shards = []
  i = 0
  while i < shardkeys.count
    j = 0
    while j < services.count
      begin
        if services[j][:service].exist?(shardkeys[i])
          shard = services[j][:service].download(shardkeys[i])
          shards << shard
          break
        end
        j = j + 1
      rescue NotImplementedError
        begin
          shard = services[j][:service].download(shardkeys[i]).to_s
          if shard.match(/^invalid/)
            j = j + 1
          else
            shards << shard
            break
          end
        rescue RestClient::BadRequest
          j = j + 1
        end
      end
    end
    i = i + 1
  end
  secret = TSS.combine(shares: shards)
  if block_given?
    yield Base64.decode64(secret[:secret])
  else
    return Base64.decode64(secret[:secret])
  end
end
download_chunk(keys, range) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 83
def download_chunk(keys, range)
  raise ActiveStorage::UnpreviewableError, "Horcrux does not implement ranged download yet"
end
exist?(keys) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 120
def exist?(keys)
  localKeys = keys.split(',')
  i = 0
  while i < localKeys.count
    j = 0
    while j < services.count
      if services[j][:service].exist?(localKeys[i])
        return true
      end
      j = j + 1
    end
    i = i + 1
  end
  return false
end
path_for(*args) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 140
def path_for(*args)
  raise ActiveStorage::UnpreviewableError, "Horcrux does not implement path_for yet"
end
upload(key,io,checksum: nil, **options) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 13
def upload(key,io,checksum: nil, **options)
  data = io.tap(&:rewind).read
  base64Data = Base64.encode64(data)
  shards = TSS.split(secret: base64Data,threshold: @threshold,num_shares: @shares)
  i = 0
  main_key = ""
  servicesamples = []
  while i < shards.count
    if servicesamples.empty?
      servicesamples = services[0..-1]
    end
    svc = servicesamples.sample
    shardkey = SecureRandom.base58(key.length)

    scblob = Class.new Blob
    scblob.service = svc[:service]
    iofile = Tempfile.new(shardkey,"/tmp")
    iofile.write(shards[i])
    iofile.rewind
    myblob = scblob.create_and_upload! io:iofile, filename: ""
    iofile.close
    iofile.unlink

    main_key = main_key + "#{myblob.reload.key},"
    servicesamples.delete(svc)
    i = i + 1
  end
  main_blob = Blob.find_by_key(key)
  main_blob.key = main_key
  main_blob.save!
end
url(*args) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 136
def url(*args)
  raise ActiveStorage::UnpreviewableError, "Horcrux does not implement url yet"
end

Private Instance Methods

each_service(&block) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 146
def each_service(&block)
  [ *services ].each(&block)
end
perform_across_services(method, *args) click to toggle source
# File lib/active_storage/service/horcrux_service.rb, line 150
def perform_across_services(method, *args)
  # FIXME: Convert to be threaded
  each_service.collect do |service|
    service.public_send method, *args
  end
end