presigned_upload 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +28 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +30 -0
- data/Rakefile +12 -0
- data/lib/generators/presigned_upload/templates/migration.rb +12 -0
- data/lib/generators/presigned_upload/templates/uploadable_model.rb +3 -0
- data/lib/generators/presigned_upload/uploadable_model_generator.rb +38 -0
- data/lib/presigned_upload/adapter/aws.rb +77 -0
- data/lib/presigned_upload/adapter/base.rb +30 -0
- data/lib/presigned_upload/configuration.rb +58 -0
- data/lib/presigned_upload/errors.rb +7 -0
- data/lib/presigned_upload/models.rb +65 -0
- data/lib/presigned_upload/railtie.rb +18 -0
- data/lib/presigned_upload/storage.rb +44 -0
- data/lib/presigned_upload/uploadable.rb +76 -0
- data/lib/presigned_upload/version.rb +5 -0
- data/lib/presigned_upload.rb +28 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 651464bf9650c6acb0cbd6da5f0d3e1cb41bcf16c2825e32a64fd102e214917b
|
4
|
+
data.tar.gz: e07b382fd743b259a3196912dbb19eff4069e55381e20eb7b9a20f622b20aa88
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8b7f57130a706d1d5651652134b152cf51a4dcd6442382c8c608d22d2b3af1380048f6bca891a811559cc94f7bc892a017170962ea23f92f6d2149ccf98ea066
|
7
|
+
data.tar.gz: 9329538342ea4ae88cd2b571e92c6cc87512a2f8f455cf6332267768ebdc9d170da6daed49bad15ad276cf77d801d3210076b82fdb07c1bbaae1dae17598fded
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
Exclude:
|
4
|
+
- "lib/generators/**/templates/*"
|
5
|
+
NewCops: disable
|
6
|
+
|
7
|
+
Style/Documentation:
|
8
|
+
Enabled: true
|
9
|
+
Exclude:
|
10
|
+
- "lib/generators/presigned_upload/**"
|
11
|
+
- "spec/support/storage/*"
|
12
|
+
- "spec/support/*"
|
13
|
+
|
14
|
+
Style/StringLiterals:
|
15
|
+
Enabled: true
|
16
|
+
EnforcedStyle: double_quotes
|
17
|
+
|
18
|
+
Style/StringLiteralsInInterpolation:
|
19
|
+
Enabled: true
|
20
|
+
EnforcedStyle: double_quotes
|
21
|
+
|
22
|
+
Layout/LineLength:
|
23
|
+
Max: 120
|
24
|
+
|
25
|
+
Metrics/BlockLength:
|
26
|
+
Enabled: true
|
27
|
+
Exclude:
|
28
|
+
- "spec/**/*"
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Denis Stael
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# PresignedUpload
|
2
|
+
|
3
|
+
Gem designed to control file uploads via presigned URLs to cloud storage services.
|
4
|
+
|
5
|
+
A presigned URL is generated by a server that grants temporary and controlled access to a specific resource. In the context of file uploads, it allows clients to directly upload files to a designated storage location without the server being directly involved in the transfer process.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this to your Gemfile and run `bundle install`.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'presigned_upload'
|
13
|
+
```
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
```sh
|
17
|
+
gem install presigned_upload
|
18
|
+
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
TODO: Write usage instructions here
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
|
26
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/DenisStael/presigned_upload.
|
27
|
+
|
28
|
+
## License
|
29
|
+
|
30
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
class Create<%= model_name.camelize.pluralize %> < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :<%= model_name.underscore.pluralize + migration_id_column %> do |t|
|
4
|
+
t.string :original_name, null: false
|
5
|
+
t.string :content_type, null: false
|
6
|
+
t.string :store_path, null: false
|
7
|
+
t.string :upload_status, null: false
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
require "rails/generators/active_record"
|
5
|
+
|
6
|
+
module PresignedUpload
|
7
|
+
class UploadableModelGenerator < Rails::Generators::Base
|
8
|
+
include Rails::Generators::Migration
|
9
|
+
|
10
|
+
source_root File.expand_path("templates", __dir__)
|
11
|
+
|
12
|
+
argument :model_name, type: :string, desc: "Name of presigned uploadable model"
|
13
|
+
class_option :uuid, type: :boolean, default: false, desc: "Use UUID type for primary key"
|
14
|
+
|
15
|
+
def self.next_migration_number(path)
|
16
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_model_and_migration
|
20
|
+
generate_model
|
21
|
+
generate_migration
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def generate_model
|
27
|
+
template "uploadable_model.rb", File.join("app", "models", "#{model_name.underscore}.rb")
|
28
|
+
end
|
29
|
+
|
30
|
+
def migration_id_column
|
31
|
+
options.uuid? ? ", id: :uuid" : ""
|
32
|
+
end
|
33
|
+
|
34
|
+
def generate_migration
|
35
|
+
migration_template "migration.rb", "db/migrate/create_#{model_name.underscore.pluralize}.rb"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "presigned_upload/adapter/base"
|
4
|
+
|
5
|
+
module PresignedUpload
|
6
|
+
module Adapter
|
7
|
+
#
|
8
|
+
# The `Aws` class is an adapter for interacting with the Amazon Simple Storage Service (S3) using the AWS SDK.
|
9
|
+
# It inherits from `Adapter::Base` and implements methods for generating presigned URLs, uploading files,
|
10
|
+
# and deleting files.
|
11
|
+
#
|
12
|
+
# @see Adapter::Base
|
13
|
+
class Aws < Base
|
14
|
+
#
|
15
|
+
# Generates a presigned URL for the specified key, HTTP method, and expiration time.
|
16
|
+
#
|
17
|
+
# @param [String] key The key or identifier of the file in the storage.
|
18
|
+
# @param [Symbol] method The HTTP method for which the presigned URL is generated (e.g., :put, :get).
|
19
|
+
# @param [Integer] expires_in The duration in seconds for which the URL is valid.
|
20
|
+
#
|
21
|
+
# @return [String] The presigned URL for the specified key, method, and expiration time.
|
22
|
+
def presigned_url(key, method, expires_in)
|
23
|
+
bucket.object(key).presigned_url(method, expires_in: expires_in)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Uploads the specified file to the storage with the given key.
|
27
|
+
#
|
28
|
+
# @param [String] file The path to the local file to be uploaded.
|
29
|
+
# @param [String] key The key or identifier for the file in the storage.
|
30
|
+
#
|
31
|
+
# @return [void]
|
32
|
+
def upload_file(file, key)
|
33
|
+
object = bucket.object(key)
|
34
|
+
object.upload_file(file)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Deletes the file with the specified key from the storage.
|
38
|
+
#
|
39
|
+
# @param [String] key The key or identifier of the file to be deleted.
|
40
|
+
#
|
41
|
+
# @return [void]
|
42
|
+
def delete_file(key)
|
43
|
+
bucket.object(key).delete
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Returns the AWS S3 client for interacting with the service.
|
49
|
+
#
|
50
|
+
# @return [Aws::S3::Client] The AWS S3 client.
|
51
|
+
def client
|
52
|
+
@client ||= ::Aws::S3::Client.new
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the AWS S3 resource for interacting with S3 objects and buckets.
|
56
|
+
#
|
57
|
+
# @return [Aws::S3::Resource] The AWS S3 resource.
|
58
|
+
def resource
|
59
|
+
@resource ||= ::Aws::S3::Resource.new
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the name of the S3 bucket configured for storage.
|
63
|
+
#
|
64
|
+
# @return [String] The name of the S3 bucket.
|
65
|
+
def bucket_name
|
66
|
+
@bucket_name ||= storage_options[:bucket]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns the S3 bucket resource for the configured bucket name.
|
70
|
+
#
|
71
|
+
# @return [Aws::S3::Bucket] The S3 bucket resource.
|
72
|
+
def bucket
|
73
|
+
@bucket ||= resource.bucket(bucket_name)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PresignedUpload
|
4
|
+
#
|
5
|
+
# The `Adapter` module contains classes responsible for interfacing with different storage services.
|
6
|
+
# Each adapter class should inherit from `PresignedUpload::Adapter::Base`.
|
7
|
+
#
|
8
|
+
# @see PresignedUpload::Adapter::Base
|
9
|
+
module Adapter
|
10
|
+
# The `Base` class serves as the base class for all storage adapters in the `PresignedUpload` module.
|
11
|
+
# It provides a common interface for accessing storage configurations.
|
12
|
+
#
|
13
|
+
# @see PresignedUpload::Adapter
|
14
|
+
class Base
|
15
|
+
#
|
16
|
+
# Initializes a new instance of the adapter.
|
17
|
+
#
|
18
|
+
def initialize
|
19
|
+
@storage_options = PresignedUpload.configuration.storage_options
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
# Returns the storage configuration for the adapter.
|
25
|
+
#
|
26
|
+
# @return [Hash] The storage configuration.
|
27
|
+
attr_reader :storage_options
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PresignedUpload
|
4
|
+
#
|
5
|
+
# Configuration class
|
6
|
+
#
|
7
|
+
class Configuration
|
8
|
+
AVAILABLE_STORAGES = [:aws].freeze
|
9
|
+
|
10
|
+
attr_accessor :storage, :storage_options
|
11
|
+
attr_reader :adapter_class
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@storage = nil
|
15
|
+
@storage_options = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure!
|
19
|
+
unless AVAILABLE_STORAGES.include?(storage)
|
20
|
+
raise InvalidStorage, "Invalid storage. Allowed types are: #{AVAILABLE_STORAGES}"
|
21
|
+
end
|
22
|
+
|
23
|
+
raise InvalidStorageConfig, "Empty storage configuration" if storage_options.empty?
|
24
|
+
|
25
|
+
case storage
|
26
|
+
when :aws
|
27
|
+
load_aws
|
28
|
+
end
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def load_aws
|
36
|
+
require_aws_dependencies!
|
37
|
+
|
38
|
+
required_config_keys = [:bucket]
|
39
|
+
storage_options.each_key { |key| storage_options.except!(key) unless required_config_keys.include?(key) }
|
40
|
+
|
41
|
+
unless required_config_keys.all? { |key| storage_options.key?(key) }
|
42
|
+
raise InvalidStorageConfig, "Missing storage configuration. Required keys are: #{required_config_keys}"
|
43
|
+
end
|
44
|
+
|
45
|
+
@adapter_class = PresignedUpload::Adapter::Aws
|
46
|
+
end
|
47
|
+
|
48
|
+
def require_aws_dependencies!
|
49
|
+
unless defined?(::Aws::S3)
|
50
|
+
raise MissingDependency, "Missing required dependency\n
|
51
|
+
PresignedUpload requires 'aws-sdk-s3' gem to work properly with Aws S3 storage.\n
|
52
|
+
To fix this error, consider adding [gem 'aws-sdk-s3'] into your Gemfile."
|
53
|
+
end
|
54
|
+
|
55
|
+
require "presigned_upload/adapter/aws"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "presigned_upload/uploadable"
|
4
|
+
|
5
|
+
module PresignedUpload
|
6
|
+
#
|
7
|
+
# Module extended by ActiveRecord::Base to allow configuring models with resources of the gem
|
8
|
+
#
|
9
|
+
module Models
|
10
|
+
#
|
11
|
+
# Calling this method in the context of the model class includes Uploadable module, which makes
|
12
|
+
# available the methods for requesting presigned_urls and deleting file from the cloud storage
|
13
|
+
#
|
14
|
+
# @example:
|
15
|
+
#
|
16
|
+
# UploadLink < ApplicationRecord
|
17
|
+
# presigned_uploadable
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# upload_link = UploadLink.new
|
21
|
+
# upload_link.presigned_url('key', :get, expires_in = 3600)
|
22
|
+
# upload_link.delete_file('key')
|
23
|
+
#
|
24
|
+
def presigned_uploadable
|
25
|
+
include Uploadable
|
26
|
+
end
|
27
|
+
|
28
|
+
# rubocop:disable Metrics/MethodLength
|
29
|
+
#
|
30
|
+
# Calling this method in the context of the model class includes Uploadable::Model module, which includes
|
31
|
+
# all the behavior from the Uploadable module and the Uploadable::Model, including validations and callbacks
|
32
|
+
#
|
33
|
+
# @param [Hash] options Options hash
|
34
|
+
# @option options [Symbol] :store_path The path to the storage location
|
35
|
+
# Accepts a Symbol value, which will try to call a method with same name
|
36
|
+
# in model, a String value representing the store path or a Proc to call
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
#
|
40
|
+
# UploadLink < ApplicationRecord
|
41
|
+
# presigned_uploadable_model, store_path: :generate_store_path
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
def presigned_uploadable_model(options = {})
|
45
|
+
include Uploadable::Model
|
46
|
+
|
47
|
+
store_path = options[:store_path]
|
48
|
+
|
49
|
+
before_create do
|
50
|
+
self.store_path =
|
51
|
+
case store_path
|
52
|
+
when Symbol
|
53
|
+
__send__(store_path)
|
54
|
+
when String
|
55
|
+
store_path
|
56
|
+
when Proc
|
57
|
+
store_path.call
|
58
|
+
else
|
59
|
+
"uploads/#{model_name.plural}/#{original_name}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
# rubocop:enable Metrics/MethodLength
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/railtie"
|
4
|
+
require "presigned_upload/models"
|
5
|
+
|
6
|
+
# rubocop:disable Style/Documentation
|
7
|
+
|
8
|
+
module PresignedUpload
|
9
|
+
class Railtie < Rails::Railtie
|
10
|
+
initializer "presigned_upload.initialize" do
|
11
|
+
ActiveSupport.on_load(:active_record) do
|
12
|
+
ActiveRecord::Base.extend PresignedUpload::Models
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# rubocop:enable Style/Documentation
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PresignedUpload
|
4
|
+
# Storage module that provides a common interface for interacting with different storage adapters.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# class MyUploader
|
8
|
+
# include Storage
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# uploader = MyUploader.new
|
12
|
+
# url = uploader.presigned_url('key', :put, 3600)
|
13
|
+
# uploader.delete_file('key')
|
14
|
+
#
|
15
|
+
module Storage
|
16
|
+
# Generates a presigned URL for the specified key, HTTP method, and expiration time.
|
17
|
+
#
|
18
|
+
# @param [String] key The key or identifier of the file in the storage.
|
19
|
+
# @param [Symbol] method The HTTP method for which the presigned URL is generated (e.g., :put, :get).
|
20
|
+
# @param [Integer] expires_in The duration in seconds for which the URL is valid (default is 3600 seconds).
|
21
|
+
#
|
22
|
+
# @return [String] The presigned URL for the specified key and method.
|
23
|
+
def presigned_url(key, method, expires_in = 3600)
|
24
|
+
adapter.presigned_url(key, method, expires_in)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Deletes the file with the specified key from the storage.
|
28
|
+
#
|
29
|
+
# @param [String] key The key or identifier of the file to be deleted.
|
30
|
+
#
|
31
|
+
def delete_file(key)
|
32
|
+
adapter.delete_file(key)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Returns the storage adapter based on the configured storage type.
|
38
|
+
#
|
39
|
+
# @return [PresignedUpload::Adapter::Base] An instance of the configured storage adapter.
|
40
|
+
def adapter
|
41
|
+
@adapter ||= PresignedUpload.adapter_class.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "presigned_upload/storage"
|
4
|
+
require "active_support/concern"
|
5
|
+
|
6
|
+
module PresignedUpload
|
7
|
+
#
|
8
|
+
# The `Uploadable` module integrates storage functionality with a model, allowing handling
|
9
|
+
# file uploads and associated storage operations. It includes the capabilities provided by the
|
10
|
+
# `PresignedUpload::Storage` module.
|
11
|
+
#
|
12
|
+
# This module is designed to be included in ActiveRecord models to facilitate common file upload
|
13
|
+
# operations, such as generating presigned URLs, deleting stored files, and managing upload status.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
#
|
17
|
+
# class MyUploadableModel < ApplicationRecord
|
18
|
+
# include Uploadable::Model
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# model = MyUploadableModel.new(original_name: 'example.txt', content_type: 'text/plain', upload_status: :initial)
|
22
|
+
# model.upload_url # Generates a presigned URL for file upload.
|
23
|
+
# model.url # Retrieves a presigned URL for accessing the stored file.
|
24
|
+
#
|
25
|
+
# @see PresignedUpload::Storage
|
26
|
+
module Uploadable
|
27
|
+
include PresignedUpload::Storage
|
28
|
+
|
29
|
+
# The `Model` submodule extends ActiveSupport::Concern to provide upload-related functionality
|
30
|
+
# to ActiveRecord models.
|
31
|
+
module Model
|
32
|
+
extend ActiveSupport::Concern
|
33
|
+
|
34
|
+
include Uploadable
|
35
|
+
|
36
|
+
included do
|
37
|
+
attr_readonly :original_name, :content_type, :store_path
|
38
|
+
|
39
|
+
validates :original_name, :content_type, :upload_status, presence: true
|
40
|
+
|
41
|
+
enum upload_status: { initial: "initial", completed: "completed" }
|
42
|
+
|
43
|
+
after_destroy { delete_stored_file }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns a presigned URL for accessing the stored file. Returns `nil` if the upload status is not 'completed'.
|
47
|
+
#
|
48
|
+
# @return [String, nil] The presigned URL for accessing the stored file or `nil` if the
|
49
|
+
# upload status is not completed.
|
50
|
+
#
|
51
|
+
def url
|
52
|
+
return unless completed?
|
53
|
+
|
54
|
+
presigned_url(store_path, :get)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns a presigned URL for uploading the file. Returns `nil` if the store path is blank or the
|
58
|
+
# upload status is 'completed'.
|
59
|
+
#
|
60
|
+
# @return [String, nil] The presigned URL for uploading the file or `nil` if the upload status is
|
61
|
+
# 'completed' or store path is not present.
|
62
|
+
#
|
63
|
+
def upload_url
|
64
|
+
return if store_path.blank? || completed?
|
65
|
+
|
66
|
+
presigned_url(store_path, :put)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Deletes the stored file associated with the model.
|
70
|
+
#
|
71
|
+
def delete_stored_file
|
72
|
+
delete_file(store_path)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "presigned_upload/railtie"
|
4
|
+
require "presigned_upload/version"
|
5
|
+
require "presigned_upload/configuration"
|
6
|
+
require "presigned_upload/errors"
|
7
|
+
require "presigned_upload/adapter/base"
|
8
|
+
|
9
|
+
# The `PresignedUpload` module serves as the main module for the presigned file upload functionality.
|
10
|
+
# It provides configuration options, such as storage type and configuration settings.
|
11
|
+
#
|
12
|
+
module PresignedUpload
|
13
|
+
class << self
|
14
|
+
attr_accessor :configuration
|
15
|
+
|
16
|
+
def configure
|
17
|
+
self.configuration ||= Configuration.new
|
18
|
+
|
19
|
+
yield(configuration)
|
20
|
+
|
21
|
+
configuration.configure!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.adapter_class
|
26
|
+
@adapter_class ||= configuration.adapter_class
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: presigned_upload
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Denis Stael
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-11-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.21'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.21'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.4.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.4.2
|
55
|
+
description: ' "This gem provides an easy way to handle direct file uploads to
|
56
|
+
cloud storage services via presigned URL."
|
57
|
+
|
58
|
+
'
|
59
|
+
email:
|
60
|
+
- denissantistael@gmail.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".rspec"
|
66
|
+
- ".rubocop.yml"
|
67
|
+
- CHANGELOG.md
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE.txt
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- lib/generators/presigned_upload/templates/migration.rb
|
73
|
+
- lib/generators/presigned_upload/templates/uploadable_model.rb
|
74
|
+
- lib/generators/presigned_upload/uploadable_model_generator.rb
|
75
|
+
- lib/presigned_upload.rb
|
76
|
+
- lib/presigned_upload/adapter/aws.rb
|
77
|
+
- lib/presigned_upload/adapter/base.rb
|
78
|
+
- lib/presigned_upload/configuration.rb
|
79
|
+
- lib/presigned_upload/errors.rb
|
80
|
+
- lib/presigned_upload/models.rb
|
81
|
+
- lib/presigned_upload/railtie.rb
|
82
|
+
- lib/presigned_upload/storage.rb
|
83
|
+
- lib/presigned_upload/uploadable.rb
|
84
|
+
- lib/presigned_upload/version.rb
|
85
|
+
homepage: https://github.com/DenisStael/presigned_upload
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata:
|
89
|
+
homepage_uri: https://github.com/DenisStael/presigned_upload
|
90
|
+
source_code_uri: https://github.com/DenisStael/presigned_upload
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 2.6.0
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubygems_version: 3.3.7
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Control model associated files uploads via presigned URL to cloud storage
|
110
|
+
services.
|
111
|
+
test_files: []
|