leifcr-refile-s3 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e6391fbbdde07b1caf059e6ddfdb2bee9e97dec28dfb05a49699b8d1a3f2ac08
4
+ data.tar.gz: 679e925a22687d19496404b58ec4ede066acd8982cd9840a1ecdcfbc4f0de18b
5
+ SHA512:
6
+ metadata.gz: 5934e43901031d47c6c94f1c4f883fb3bb1d46d59b514c96818b69f1052f733e58c4fc81e27ef5a0ff1050893f3347a6a6ffc78d9d9cf4ef8153c3ae670f2572
7
+ data.tar.gz: 379dca84ad3d4085b1f535e99d0261abbf1744b12fd0be9d15421cf358f5867176b97bb065c9fbeb820c09a25c7a703b885ff5475855136f61b6cc5eaef0e240
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ s3.yml
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in refile-s3.gemspec
4
+ gemspec
5
+
6
+ # gem "refile" #, github: "refile/refile"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Jonas Nicklas
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # Refile::S3
2
+
3
+ Amazon S3 backend for the [Refile][gh] gem. See the Refile documentation for
4
+ more details.
5
+
6
+ ## License
7
+
8
+ [MIT](LICENSE.txt)
9
+
10
+ [gh]: http://github.com/refile/refile
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: "spec"
7
+
data/lib/refile/s3.rb ADDED
@@ -0,0 +1,157 @@
1
+ require "aws-sdk-s3"
2
+ require "open-uri"
3
+ require "refile"
4
+ require "refile/s3/version"
5
+
6
+ module Refile
7
+
8
+ # @api private
9
+ class S3BackendError < StandardError; end
10
+
11
+ # @api private
12
+ class S3CredentialsError < S3BackendError
13
+ def message
14
+ "Credentials not found"
15
+ end
16
+ end
17
+
18
+ # A refile backend which stores files in Amazon S3
19
+ #
20
+ # @example
21
+ # backend = Refile::Backend::S3.new(
22
+ # region: "sa-east-1",
23
+ # bucket: "my-bucket",
24
+ # prefix: "files"
25
+ # )
26
+ # file = backend.upload(StringIO.new("hello"))
27
+ # backend.read(file.id) # => "hello"
28
+ class S3
29
+ extend Refile::BackendMacros
30
+
31
+ attr_reader :access_key_id, :max_size
32
+
33
+ # Sets up an S3 backend
34
+ #
35
+ # @param [String] region The AWS region to connect to
36
+ # @param [String] bucket The name of the bucket where files will be stored
37
+ # @param [String] prefix A prefix to add to all files. Prefixes on S3 are kind of like folders.
38
+ # @param [Integer, nil] max_size The maximum size of an uploaded file
39
+ # @param [#hash] hasher A hasher which is used to generate ids from files
40
+ # @param [Hash] s3_options Additional options to initialize S3 with
41
+ # @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/Core/Configuration.html
42
+ # @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3.html
43
+ def initialize(region:, bucket:, max_size: nil, prefix: nil, hasher: Refile::RandomHasher.new, **s3_options)
44
+ @s3_options = { region: region }.merge s3_options
45
+ @s3 = Aws::S3::Resource.new @s3_options
46
+ credentials = @s3.client.config.credentials
47
+ raise S3CredentialsError unless credentials
48
+ @access_key_id = credentials.access_key_id
49
+ @bucket_name = bucket
50
+ @bucket = @s3.bucket @bucket_name
51
+ @hasher = hasher
52
+ @prefix = prefix
53
+ @max_size = max_size
54
+ end
55
+
56
+ # Upload a file into this backend
57
+ #
58
+ # @param [IO] uploadable An uploadable IO-like object.
59
+ # @return [Refile::File] The uploaded file
60
+ verify_uploadable def upload(uploadable)
61
+ id = @hasher.hash(uploadable)
62
+
63
+ if uploadable.is_a?(Refile::File) and uploadable.backend.is_a?(S3) and uploadable.backend.access_key_id == access_key_id
64
+ object(id).copy_from(copy_source: [@bucket_name, uploadable.backend.object(uploadable.id).key].join("/"))
65
+ else
66
+ object(id).put(body: uploadable, content_length: uploadable.size)
67
+ end
68
+
69
+ Refile::File.new(self, id)
70
+ end
71
+
72
+ # Get a file from this backend.
73
+ #
74
+ # Note that this method will always return a {Refile::File} object, even
75
+ # if a file with the given id does not exist in this backend. Use
76
+ # {FileSystem#exists?} to check if the file actually exists.
77
+ #
78
+ # @param [String] id The id of the file
79
+ # @return [Refile::File] The retrieved file
80
+ verify_id def get(id)
81
+ Refile::File.new(self, id)
82
+ end
83
+
84
+ # Delete a file from this backend
85
+ #
86
+ # @param [String] id The id of the file
87
+ # @return [void]
88
+ verify_id def delete(id)
89
+ object(id).delete
90
+ end
91
+
92
+ # Return an IO object for the uploaded file which can be used to read its
93
+ # content.
94
+ #
95
+ # @param [String] id The id of the file
96
+ # @return [IO] An IO object containing the file contents
97
+ verify_id def open(id)
98
+ Kernel.open(object(id).presigned_url(:get))
99
+ end
100
+
101
+ # Return the entire contents of the uploaded file as a String.
102
+ #
103
+ # @param [String] id The id of the file
104
+ # @return [String] The file's contents
105
+ verify_id def read(id)
106
+ object(id).get.body.read
107
+ rescue Aws::S3::Errors::NoSuchKey
108
+ nil
109
+ end
110
+
111
+ # Return the size in bytes of the uploaded file.
112
+ #
113
+ # @param [String] id The id of the file
114
+ # @return [Integer] The file's size
115
+ verify_id def size(id)
116
+ object(id).get.content_length
117
+ rescue Aws::S3::Errors::NoSuchKey
118
+ nil
119
+ end
120
+
121
+ # Return whether the file with the given id exists in this backend.
122
+ #
123
+ # @param [String] id The id of the file
124
+ # @return [Boolean]
125
+ verify_id def exists?(id)
126
+ object(id).exists?
127
+ end
128
+
129
+ # Remove all files in this backend. You must confirm the deletion by
130
+ # passing the symbol `:confirm` as an argument to this method.
131
+ #
132
+ # @example
133
+ # backend.clear!(:confirm)
134
+ # @raise [Refile::Confirm] Unless the `:confirm` symbol has been passed.
135
+ # @param [:confirm] confirm Pass the symbol `:confirm` to confirm deletion.
136
+ # @return [void]
137
+ def clear!(confirm = nil)
138
+ raise Refile::Confirm unless confirm == :confirm
139
+ @bucket.objects(prefix: @prefix).delete
140
+ end
141
+
142
+ # Return a presign signature which can be used to upload a file into this
143
+ # backend directly.
144
+ #
145
+ # @return [Refile::Signature]
146
+ def presign
147
+ id = RandomHasher.new.hash
148
+ signature = @bucket.presigned_post(key: [*@prefix, id].join("/"))
149
+ signature.content_length_range(0..@max_size) if @max_size
150
+ Signature.new(as: "file", id: id, url: signature.url.to_s, fields: signature.fields)
151
+ end
152
+
153
+ verify_id def object(id)
154
+ @bucket.object([*@prefix, id].join("/"))
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,5 @@
1
+ module Refile
2
+ class S3
3
+ VERSION = "0.2.1"
4
+ end
5
+ end
data/refile-s3.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'refile/s3/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "leifcr-refile-s3"
8
+ spec.version = Refile::S3::VERSION
9
+ spec.authors = ["Jonas Nicklas"]
10
+ spec.email = ["jonas.nicklas@gmail.com"]
11
+ spec.summary = "Amazon S3 backend for the Refile gem"
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.required_ruby_version = ">= 2.1.0"
21
+
22
+ spec.add_dependency "leifcr-refile"
23
+ spec.add_dependency "aws-sdk-s3", "~> 1.36"
24
+ spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency "webmock"
28
+ end
@@ -0,0 +1,12 @@
1
+ require "refile/spec_helper"
2
+ require "refile/s3"
3
+
4
+ WebMock.allow_net_connect!
5
+
6
+ config = YAML.load_file("s3.yml").map { |k, v| [k.to_sym, v] }.to_h
7
+
8
+ RSpec.describe Refile::S3 do
9
+ let(:backend) { Refile::S3.new(max_size: 100, **config) }
10
+
11
+ it_behaves_like :backend
12
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leifcr-refile-s3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Jonas Nicklas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: leifcr-refile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-sdk-s3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.36'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.36'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email:
99
+ - jonas.nicklas@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - lib/refile/s3.rb
110
+ - lib/refile/s3/version.rb
111
+ - refile-s3.gemspec
112
+ - spec/refile/s3_spec.rb
113
+ homepage: ''
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: 2.1.0
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.0.3
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Amazon S3 backend for the Refile gem
136
+ test_files:
137
+ - spec/refile/s3_spec.rb