presigned_upload 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|