class BucketClient::DigitalOceanClient

Public Class Methods

new(client, id, secret, region) click to toggle source

@param [KirinHttp::Client] client Basic http client @param [String] id AWS id @param [String] secret AWS secret @param [String] region Region for bucket

# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 38
def initialize(client, id, secret, region)
        signer = AWS4RequestSigner.new(id, secret)
        @region = region
        @http = DigitalOceanHttpClient.new(signer, region, client)
        @acl_factory = DigitalOceanACLFactory.new
end

Public Instance Methods

create_bucket(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 60
def create_bucket(key)
        endpoint = "https://#{@region}.digitaloceanspaces.com/#{key}"
        resp = @http.query(:put, endpoint)
        success = resp.code === 200
        if success
                bucket = get_bucket! key
                OperationResult.new(success, "Bucket created", bucket, 200)
        else
                OperationResult.new(success, resp.content, nil, resp.code)
        end
end
delete_blob(uri) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 164
def delete_blob(uri)
        exist = exist_blob uri
        if exist
                delete_blob_if_exist uri
        else
                OperationResult.new(false, "Blob does not exist", nil, 404)
        end
end
delete_blob_if_exist(uri) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 154
def delete_blob_if_exist(uri)
        resp = @http.query :delete, uri
        success = resp.code === 204
        if success
                OperationResult.new(success, "Blob deleted", nil, resp.code)
        else
                OperationResult.new(success, resp.content, nil, resp.code)
        end
end
delete_bucket(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 81
def delete_bucket(key)
        endpoint = "https://#{@region}.digitaloceanspaces.com/#{key}"
        resp = @http.query(:delete, endpoint)
        success = resp.code === 204
        if success
                OperationResult.new(success, "Bucket deleted", nil, resp.code)
        else
                OperationResult.new(success, resp.content, nil, resp.code)
        end
end
delete_bucket_if_exist(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 72
def delete_bucket_if_exist(key)
        exist = exist_bucket key
        if exist
                delete_bucket key
        else
                OperationResult.new(true, "Bucket already deleted", nil, 204)
        end
end
exist_blob(uri) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 124
def exist_blob(uri)
        @http.query(:head, uri).code === 200
end
exist_bucket(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 45
def exist_bucket(key)
        resp = @http.query(:head, "https://#{@region}.digitaloceanspaces.com/#{key}")
        resp.code == 200
end
get_blob(uri) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 114
def get_blob(uri)
        resp = @http.query :get, uri
        success = resp.code === 200
        if success
                OperationResult.new(success, "OK", resp.content, resp.code)
        else
                OperationResult.new(success, resp.content, nil, resp.code)
        end
end
get_bucket!(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 92
def get_bucket!(key)
        DigitalOceanBucket.new(@region, @http, self, key)
end
put_blob(payload, uri) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 128
def put_blob(payload, uri)
        mime = MimeMagic.by_magic payload
        type = mime&.type || "text/plain"
        resp = @http.query :put, uri, payload, type, "application/xml"
        return OperationResult.new(false, resp.content, nil, 400) unless resp.code === 200
        url = Addressable::URI.parse uri
        bucket = url.path.split("/").find {|x| !x.nil? && !x.empty?}
        domain = url.host.split(".").first
        bucket = domain unless domain == @region
        is_public = bucket_public bucket
        return is_public unless is_public.success
        access = is_public.value ? :public : :private
        resp = set_blob_acl uri, access, 10
        return resp unless resp.code === 200
        OperationResult.new(true, "OK", uri, resp.code)
end
put_bucket(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 50
def put_bucket(key)
        exist = exist_bucket key
        if exist
                bucket = get_bucket! key
                OperationResult.new(true, "OK", bucket, 200)
        else
                create_bucket key
        end
end
set_get_cors(key, cors) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 96
def set_get_cors(key, cors)
        resp = set_cors key, cors, 10
        OperationResult.new(resp.code === 200, resp.content, nil, resp.code)
end
set_read_policy(key, access) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 101
def set_read_policy(key, access)
        raise ArgumentError.new("Read Policy not accepted") if access != :public && access != :private
        resp = set_bucket_acl key, access, 10
        return resp unless resp.success
        object_uri_resp = get_all_object_uri key
        return object_uri_resp unless object_uri_resp.success
        object_uri_resp.value.each do |uri|
                acl_resp = set_blob_acl uri, access, 10
                return acl_resp unless acl_resp.success
        end
        resp
end
update_blob(payload, uri) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 145
def update_blob(payload, uri)
        exist = exist_blob uri
        if exist
                put_blob payload, uri
        else
                OperationResult.new(false, "Blob does not exist", nil, 404)
        end
end

Private Instance Methods

acl_malformed(acl_xml) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 265
def acl_malformed(acl_xml)
        policy = acl_xml[:AccessControlPolicy]
        policy.nil? || policy.select {|k| !k[:Owner].nil?}.length == 0
end
acl_owner(acl_xml) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 270
def acl_owner(acl_xml)
        acl_xml[:AccessControlPolicy].select {|k| !k[:Owner].nil?}.first[:Owner][:ID]
end
bucket_public(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 175
def bucket_public(key)
        endpoint = "https://#{@region}.digitaloceanspaces.com/#{key}/?acl="
        resp = @http.query :get, endpoint
        success = resp.code === 200
        if success
                acl_xml = Ox.load(resp.content, mode: :hash)[:AccessControlPolicy]
                acl_xml.extend(ArrayHash)
                begin
                        uri = acl_xml.access(:AccessControlList).get(:Grant).access(:Grantee).access(:URI)
                        value = uri === "http://acs.amazonaws.com/groups/global/AllUsers"
                rescue
                        value = false
                end
                OperationResult.new(success, "OK", value, 200)
        else
                OperationResult.new(success, resp.content, nil, resp.code)
        end
end
cors_rule(cors) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 216
  def cors_rule(cors)
          "<CORSRule>
                <AllowedOrigin>#{cors}</AllowedOrigin>
                <AllowedMethod>GET</AllowedMethod>
                <AllowedHeader>*</AllowedHeader>
                <MaxAgeSeconds>3000</MaxAgeSeconds>
</CORSRule>"
  end
cors_xml(cors) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 211
def cors_xml(cors)
        rules = cors.map(&method(:cors_rule))
        "<CORSConfiguration>#{rules.join "\n"}</CORSConfiguration>"
end
get_all_object_uri(key) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 225
def get_all_object_uri(key)
        endpoint = "https://#{@region}.digitaloceanspaces.com/#{key}/"
        resp = @http.query :get, endpoint
        if resp.code === 200
                value = Ox.load(resp.content, mode: :hash)[:ListBucketResult]
                                .select {|k| !k[:Contents].nil?}
                                .map {|k| endpoint + k[:Contents][:Key]}
                OperationResult.new(true, "OK", value, resp.code)
        else
                OperationResult.new(false, resp.content, nil, resp.code)
        end
end
set_acl(endpoint, access, max, count) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 248
def set_acl(endpoint, access, max, count)
        error = "Failed too many times due to conflict"
        return OperationResult.new(false, error, nil, 400) if ++count === max
        acl = @http.query :get, endpoint
        return OperationResult.new(false, acl.content, nil, acl.code) if acl.code != 200
        acl_xml = Ox.load(acl.content, mode: :hash)
        return OperationResult.new(false, "ACL XML Malformed? Check value for XML", acl_xml, 400) if acl_malformed acl_xml
        owner_id = acl_owner acl_xml
        new_xml = @acl_factory.generate_acl access, owner_id
        resp = @http.query :put, endpoint, new_xml
        if resp.code === 409
                set_blob_acl uri, access, max, count
        else
                OperationResult.new resp.code === 200, resp.content, nil, resp.code
        end
end
set_blob_acl(uri, access, max, count = 0) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 238
def set_blob_acl(uri, access, max, count = 0)
        endpoint = uri + "?acl="
        set_acl endpoint, access, max, count
end
set_bucket_acl(key, access, max, count = 0) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 243
def set_bucket_acl(key, access, max, count = 0)
        endpoint = "https://#{@region}.digitaloceanspaces.com/#{key}/?acl="
        set_acl endpoint, access, max, count
end
set_cors(key, cors, max, count = 0) click to toggle source
# File lib/bucket_client/digital_ocean/digital_ocean_client.rb, line 194
def set_cors(key, cors, max, count = 0)
        failure = "Failed too many times due to conflict"
        return OperationResult.new(false, failure, nil, 400) if ++count === max
        endpoint = "https://#{@region}.digitaloceanspaces.com/#{key}/?cors="
        if cors.length > 0
                xml = cors_xml cors
                resp = @http.query :put, endpoint, xml
        else
                resp = @http.query :delete, endpoint, nil, "text/plain"
        end
        if resp.code === 409
                set_cors key, cors, max, count
        else
                resp
        end
end