cloudinary 2.2.0 โ 2.3.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 +4 -4
- data/.github/workflows/ci.yml +42 -0
- data/CHANGELOG.md +17 -0
- data/lib/cloudinary/api.rb +29 -6
- data/lib/cloudinary/base_api.rb +1 -1
- data/lib/cloudinary/cloudinary_controller.rb +7 -5
- data/lib/cloudinary/helper.rb +7 -2
- data/lib/cloudinary/preloaded_file.rb +1 -2
- data/lib/cloudinary/uploader.rb +4 -4
- data/lib/cloudinary/utils.rb +45 -6
- data/lib/cloudinary/version.rb +1 -1
- metadata +3 -3
- data/.travis.yml +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0ad3ba5b49a838e7d13426ba67a292f27831034fca177ce31e8858bd3a214f6
|
4
|
+
data.tar.gz: 91b672ddf6bec07bdddd0691e29b8e50d28d757627bbd22384c62afd0661a73a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2189e9c87739637af5a46b989d76ee14b7ccf024228a785fdc54bd875176ece44a3f72ad46659bf10ec1a86a7686faca19921b89faa4b7deaed47c616257457
|
7
|
+
data.tar.gz: 644dbad25b178cbc92928b9b1c2e7e51b4fcd0c23a2bd1d7a48f054db6c4fea640e8b998138fe914cbd7ea3ea8b06c28a449429c5b0d20a45e6d2662140e98b2
|
@@ -0,0 +1,42 @@
|
|
1
|
+
name: Ruby Test ๐
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
name: ๐ Test with Ruby ${{ matrix.ruby-version }}
|
12
|
+
strategy:
|
13
|
+
fail-fast: false
|
14
|
+
matrix:
|
15
|
+
ruby-version:
|
16
|
+
- '3.1.7'
|
17
|
+
- '3.2.8'
|
18
|
+
- '3.3.8'
|
19
|
+
- '3.4.4'
|
20
|
+
|
21
|
+
runs-on: ubuntu-22.04
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- name: ๐ Checkout Repository
|
25
|
+
uses: actions/checkout@v4
|
26
|
+
|
27
|
+
- name: ๐ ๏ธ Setup Ruby ${{ matrix.ruby-version }}
|
28
|
+
uses: ruby/setup-ruby@v1
|
29
|
+
with:
|
30
|
+
ruby-version: ${{ matrix.ruby-version }}
|
31
|
+
bundler-cache: true
|
32
|
+
|
33
|
+
- name: โ๏ธ Set up test cloud
|
34
|
+
run: |
|
35
|
+
export CLOUDINARY_URL=$(bash tools/get_test_cloud.sh)
|
36
|
+
echo "CLOUDINARY_URL=$CLOUDINARY_URL" >> $GITHUB_ENV
|
37
|
+
echo "cloud_name: $(echo $CLOUDINARY_URL | cut -d'@' -f2)"
|
38
|
+
|
39
|
+
- name: ๐งช Run tests
|
40
|
+
run: bundle exec rspec --format documentation --color
|
41
|
+
env:
|
42
|
+
CLOUDINARY_URL: ${{ env.CLOUDINARY_URL }}
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
2.3.1 / 2025-06-17
|
2
|
+
==================
|
3
|
+
|
4
|
+
* Fix API parameters signature
|
5
|
+
* Allow passing tag attributes for `cloudinary_js_config` tag
|
6
|
+
* Fix `Cloudinary::Uploader.exists?` method
|
7
|
+
|
8
|
+
2.3.0 / 2025-02-20
|
9
|
+
==================
|
10
|
+
|
11
|
+
New functionality and features
|
12
|
+
------------------------------
|
13
|
+
|
14
|
+
* Add support for `429 Too Many Requests` HTTP status code
|
15
|
+
* Add support for `allow_dynamic_list_values` parameter in `MetadataField`
|
16
|
+
* Add support for `config` Admin API
|
17
|
+
|
1
18
|
2.2.0 / 2024-09-08
|
2
19
|
==================
|
3
20
|
|
data/lib/cloudinary/api.rb
CHANGED
@@ -14,6 +14,22 @@ class Cloudinary::Api
|
|
14
14
|
call_api(:get, "ping", {}, options)
|
15
15
|
end
|
16
16
|
|
17
|
+
# Retrieves account configuration details.
|
18
|
+
#
|
19
|
+
# @param [Hash] options The optional parameters.
|
20
|
+
#
|
21
|
+
# @return [Cloudinary::Api::Response]
|
22
|
+
#
|
23
|
+
# @raise [Cloudinary::Api::Error]
|
24
|
+
#
|
25
|
+
# @see https://cloudinary.com/documentation/admin_api#config
|
26
|
+
def self.config(options={})
|
27
|
+
uri = "config"
|
28
|
+
params = only(options, :settings)
|
29
|
+
|
30
|
+
call_api(:get, uri, params, options)
|
31
|
+
end
|
32
|
+
|
17
33
|
# Gets cloud usage details.
|
18
34
|
#
|
19
35
|
# Returns a report detailing your current Cloudinary cloud usage details, including
|
@@ -1021,9 +1037,7 @@ class Cloudinary::Api
|
|
1021
1037
|
#
|
1022
1038
|
# @see https://cloudinary.com/documentation/admin_api#create_a_metadata_field
|
1023
1039
|
def self.add_metadata_field(field, options = {})
|
1024
|
-
|
1025
|
-
|
1026
|
-
call_metadata_api(:post, [], params, options)
|
1040
|
+
call_metadata_api(:post, [], prepare_metadata_field_params(field), options)
|
1027
1041
|
end
|
1028
1042
|
|
1029
1043
|
# Updates a metadata field by external ID.
|
@@ -1040,10 +1054,19 @@ class Cloudinary::Api
|
|
1040
1054
|
#
|
1041
1055
|
# @see https://cloudinary.com/documentation/admin_api#update_a_metadata_field_by_external_id
|
1042
1056
|
def self.update_metadata_field(field_external_id, field, options = {})
|
1043
|
-
uri
|
1044
|
-
params = only(field, :label, :mandatory, :default_value, :validation)
|
1057
|
+
uri = [field_external_id]
|
1045
1058
|
|
1046
|
-
call_metadata_api(:put, uri,
|
1059
|
+
call_metadata_api(:put, uri, prepare_metadata_field_params(field), options)
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
# Prepares optional parameters for add/update_metadata_field API calls.
|
1063
|
+
# @param [Hash] options Additional options
|
1064
|
+
# @return [Object] Optional parameters
|
1065
|
+
def self.prepare_metadata_field_params(field)
|
1066
|
+
only(field,
|
1067
|
+
:type, :external_id, :label, :mandatory, :restrictions, :default_value, :default_disabled,
|
1068
|
+
:validation, :datasource, :allow_dynamic_list_values
|
1069
|
+
)
|
1047
1070
|
end
|
1048
1071
|
|
1049
1072
|
# Deletes a metadata field definition by external ID.
|
data/lib/cloudinary/base_api.rb
CHANGED
@@ -57,7 +57,7 @@ module Cloudinary::BaseApi
|
|
57
57
|
when 403 then NotAllowed
|
58
58
|
when 404 then NotFound
|
59
59
|
when 409 then AlreadyExists
|
60
|
-
when 420 then RateLimited
|
60
|
+
when 420, 429 then RateLimited
|
61
61
|
when 500 then GeneralError
|
62
62
|
else raise GeneralError.new("Server returned unexpected status code - #{response.status} - #{response.body}")
|
63
63
|
end
|
@@ -2,10 +2,12 @@ module Cloudinary::CloudinaryController
|
|
2
2
|
protected
|
3
3
|
|
4
4
|
def valid_cloudinary_response?
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
params = request.query_parameters.select { |key, value| [:public_id, :version, :signature].include?(key.to_sym) }.transform_keys(&:to_sym)
|
6
|
+
|
7
|
+
Cloudinary::Utils.verify_api_response_signature(
|
8
|
+
params[:public_id],
|
9
|
+
params[:version],
|
10
|
+
params[:signature]
|
11
|
+
)
|
10
12
|
end
|
11
13
|
end
|
data/lib/cloudinary/helper.rb
CHANGED
@@ -219,14 +219,19 @@ module CloudinaryHelper
|
|
219
219
|
end
|
220
220
|
|
221
221
|
CLOUDINARY_JS_CONFIG_PARAMS = [:api_key, :cloud_name, :private_cdn, :secure_distribution, :cdn_subdomain]
|
222
|
-
def cloudinary_js_config
|
222
|
+
def cloudinary_js_config(**tag_options)
|
223
223
|
params = {}
|
224
224
|
CLOUDINARY_JS_CONFIG_PARAMS.each do
|
225
225
|
|param|
|
226
226
|
value = Cloudinary.config.send(param)
|
227
227
|
params[param] = value if !value.nil?
|
228
228
|
end
|
229
|
-
content_tag(
|
229
|
+
content_tag(
|
230
|
+
"script",
|
231
|
+
"$.cloudinary.config(#{params.to_json});".html_safe,
|
232
|
+
:type=>"text/javascript",
|
233
|
+
**tag_options
|
234
|
+
)
|
230
235
|
end
|
231
236
|
|
232
237
|
def cl_client_hints_meta_tag
|
@@ -9,8 +9,7 @@ class Cloudinary::PreloadedFile
|
|
9
9
|
|
10
10
|
def valid?
|
11
11
|
public_id = @resource_type == "raw" ? self.filename : self.public_id
|
12
|
-
|
13
|
-
@signature == expected_signature
|
12
|
+
Cloudinary::Utils.verify_api_response_signature(public_id, version, @signature)
|
14
13
|
end
|
15
14
|
|
16
15
|
def identifier
|
data/lib/cloudinary/uploader.rb
CHANGED
@@ -150,12 +150,11 @@ class Cloudinary::Uploader
|
|
150
150
|
def self.exists?(public_id, options={})
|
151
151
|
cloudinary_url = Cloudinary::Utils.cloudinary_url(public_id, options)
|
152
152
|
begin
|
153
|
-
code =
|
153
|
+
code = Faraday.new(request: { timeout: 5 }).head(cloudinary_url).status
|
154
154
|
code >= 200 && code < 300
|
155
|
-
rescue
|
155
|
+
rescue Faraday::ResourceNotFound
|
156
156
|
return false
|
157
157
|
end
|
158
|
-
|
159
158
|
end
|
160
159
|
|
161
160
|
def self.explicit(public_id, options={})
|
@@ -361,7 +360,8 @@ class Cloudinary::Uploader
|
|
361
360
|
api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
|
362
361
|
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
|
363
362
|
signature_algorithm = options[:signature_algorithm]
|
364
|
-
|
363
|
+
signature_version = options[:signature_version]
|
364
|
+
params[:signature] = Cloudinary::Utils.api_sign_request(params.reject { |k, v| non_signable.include?(k) }, api_secret, signature_algorithm, signature_version)
|
365
365
|
params[:api_key] = api_key
|
366
366
|
end
|
367
367
|
|
data/lib/cloudinary/utils.rb
CHANGED
@@ -469,12 +469,50 @@ class Cloudinary::Utils
|
|
469
469
|
end
|
470
470
|
end
|
471
471
|
|
472
|
-
|
473
|
-
|
472
|
+
# Encodes a parameter for safe inclusion in URL query strings.
|
473
|
+
#
|
474
|
+
# Specifically replaces "&" characters with their percent-encoded equivalent "%26"
|
475
|
+
# to prevent them from being interpreted as parameter separators in URL query strings.
|
476
|
+
#
|
477
|
+
# @param [Object] value The parameter to encode
|
478
|
+
# @return [String] Encoded parameter
|
479
|
+
# @private
|
480
|
+
def self.encode_param(value)
|
481
|
+
value.to_s.gsub("&", "%26")
|
474
482
|
end
|
475
483
|
|
476
|
-
|
477
|
-
|
484
|
+
# Generates a string to be signed for API requests
|
485
|
+
#
|
486
|
+
# @param [Hash] params_to_sign Parameters to include in the signature
|
487
|
+
# @param [Integer] signature_version Version of signature algorithm to use:
|
488
|
+
# - Version 1: Original behavior without parameter encoding
|
489
|
+
# - Version 2+ (default): Includes parameter encoding to prevent parameter smuggling
|
490
|
+
# @return [String] String to be signed
|
491
|
+
# @private
|
492
|
+
def self.api_string_to_sign(params_to_sign, signature_version = 2)
|
493
|
+
params_to_sign.map { |k, v| [k.to_s, v.is_a?(Array) ? v.join(",") : v] }
|
494
|
+
.reject { |k, v| v.nil? || v == "" }
|
495
|
+
.sort_by(&:first)
|
496
|
+
.map { |k, v|
|
497
|
+
param_string = "#{k}=#{v}"
|
498
|
+
signature_version >= 2 ? encode_param(param_string) : param_string
|
499
|
+
}
|
500
|
+
.join("&")
|
501
|
+
end
|
502
|
+
|
503
|
+
# Signs API request parameters
|
504
|
+
#
|
505
|
+
# @param [Hash] params_to_sign Parameters to include in the signature
|
506
|
+
# @param [String] api_secret API secret for signing
|
507
|
+
# @param [Symbol|nil] signature_algorithm Hash algorithm to use (:sha1 or :sha256)
|
508
|
+
# @param [Integer|nil] signature_version Version of signature algorithm to use:
|
509
|
+
# - Version 1: Original behavior without parameter encoding
|
510
|
+
# - Version 2+ (default): Includes parameter encoding to prevent parameter smuggling
|
511
|
+
# @return [String] Hexadecimal signature
|
512
|
+
# @private
|
513
|
+
def self.api_sign_request(params_to_sign, api_secret, signature_algorithm = nil, signature_version = nil)
|
514
|
+
signature_version ||= Cloudinary.config.signature_version || 2
|
515
|
+
to_sign = api_string_to_sign(params_to_sign, signature_version)
|
478
516
|
hash("#{to_sign}#{api_secret}", signature_algorithm, :hexdigest)
|
479
517
|
end
|
480
518
|
|
@@ -746,8 +784,9 @@ class Cloudinary::Utils
|
|
746
784
|
api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
|
747
785
|
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
|
748
786
|
signature_algorithm = options[:signature_algorithm]
|
787
|
+
signature_version = options[:signature_version]
|
749
788
|
params = params.reject{|k, v| self.safe_blank?(v)}
|
750
|
-
params[:signature] = api_sign_request(params, api_secret, signature_algorithm)
|
789
|
+
params[:signature] = api_sign_request(params, api_secret, signature_algorithm, signature_version)
|
751
790
|
params[:api_key] = api_key
|
752
791
|
params
|
753
792
|
end
|
@@ -1351,7 +1390,7 @@ class Cloudinary::Utils
|
|
1351
1390
|
:version => version
|
1352
1391
|
}
|
1353
1392
|
|
1354
|
-
signature == api_sign_request(parameters_to_sign, api_secret, signature_algorithm)
|
1393
|
+
signature == api_sign_request(parameters_to_sign, api_secret, signature_algorithm, 1)
|
1355
1394
|
end
|
1356
1395
|
|
1357
1396
|
# Verifies the authenticity of a notification signature.
|
data/lib/cloudinary/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudinary
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nadav Soferman
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2025-06-17 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: faraday
|
@@ -332,9 +332,9 @@ files:
|
|
332
332
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
333
333
|
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
334
334
|
- ".github/pull_request_template.md"
|
335
|
+
- ".github/workflows/ci.yml"
|
335
336
|
- ".gitignore"
|
336
337
|
- ".rspec"
|
337
|
-
- ".travis.yml"
|
338
338
|
- CHANGELOG.md
|
339
339
|
- CONTRIBUTING.md
|
340
340
|
- Gemfile
|
data/.travis.yml
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
dist: jammy
|
2
|
-
language: ruby
|
3
|
-
rvm:
|
4
|
-
- 3.1.4
|
5
|
-
- 3.2.2
|
6
|
-
- 3.3.0
|
7
|
-
|
8
|
-
matrix:
|
9
|
-
include:
|
10
|
-
# There is an OpenSSL issue on Jammy with Ruby 3.0
|
11
|
-
- name: "Ruby: 3.0.6"
|
12
|
-
dist: focal
|
13
|
-
rvm: 3.0.6
|
14
|
-
|
15
|
-
before_script: >
|
16
|
-
export CLOUDINARY_URL=$(bash tools/get_test_cloud.sh);
|
17
|
-
echo cloud_name: "$(echo $CLOUDINARY_URL | cut -d'@' -f2)"
|
18
|
-
script: bundle exec rspec
|
19
|
-
|
20
|
-
notifications:
|
21
|
-
email:
|
22
|
-
recipients:
|
23
|
-
- sdk_developers@cloudinary.com
|