fileboost 0.1.1 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b0218cd56f2e874e631b1d0bab51c86e8fb2b0b91bdcd2c2879877bf1b2a64f
4
- data.tar.gz: 3bd21ff3ba8f05f640c99a6003f2ca3da29feeca59d642a3230870705c7f21ab
3
+ metadata.gz: c4fec62d9be1b012648ceccd75eaa24a75c64ce4d3ae2e4d3fa060e08960de70
4
+ data.tar.gz: 67fbe1d13e4ec43b47c9517b3acddff6fc7a35a930b670cd15be781474d4824f
5
5
  SHA512:
6
- metadata.gz: 8d85be5931908aed5d46285b2bf8b27bc70031987b2c7c643989694a0bd688a1e5c8fa442aa7598092a5e6f8d197c91c1973d26d33b2b031933a98f23acba58d
7
- data.tar.gz: 82a9468ba2967c5cbc6bba6edcbc1faecdc962f6f50f913f179babcd18b86f610135a74f8b99a523f102e5f2a0e920e030159c701fdf082a4287cbd0dbb74424
6
+ metadata.gz: add42effb51bb5a83eaf754365d703ab6c9161f2c8aa7b7297b1aee99194e02f8b706eae6cf04e2f9137683c13c52dc5aa57451a94a7d5dffaa7246b479508a9
7
+ data.tar.gz: 56ebbea598301c491c2cfef190c9cdb15716b9621874beb8e5f3a007c4da2ba9c27303cf1784cd89a35daed9039ec81f961849576f588bed975ccebfdd675a15
data/README.md CHANGED
@@ -205,17 +205,6 @@ $ bundle exec rubocop
205
205
  6. Push to the branch (`git push origin my-new-feature`)
206
206
  7. Create new Pull Request
207
207
 
208
- ## Fileboost.dev Service
209
-
210
- To use Fileboost, you'll need access to the Fileboost.dev image optimization service at `cdn.fileboost.dev`. The service:
211
-
212
- 1. Receives requests at `https://cdn.fileboost.dev/{project_id}/path/to/activestorage/blob`
213
- 2. Verifies HMAC signatures using your secret token
214
- 3. Applies transformations based on query parameters
215
- 4. Returns optimized images
216
-
217
- The service handles ActiveStorage blob URLs and applies image transformations on-the-fly.
218
-
219
208
  ## License
220
209
 
221
210
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -224,4 +213,3 @@ The gem is available as open source under the terms of the [MIT License](https:/
224
213
 
225
214
  - [GitHub Issues](https://github.com/bilalbudhani/fileboost/issues)
226
215
  - [Documentation](https://github.com/bilalbudhani/fileboost/wiki)
227
- - [Cloudflare Worker Setup Guide](https://github.com/bilalbudhani/fileboost-worker)
data/Rakefile CHANGED
@@ -1,8 +1,7 @@
1
1
  require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
2
4
 
3
- APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
- load "rails/tasks/engine.rake"
5
-
6
- load "rails/tasks/statistics.rake"
5
+ RSpec::Core::RakeTask.new(:spec)
7
6
 
8
- require "bundler/gem_tasks"
7
+ task default: :spec
@@ -11,7 +11,7 @@ module Fileboost
11
11
  end
12
12
 
13
13
  def valid?
14
- project_id.present? && token.present?
14
+ !project_id.empty? && !token.empty?
15
15
  end
16
16
 
17
17
  def base_url
@@ -26,4 +26,4 @@ module Fileboost
26
26
  def self.configure
27
27
  yield(config) if block_given?
28
28
  end
29
- end
29
+ end
@@ -7,11 +7,5 @@ module Fileboost
7
7
  include Fileboost::Helpers
8
8
  end
9
9
  end
10
-
11
- initializer "fileboost.active_storage" do
12
- ActiveSupport.on_load :active_storage_blob do
13
- # Extend ActiveStorage::Blob with fileboost-specific methods if needed
14
- end
15
- end
16
10
  end
17
11
  end
@@ -1,57 +1,7 @@
1
1
  module Fileboost
2
- class ErrorHandler
3
- class << self
4
- def handle_with_fallback(error_context, &block)
5
- begin
6
- yield
7
- rescue StandardError => e
8
- log_error(error_context, e)
9
-
10
- if Fileboost.config.fallback_to_rails
11
- yield_fallback if block_given?
12
- else
13
- nil
14
- end
15
- end
16
- end
17
-
18
- def handle_gracefully(error_context, default_value = nil, &block)
19
- begin
20
- yield
21
- rescue StandardError => e
22
- log_error(error_context, e)
23
- default_value
24
- end
25
- end
26
-
27
- private
28
-
29
- def log_error(context, error)
30
- return unless defined?(Rails) && Rails.logger
31
-
32
- Rails.logger.warn(
33
- "[Fileboost] Error in #{context}: #{error.class}: #{error.message}"
34
- )
35
-
36
- # Log backtrace in development for debugging
37
- if Rails.env.development?
38
- Rails.logger.debug(
39
- "[Fileboost] Backtrace:\n#{error.backtrace.take(5).join("\n")}"
40
- )
41
- end
42
- end
43
-
44
- def yield_fallback
45
- # This would be implemented by the calling code
46
- # The pattern is to pass a fallback block when needed
47
- nil
48
- end
49
- end
50
- end
51
-
52
2
  # Specific exception classes for better error handling
53
3
  class ConfigurationError < StandardError; end
54
4
  class SignatureGenerationError < StandardError; end
55
5
  class UrlBuildError < StandardError; end
56
6
  class AssetPathExtractionError < StandardError; end
57
- end
7
+ end
@@ -18,9 +18,6 @@ module Fileboost
18
18
  # Generate the optimized URL
19
19
  optimized_url = fileboost_url_for(asset, resize: resize_options)
20
20
 
21
- # Return empty string if no URL could be generated
22
- return "" if optimized_url.blank?
23
-
24
21
  # Use the optimized URL with Rails image_tag for consistency
25
22
  image_tag(optimized_url, **options)
26
23
  end
@@ -36,16 +33,10 @@ module Fileboost
36
33
  # fileboost_url_for(user.avatar.blob, resize: { w: 1200, h: 400, q: 85 })
37
34
  def fileboost_url_for(asset, **options)
38
35
  # Validate that asset is an ActiveStorage object
39
- unless valid_activestorage_asset?(asset)
40
- Rails.logger.error("[Fileboost] Invalid asset type #{asset.class}. Only ActiveStorage objects are supported.") if defined?(Rails)
41
- return nil
42
- end
36
+ raise ArgumentError, "Invalid asset type #{asset.class}. Only ActiveStorage objects are supported." unless valid_activestorage_asset?(asset)
43
37
 
44
38
  # Validate configuration
45
- unless Fileboost.config.valid?
46
- log_configuration_warning
47
- return nil
48
- end
39
+ raise Fileboost::ConfigurationError, "Invalid Fileboost configuration" unless Fileboost.config.valid?
49
40
 
50
41
  # Build the optimized URL
51
42
  Fileboost::UrlBuilder.build_url(asset, **options)
@@ -71,10 +62,13 @@ module Fileboost
71
62
  sizes.each do |size_config|
72
63
  suffix = size_config[:suffix] || size_config["suffix"]
73
64
  size_options = size_config.except(:suffix, "suffix")
74
- combined_options = base_options.merge(size_options)
65
+
66
+ # Merge size options into base resize options
67
+ merged_resize_options = (base_options[:resize] || {}).merge(size_options)
68
+ combined_options = base_options.merge(resize: merged_resize_options)
75
69
 
76
70
  url = fileboost_url_for(asset, **combined_options)
77
- urls[suffix] = url if url.present?
71
+ urls[suffix] = url if !url.nil? && !url.empty?
78
72
  end
79
73
 
80
74
  urls
@@ -91,17 +85,5 @@ module Fileboost
91
85
 
92
86
  false
93
87
  end
94
-
95
- # Log configuration warnings
96
- def log_configuration_warning
97
- missing_configs = []
98
- missing_configs << "project_id" if Fileboost.config.project_id.blank?
99
- missing_configs << "token" if Fileboost.config.token.blank?
100
-
101
- Rails.logger.warn(
102
- "[Fileboost] Configuration incomplete. Missing: #{missing_configs.join(', ')}. " \
103
- "Set FILEBOOST_PROJECT_ID and FILEBOOST_TOKEN environment variables or configure them in your initializer."
104
- ) if defined?(Rails)
105
- end
106
88
  end
107
89
  end
@@ -3,42 +3,17 @@ require "base64"
3
3
 
4
4
  module Fileboost
5
5
  class SignatureGenerator
6
- def self.generate(project_id:, asset_path:, params: {})
7
- return nil unless project_id.present? && asset_path.present? && Fileboost.config.token.present?
8
-
6
+ def self.generate(asset_path:, params: {})
9
7
  # Sort parameters for consistent signature generation
10
8
  sorted_params = params.sort.to_h
11
9
  query_string = sorted_params.map { |k, v| "#{k}=#{v}" }.join("&")
12
10
 
13
11
  # Create the signing string: project_id:asset_path:sorted_query_params
14
- signing_string = [project_id, asset_path, query_string].join(":")
15
- Rails.logger.debug("signature payload #{project_id}, #{asset_path}, #{query_string}, #{Fileboost.config.token}")
12
+ signing_string = [ Fileboost.config.project_id, asset_path, query_string ].join(":")
16
13
  # Generate HMAC-SHA256 signature for secure authentication with Fileboost.dev
17
14
  digest = OpenSSL::HMAC.digest("SHA256", Fileboost.config.token, signing_string)
18
15
  # Use URL-safe base64 encoding and remove padding for maximum URL compatibility
19
16
  Base64.urlsafe_encode64(digest, padding: false)
20
- rescue StandardError => e
21
- if defined?(Rails) && Rails.env.development?
22
- raise e
23
- else
24
- Rails.logger.warn("[Fileboost] Failed to generate signature: #{e.message}") if defined?(Rails)
25
- nil
26
- end
27
- end
28
-
29
- def self.verify_signature(project_id:, asset_path:, params: {}, signature:)
30
- expected_signature = generate(project_id: project_id, asset_path: asset_path, params: params)
31
- return false if expected_signature.nil? || signature.nil?
32
-
33
- # Use secure comparison to prevent timing attacks
34
- ActiveSupport::SecurityUtils.secure_compare(signature, expected_signature)
35
- rescue StandardError => e
36
- if defined?(Rails) && Rails.env.development?
37
- raise e
38
- else
39
- Rails.logger.warn("[Fileboost] Failed to verify signature: #{e.message}") if defined?(Rails)
40
- false
41
- end
42
17
  end
43
18
  end
44
19
  end
@@ -31,44 +31,36 @@ module Fileboost
31
31
  RESIZE_PARAMS = %w[w width h height q quality f format b blur br brightness c contrast r rotation fit].freeze
32
32
 
33
33
  def self.build_url(asset, **options)
34
- return nil unless Fileboost.config.valid?
35
-
34
+ raise ConfigurationError, "Invalid configuration" unless Fileboost.config.valid?
35
+
36
36
  asset_path = extract_asset_path(asset)
37
- return nil unless asset_path.present?
37
+ raise AssetPathExtractionError, "Unable to extract asset path" unless !asset_path.nil? && !asset_path.empty?
38
38
 
39
39
  project_id = Fileboost.config.project_id
40
40
  base_url = Fileboost.config.base_url
41
-
41
+
42
42
  # Build the full asset URL path for Fileboost.dev service
43
43
  full_path = "/#{project_id}#{asset_path}"
44
-
44
+
45
45
  # Extract and normalize transformation parameters
46
46
  transformation_params = extract_transformation_params(options)
47
-
47
+
48
48
  # Generate HMAC signature for secure authentication
49
49
  signature = Fileboost::SignatureGenerator.generate(
50
- project_id: project_id,
51
50
  asset_path: asset_path,
52
51
  params: transformation_params
53
52
  )
54
-
55
- return nil unless signature
56
-
53
+
54
+ raise SignatureGenerationError, "Failed to generate signature" unless signature
55
+
57
56
  # Add signature to parameters
58
57
  all_params = transformation_params.merge("sig" => signature)
59
-
58
+
60
59
  # Build final URL
61
60
  uri = URI.join(base_url, full_path)
62
61
  uri.query = URI.encode_www_form(all_params) unless all_params.empty?
63
-
62
+
64
63
  uri.to_s
65
- rescue StandardError => e
66
- if defined?(Rails) && Rails.env.development?
67
- raise e
68
- else
69
- Rails.logger.warn("[Fileboost] Failed to build URL: #{e.message}") if defined?(Rails)
70
- nil
71
- end
72
64
  end
73
65
 
74
66
  private
@@ -78,57 +70,48 @@ module Fileboost
78
70
  when ActiveStorage::Blob
79
71
  # ActiveStorage Blob
80
72
  Rails.application.routes.url_helpers.rails_blob_path(asset, only_path: true)
81
-
73
+
82
74
  when ActiveStorage::Attached
83
75
  # ActiveStorage Attachment (has_one_attached, has_many_attached)
84
- if asset.respond_to?(:blob) && asset.blob.present?
76
+ if asset.respond_to?(:blob) && !asset.blob.nil?
85
77
  Rails.application.routes.url_helpers.rails_blob_path(asset.blob, only_path: true)
86
78
  else
87
- Rails.logger.warn("[Fileboost] ActiveStorage attachment has no blob") if defined?(Rails)
88
- nil
79
+ raise AssetPathExtractionError, "ActiveStorage attachment has no blob"
89
80
  end
90
-
81
+
91
82
  when ActiveStorage::VariantWithRecord
92
83
  # ActiveStorage Variant - use blob URL to avoid triggering variant generation
93
84
  Rails.application.routes.url_helpers.rails_blob_path(asset.blob, only_path: true)
94
-
85
+
95
86
  else
96
87
  # Only ActiveStorage objects are supported
97
- Rails.logger.warn("[Fileboost] Unsupported asset type: #{asset.class}. Only ActiveStorage objects are supported.") if defined?(Rails)
98
- nil
99
- end
100
- rescue StandardError => e
101
- if defined?(Rails) && Rails.env.development?
102
- raise e
103
- else
104
- Rails.logger.warn("[Fileboost] Failed to extract asset path: #{e.message}") if defined?(Rails)
105
- nil
88
+ raise AssetPathExtractionError, "Unsupported asset type: #{asset.class}. Only ActiveStorage objects are supported."
106
89
  end
107
90
  end
108
91
 
109
92
  def self.extract_transformation_params(options)
110
93
  params = {}
111
-
94
+
112
95
  # Only handle nested resize parameter
113
96
  if options[:resize].is_a?(Hash)
114
97
  resize_options = options[:resize]
115
98
  resize_options.each do |key, value|
116
99
  key_str = key.to_s
117
-
100
+
118
101
  # Only process valid resize parameters
119
102
  next unless RESIZE_PARAMS.include?(key_str)
120
-
103
+
121
104
  # Use alias if available
122
105
  param_key = PARAM_ALIASES[key_str] || key_str
123
-
106
+
124
107
  # Convert value to string and validate
125
108
  param_value = normalize_param_value(param_key, value)
126
- next if param_value.blank?
127
-
109
+ next if param_value.nil? || param_value.empty?
110
+
128
111
  params[param_key] = param_value
129
112
  end
130
113
  end
131
-
114
+
132
115
  params
133
116
  end
134
117
 
@@ -152,4 +135,4 @@ module Fileboost
152
135
  end
153
136
  end
154
137
  end
155
- end
138
+ end
@@ -1,3 +1,3 @@
1
1
  module Fileboost
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -4,7 +4,7 @@ module Fileboost
4
4
  module Generators
5
5
  class InstallGenerator < Rails::Generators::Base
6
6
  desc "Create Fileboost initializer file"
7
-
7
+
8
8
  def self.source_root
9
9
  @source_root ||= File.expand_path("templates", __dir__)
10
10
  end
@@ -24,4 +24,4 @@ module Fileboost
24
24
  end
25
25
  end
26
26
  end
27
- end
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fileboost
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - bilal
@@ -29,28 +29,28 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '1.15'
32
+ version: '2'
33
33
  type: :development
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.15'
39
+ version: '2'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: combustion
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1.1'
46
+ version: '1'
47
47
  type: :development
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.1'
53
+ version: '1'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: rake
56
56
  requirement: !ruby/object:Gem::Requirement
@@ -79,6 +79,48 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: 8.0.0
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rspec-rails
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '6.0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '6.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: sqlite3
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '2.0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '2.0'
82
124
  description: Fileboost provides drop-in replacement Rails image helpers with automatic
83
125
  optimization through the Fileboost.dev service. Works exclusively with ActiveStorage
84
126
  objects, features HMAC authentication, and comprehensive transformation support.