From 0bb532f7a6cdd75ec76cb127e926c7ff7a046d3c Mon Sep 17 00:00:00 2001 From: cintamani Date: Fri, 7 Jun 2019 13:50:27 +0100 Subject: [PATCH] Implement presigned url method in the Bucket object An handy method to generate a presigned url to download CSV files from the bucket. --- README.md | 9 ++++++ lib/defra_ruby/aws.rb | 2 ++ lib/defra_ruby/aws/bucket.rb | 4 +++ .../aws/services/bucket_loader_service.rb | 17 ++-------- .../concerns/has_aws_bucket_configuration.rb | 22 +++++++++++++ .../aws/services/presigned_url_service.rb | 32 +++++++++++++++++++ .../services/presigned_url_service_spec.rb | 32 +++++++++++++++++++ 7 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 lib/defra_ruby/aws/services/concerns/has_aws_bucket_configuration.rb create mode 100644 lib/defra_ruby/aws/services/presigned_url_service.rb create mode 100644 spec/lib/defra_ruby/aws/services/presigned_url_service_spec.rb diff --git a/README.md b/README.md index 7d62031..5f49cb2 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ end ## Usage +### Upload a file + ``` file_to_upload = Tempfile.new("test-upload-file.csv") bucket = DefraRuby::Aws.get_bucket("defra-ruby-aws") @@ -58,6 +60,13 @@ else end ``` +### Generate a presigned URL for download + +``` +bucket = DefraRuby::Aws.get_bucket("defra-ruby-aws") +presigned_url = bucket.presigned_url("test-upload-file.csv") +``` + ## Contributing to this project If you have an idea you'd like to contribute please log an issue. diff --git a/lib/defra_ruby/aws.rb b/lib/defra_ruby/aws.rb index 5a607b4..0e8127a 100644 --- a/lib/defra_ruby/aws.rb +++ b/lib/defra_ruby/aws.rb @@ -4,7 +4,9 @@ require_relative "aws/response" require_relative "aws/configuration" +require_relative "aws/services/concerns/has_aws_bucket_configuration" require_relative "aws/services/bucket_loader_service" +require_relative "aws/services/presigned_url_service" module DefraRuby module Aws diff --git a/lib/defra_ruby/aws/bucket.rb b/lib/defra_ruby/aws/bucket.rb index 2a086b5..669585d 100644 --- a/lib/defra_ruby/aws/bucket.rb +++ b/lib/defra_ruby/aws/bucket.rb @@ -25,6 +25,10 @@ def load(file) BucketLoaderService.run(self, file) end + def presigned_url(file_name) + PresignedUrlService.run(self, file_name) + end + private attr_writer :region diff --git a/lib/defra_ruby/aws/services/bucket_loader_service.rb b/lib/defra_ruby/aws/services/bucket_loader_service.rb index 363ab9b..e36984d 100644 --- a/lib/defra_ruby/aws/services/bucket_loader_service.rb +++ b/lib/defra_ruby/aws/services/bucket_loader_service.rb @@ -3,6 +3,8 @@ module DefraRuby module Aws class BucketLoaderService + include HasAwsBucketConfiguration + def self.run(bucket, file) new(bucket, file).run end @@ -20,21 +22,6 @@ def run attr_reader :bucket, :file - def s3_bucket - s3.bucket(bucket.bucket_name) - end - - def s3 - ::Aws::S3::Resource.new( - region: bucket.region, - credentials: aws_credentials - ) - end - - def aws_credentials - ::Aws::Credentials.new(bucket.access_key_id, bucket.secret_access_key) - end - def response_exe lambda do s3_bucket.object(File.basename(file.path)).upload_file(file.path, server_side_encryption: :AES256) diff --git a/lib/defra_ruby/aws/services/concerns/has_aws_bucket_configuration.rb b/lib/defra_ruby/aws/services/concerns/has_aws_bucket_configuration.rb new file mode 100644 index 0000000..5bef12e --- /dev/null +++ b/lib/defra_ruby/aws/services/concerns/has_aws_bucket_configuration.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module DefraRuby + module Aws + module HasAwsBucketConfiguration + def s3_bucket + s3.bucket(bucket.bucket_name) + end + + def s3 + ::Aws::S3::Resource.new( + region: bucket.region, + credentials: aws_credentials + ) + end + + def aws_credentials + ::Aws::Credentials.new(bucket.access_key_id, bucket.secret_access_key) + end + end + end +end diff --git a/lib/defra_ruby/aws/services/presigned_url_service.rb b/lib/defra_ruby/aws/services/presigned_url_service.rb new file mode 100644 index 0000000..266c2f2 --- /dev/null +++ b/lib/defra_ruby/aws/services/presigned_url_service.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module DefraRuby + module Aws + class PresignedUrlService + include HasAwsBucketConfiguration + + def self.run(bucket, file_name) + new(bucket, file_name).run + end + + def initialize(bucket, file_name) + @bucket = bucket + @file_name = file_name + end + + def run + s3_bucket.object(file_name).presigned_url( + :get, + expires_in: 20 * 60, # 20 minutes in seconds + secure: true, + response_content_type: "text/csv", + response_content_disposition: "attachment; filename=#{file_name}" + ) + end + + private + + attr_reader :bucket, :file_name + end + end +end diff --git a/spec/lib/defra_ruby/aws/services/presigned_url_service_spec.rb b/spec/lib/defra_ruby/aws/services/presigned_url_service_spec.rb new file mode 100644 index 0000000..b0db9c4 --- /dev/null +++ b/spec/lib/defra_ruby/aws/services/presigned_url_service_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require "spec_helper" + +module DefraRuby + module Aws + RSpec.describe PresignedUrlService do + describe ".run" do + let(:configs) do + { + name: "test", + credentials: { + access_key_id: "123", + secret_access_key: "Secret" + } + } + end + let(:bucket) { Bucket.new(configs) } + let(:presigned_url) { described_class.run(bucket, "testfile.csv") } + + it "returns a presigned url for a given file in the bucket" do + expect(presigned_url).to include("https://test.s3.eu-west-1.amazonaws.com/testfile.csv") + expect(presigned_url).to include("response-content-disposition=attachment") + expect(presigned_url).to include("response-content-type=text%2Fcsv") + expect(presigned_url).to include("Amz-Expires") + expect(presigned_url).to include("Amz-Credential") + expect(presigned_url).to include("Amz-Signature") + end + end + end + end +end