cloudinary 1.19.0 → 1.20.0
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/CHANGELOG.md +23 -5
- data/lib/active_storage/service/cloudinary_service.rb +12 -2
- data/lib/cloudinary/api.rb +3 -2
- data/lib/cloudinary/auth_token.rb +4 -0
- data/lib/cloudinary/uploader.rb +6 -4
- data/lib/cloudinary/utils.rb +85 -29
- data/lib/cloudinary/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b641514503d45c3a6c4e8ba5ed87f0f5b8e521260eda789212543be5ccf77a1
|
4
|
+
data.tar.gz: 0f65e99aa08e446f01d783af5284a1265aaa4f28a1e95c284addd30beb36ec8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 191f627013b5f97fca44e748fd1c4631f9af58a69680b02fdc6b4604e2ddf31216542fcb88e2d1daa825c0ff22a138f2c7d0b41d4895a69cc1b7eaa42a1ab16a
|
7
|
+
data.tar.gz: 8a5abe09f562e188e1e6d43d05f462939c62c4070ac50e93c3acaf876998e651aa2fc50775a10c5fb324d388fac9d599c5fe0e60480cdbbebeb7eedf699057e8
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,32 @@
|
|
1
|
+
1.20.0 / 2021-03-26
|
2
|
+
==================
|
3
|
+
|
4
|
+
New functionality and features
|
5
|
+
------------------------------
|
6
|
+
|
7
|
+
* Add support for `download_backedup_asset` helper method
|
8
|
+
* Add support for `filename_override` upload parameter
|
9
|
+
* Add support for `SHA-256` algorithm in auth signatures
|
10
|
+
|
11
|
+
Other Changes
|
12
|
+
-------------
|
13
|
+
|
14
|
+
* Fix `type` parameter support in ActiveStorage service
|
15
|
+
* Fix expression normalization in advanced cases
|
16
|
+
* Add test for context metadata as user variables
|
17
|
+
* Improve validation of auth token generation
|
18
|
+
|
19
|
+
|
1
20
|
1.19.0 / 2021-03-05
|
2
21
|
==================
|
3
22
|
|
4
23
|
New functionality and features
|
5
24
|
------------------------------
|
6
25
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
26
|
+
* Add Account Provisioning API
|
27
|
+
* Add support for `api_proxy` parameter
|
28
|
+
* Add support for `date` parameter in `usage` Admin API
|
29
|
+
|
11
30
|
Other Changes
|
12
31
|
-------------
|
13
32
|
|
@@ -17,7 +36,6 @@ Other Changes
|
|
17
36
|
* Bump vulnerable version of rubyzip
|
18
37
|
* Fix `cloudinary.gemspec` glob issue
|
19
38
|
|
20
|
-
|
21
39
|
1.18.1 / 2020-09-30
|
22
40
|
===================
|
23
41
|
|
@@ -95,7 +95,12 @@ module ActiveStorage
|
|
95
95
|
|
96
96
|
def delete(key)
|
97
97
|
instrument :delete, key: key do
|
98
|
-
|
98
|
+
options = {
|
99
|
+
resource_type: resource_type(nil, key),
|
100
|
+
type: @options[:type]
|
101
|
+
}.compact
|
102
|
+
|
103
|
+
Cloudinary::Uploader.destroy public_id(key), **options
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
@@ -107,7 +112,12 @@ module ActiveStorage
|
|
107
112
|
def exist?(key)
|
108
113
|
instrument :exist, key: key do |payload|
|
109
114
|
begin
|
110
|
-
|
115
|
+
options = {
|
116
|
+
resource_type: resource_type(nil, key),
|
117
|
+
type: @options[:type]
|
118
|
+
}.compact
|
119
|
+
|
120
|
+
Cloudinary::Api.resource public_id(key), **options
|
111
121
|
true
|
112
122
|
rescue Cloudinary::Api::NotFound => e
|
113
123
|
false
|
data/lib/cloudinary/api.rb
CHANGED
@@ -82,7 +82,8 @@ class Cloudinary::Api
|
|
82
82
|
:phash,
|
83
83
|
:quality_analysis,
|
84
84
|
:derived_next_cursor,
|
85
|
-
:accessibility_analysis
|
85
|
+
:accessibility_analysis,
|
86
|
+
:versions
|
86
87
|
), options)
|
87
88
|
end
|
88
89
|
|
@@ -90,7 +91,7 @@ class Cloudinary::Api
|
|
90
91
|
resource_type = options[:resource_type] || "image"
|
91
92
|
type = options[:type] || "upload"
|
92
93
|
uri = "resources/#{resource_type}/#{type}/restore"
|
93
|
-
call_api(:post, uri, { :public_ids => public_ids }, options)
|
94
|
+
call_api(:post, uri, { :public_ids => public_ids, :versions => options[:versions] }, options)
|
94
95
|
end
|
95
96
|
|
96
97
|
def self.update(public_id, options={})
|
data/lib/cloudinary/uploader.rb
CHANGED
@@ -42,6 +42,7 @@ class Cloudinary::Uploader
|
|
42
42
|
:faces => Cloudinary::Utils.as_safe_bool(options[:faces]),
|
43
43
|
:folder => options[:folder],
|
44
44
|
:format => options[:format],
|
45
|
+
:filename_override => options[:filename_override],
|
45
46
|
:headers => build_custom_headers(options[:headers]),
|
46
47
|
:image_metadata => Cloudinary::Utils.as_safe_bool(options[:image_metadata]),
|
47
48
|
:invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate]),
|
@@ -341,10 +342,11 @@ class Cloudinary::Uploader
|
|
341
342
|
non_signable ||= []
|
342
343
|
|
343
344
|
unless options[:unsigned]
|
344
|
-
api_key
|
345
|
-
api_secret
|
346
|
-
|
347
|
-
params[:
|
345
|
+
api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
|
346
|
+
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
|
347
|
+
signature_algorithm = options[:signature_algorithm]
|
348
|
+
params[:signature] = Cloudinary::Utils.api_sign_request(params.reject { |k, v| non_signable.include?(k) }, api_secret, signature_algorithm)
|
349
|
+
params[:api_key] = api_key
|
348
350
|
end
|
349
351
|
proxy = options[:api_proxy] || Cloudinary.config.api_proxy
|
350
352
|
timeout = options.fetch(:timeout) { Cloudinary.config.to_h.fetch(:timeout, 60) }
|
data/lib/cloudinary/utils.rb
CHANGED
@@ -32,19 +32,34 @@ class Cloudinary::Utils
|
|
32
32
|
|
33
33
|
PREDEFINED_VARS = {
|
34
34
|
"aspect_ratio" => "ar",
|
35
|
+
"aspectRatio" => "ar",
|
35
36
|
"current_page" => "cp",
|
37
|
+
"currentPage" => "cp",
|
36
38
|
"face_count" => "fc",
|
39
|
+
"faceCount" => "fc",
|
37
40
|
"height" => "h",
|
38
41
|
"initial_aspect_ratio" => "iar",
|
42
|
+
"initialAspectRatio" => "iar",
|
43
|
+
"trimmed_aspect_ratio" => "tar",
|
44
|
+
"trimmedAspectRatio" => "tar",
|
39
45
|
"initial_height" => "ih",
|
46
|
+
"initialHeight" => "ih",
|
40
47
|
"initial_width" => "iw",
|
48
|
+
"initialWidth" => "iw",
|
41
49
|
"page_count" => "pc",
|
50
|
+
"pageCount" => "pc",
|
42
51
|
"page_x" => "px",
|
52
|
+
"pageX" => "px",
|
43
53
|
"page_y" => "py",
|
54
|
+
"pageY" => "py",
|
44
55
|
"tags" => "tags",
|
45
56
|
"initial_duration" => "idu",
|
57
|
+
"initialDuration" => "idu",
|
46
58
|
"duration" => "du",
|
47
|
-
"width" => "w"
|
59
|
+
"width" => "w",
|
60
|
+
"illustration_score" => "ils",
|
61
|
+
"illustrationScore" => "ils",
|
62
|
+
"context" => "ctx"
|
48
63
|
}
|
49
64
|
|
50
65
|
SIMPLE_TRANSFORMATION_PARAMS = {
|
@@ -144,6 +159,16 @@ class Cloudinary::Utils
|
|
144
159
|
LONG_URL_SIGNATURE_LENGTH = 32
|
145
160
|
SHORT_URL_SIGNATURE_LENGTH = 8
|
146
161
|
|
162
|
+
UPLOAD_PREFIX = 'https://api.cloudinary.com'
|
163
|
+
|
164
|
+
ALGO_SHA1 = :sha1
|
165
|
+
ALGO_SHA256 = :sha256
|
166
|
+
|
167
|
+
ALGORITHM_SIGNATURE = {
|
168
|
+
ALGO_SHA1 => Digest::SHA1,
|
169
|
+
ALGO_SHA256 => Digest::SHA256,
|
170
|
+
}
|
171
|
+
|
147
172
|
def self.extract_config_params(options)
|
148
173
|
options.select{|k,v| URL_KEYS.include?(k)}
|
149
174
|
end
|
@@ -309,16 +334,16 @@ class Cloudinary::Utils
|
|
309
334
|
"if_" + normalize_expression(if_value) unless if_value.to_s.empty?
|
310
335
|
end
|
311
336
|
|
312
|
-
EXP_REGEXP = Regexp.new('(?<!\$)('+PREDEFINED_VARS.keys.join("|")+')'+'|('+CONDITIONAL_OPERATORS.keys.reverse.map { |k| Regexp.escape(k) }.join('|')+')(?=[ _])')
|
337
|
+
EXP_REGEXP = Regexp.new('(\$_*[^_ ]+)|(?<!\$)('+PREDEFINED_VARS.keys.join("|")+')'+'|('+CONDITIONAL_OPERATORS.keys.reverse.map { |k| Regexp.escape(k) }.join('|')+')(?=[ _])')
|
313
338
|
EXP_REPLACEMENT = PREDEFINED_VARS.merge(CONDITIONAL_OPERATORS)
|
314
339
|
|
315
340
|
def self.normalize_expression(expression)
|
316
341
|
if expression.nil?
|
317
|
-
|
342
|
+
nil
|
318
343
|
elsif expression.is_a?( String) && expression =~ /^!.+!$/ # quoted string
|
319
344
|
expression
|
320
345
|
else
|
321
|
-
expression.to_s.gsub(EXP_REGEXP
|
346
|
+
expression.to_s.gsub(EXP_REGEXP) { |match| EXP_REPLACEMENT[match] || match }.gsub(/[ _]+/, "_")
|
322
347
|
end
|
323
348
|
end
|
324
349
|
|
@@ -433,9 +458,9 @@ class Cloudinary::Utils
|
|
433
458
|
params_to_sign.map{|k,v| [k.to_s, v.is_a?(Array) ? v.join(",") : v]}.reject{|k,v| v.nil? || v == ""}.sort_by(&:first).map{|k,v| "#{k}=#{v}"}.join("&")
|
434
459
|
end
|
435
460
|
|
436
|
-
def self.api_sign_request(params_to_sign, api_secret)
|
461
|
+
def self.api_sign_request(params_to_sign, api_secret, signature_algorithm = nil)
|
437
462
|
to_sign = api_string_to_sign(params_to_sign)
|
438
|
-
|
463
|
+
hash("#{to_sign}#{api_secret}", signature_algorithm, :hexdigest)
|
439
464
|
end
|
440
465
|
|
441
466
|
# Returns a JSON array as String.
|
@@ -501,6 +526,7 @@ class Cloudinary::Utils
|
|
501
526
|
use_root_path = config_option_consume(options, :use_root_path)
|
502
527
|
auth_token = config_option_consume(options, :auth_token)
|
503
528
|
long_url_signature = config_option_consume(options, :long_url_signature)
|
529
|
+
signature_algorithm = config_option_consume(options, :signature_algorithm)
|
504
530
|
unless auth_token == false
|
505
531
|
auth_token = Cloudinary::AuthToken.merge_auth_token(Cloudinary.config.auth_token, auth_token)
|
506
532
|
end
|
@@ -545,7 +571,10 @@ class Cloudinary::Utils
|
|
545
571
|
raise(CloudinaryException, "Must supply api_secret") if (secret.nil? || secret.empty?)
|
546
572
|
to_sign = [transformation, sign_version && version, source_to_sign].reject(&:blank?).join("/")
|
547
573
|
to_sign = fully_unescape(to_sign)
|
548
|
-
|
574
|
+
signature_algorithm = long_url_signature ? ALGO_SHA256 : signature_algorithm
|
575
|
+
hash = hash("#{to_sign}#{secret}", signature_algorithm)
|
576
|
+
signature = Base64.urlsafe_encode64(hash)
|
577
|
+
signature = "s--#{signature[0, long_url_signature ? LONG_URL_SIGNATURE_LENGTH : SHORT_URL_SIGNATURE_LENGTH ]}--"
|
549
578
|
end
|
550
579
|
|
551
580
|
prefix = unsigned_download_url_prefix(source, cloud_name, private_cdn, cdn_subdomain, secure_cdn_subdomain, cname, secure, secure_distribution)
|
@@ -661,18 +690,31 @@ class Cloudinary::Utils
|
|
661
690
|
prefix
|
662
691
|
end
|
663
692
|
|
693
|
+
# Creates a base URL for the cloudinary api
|
694
|
+
#
|
695
|
+
# @param [Object] path Resource name
|
696
|
+
# @param [Hash] options Additional options
|
697
|
+
#
|
698
|
+
# @return [String]
|
699
|
+
def self.base_api_url(path, options = {})
|
700
|
+
cloudinary = options[:upload_prefix] || Cloudinary.config.upload_prefix || UPLOAD_PREFIX
|
701
|
+
cloud_name = options[:cloud_name] || Cloudinary.config.cloud_name || raise(CloudinaryException, 'Must supply cloud_name')
|
702
|
+
|
703
|
+
[cloudinary, 'v1_1', cloud_name, path].join('/')
|
704
|
+
end
|
705
|
+
|
664
706
|
def self.cloudinary_api_url(action = 'upload', options = {})
|
665
|
-
|
666
|
-
|
667
|
-
resource_type
|
668
|
-
return [cloudinary, "v1_1", cloud_name, resource_type, action].join("/")
|
707
|
+
resource_type = options[:resource_type] || 'image'
|
708
|
+
|
709
|
+
base_api_url([resource_type, action], options)
|
669
710
|
end
|
670
711
|
|
671
712
|
def self.sign_request(params, options={})
|
672
713
|
api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
|
673
714
|
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
|
715
|
+
signature_algorithm = options[:signature_algorithm]
|
674
716
|
params = params.reject{|k, v| self.safe_blank?(v)}
|
675
|
-
params[:signature] =
|
717
|
+
params[:signature] = api_sign_request(params, api_secret, signature_algorithm)
|
676
718
|
params[:api_key] = api_key
|
677
719
|
params
|
678
720
|
end
|
@@ -1149,6 +1191,25 @@ class Cloudinary::Utils
|
|
1149
1191
|
REMOTE_URL_REGEX === url
|
1150
1192
|
end
|
1151
1193
|
|
1194
|
+
# The returned url should allow downloading the backedup asset based on the version and asset id
|
1195
|
+
#
|
1196
|
+
# asset and version id are returned with resource(<PUBLIC_ID1>, { versions: true })
|
1197
|
+
#
|
1198
|
+
# @param [String] asset_id Asset identifier
|
1199
|
+
# @param [String] version_id Specific version of asset to download
|
1200
|
+
# @param [Hash] options Additional options
|
1201
|
+
#
|
1202
|
+
# @return [String] An url for downloading a file
|
1203
|
+
def self.download_backedup_asset(asset_id, version_id, options = {})
|
1204
|
+
params = Cloudinary::Utils.sign_request({
|
1205
|
+
:timestamp => (options[:timestamp] || Time.now.to_i),
|
1206
|
+
:asset_id => asset_id,
|
1207
|
+
:version_id => version_id
|
1208
|
+
}, options)
|
1209
|
+
|
1210
|
+
"#{Cloudinary::Utils.base_api_url("download_backup", options)}?#{Cloudinary::Utils.hash_query_params((params))}"
|
1211
|
+
end
|
1212
|
+
|
1152
1213
|
# Format date in a format accepted by the usage API (e.g., 31-12-2020) if
|
1153
1214
|
# passed value is of type Date, otherwise return the string representation of
|
1154
1215
|
# the input.
|
@@ -1163,23 +1224,18 @@ class Cloudinary::Utils
|
|
1163
1224
|
end
|
1164
1225
|
end
|
1165
1226
|
|
1166
|
-
# Computes
|
1167
|
-
#
|
1168
|
-
# @param [String]
|
1169
|
-
# @param [
|
1170
|
-
# @
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
else
|
1178
|
-
[Digest::SHA1, SHORT_URL_SIGNATURE_LENGTH]
|
1179
|
-
end
|
1180
|
-
|
1181
|
-
"s--#{Base64.urlsafe_encode64(algo.digest(combined_message_secret))[0, signature_length]}--"
|
1227
|
+
# Computes hash from input string using specified algorithm.
|
1228
|
+
#
|
1229
|
+
# @param [String] input String which to compute hash from
|
1230
|
+
# @param [String|nil] signature_algorithm Algorithm to use for computing hash
|
1231
|
+
# @param [Symbol] hash_method Hash method applied to a signature algorithm (:digest or :hexdigest)
|
1232
|
+
#
|
1233
|
+
# @return [String] Computed hash value
|
1234
|
+
def self.hash(input, signature_algorithm = nil, hash_method = :digest)
|
1235
|
+
signature_algorithm ||= Cloudinary.config.signature_algorithm || ALGO_SHA1
|
1236
|
+
algorithm = ALGORITHM_SIGNATURE[signature_algorithm] || raise("Unsupported algorithm '#{signature_algorithm}'")
|
1237
|
+
algorithm.public_send(hash_method, input)
|
1182
1238
|
end
|
1183
1239
|
|
1184
|
-
private_class_method :
|
1240
|
+
private_class_method :hash
|
1185
1241
|
end
|
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: 1.
|
4
|
+
version: 1.20.0
|
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: 2021-03-
|
13
|
+
date: 2021-03-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws_cf_signer
|