cloudinary 1.20.0 → 1.21.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/.github/ISSUE_TEMPLATE/bug_report.md +15 -14
- data/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- data/.github/pull_request_template.md +18 -11
- data/CHANGELOG.md +27 -0
- data/lib/cloudinary.rb +10 -1
- data/lib/cloudinary/account_api.rb +7 -12
- data/lib/cloudinary/api.rb +37 -12
- data/lib/cloudinary/search.rb +40 -7
- data/lib/cloudinary/uploader.rb +44 -18
- data/lib/cloudinary/utils.rb +122 -5
- data/lib/cloudinary/version.rb +1 -1
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +10 -2
- 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: fbc5f576707d33b684e97610585e92838695cbd373cace7c16b0078021b46871
|
4
|
+
data.tar.gz: a5fc7e5d8f0930223cb03b4ca07910ba3b8a6e8ac18b5d6028f9a8963311f8d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 888d693726c91cba5113ca6d4e13f89b859fc01fde5603ace994eb13a907881d4d5e84a7150501c970b1792c47286ae4a9d889f61b1e41408e25a4aea20cf11d
|
7
|
+
data.tar.gz: 6a76cfcc6187c87314f1676a769b8fbfcfda08a5a22d00403f689056a680e4acb15d7360b919a2132c254295c8439e2072be74a8a2891362920f217d387d14ef
|
@@ -3,7 +3,7 @@ name: Bug report
|
|
3
3
|
about: Bug report for Cloudinary Ruby SDK
|
4
4
|
title: ''
|
5
5
|
labels: ''
|
6
|
-
assignees:
|
6
|
+
assignees: ''
|
7
7
|
|
8
8
|
---
|
9
9
|
|
@@ -14,11 +14,11 @@ Before proceeding, please update to latest version and test if the issue persist
|
|
14
14
|
…
|
15
15
|
|
16
16
|
## Issue Type (Can be multiple)
|
17
|
-
[ ] Build -
|
18
|
-
[ ] Performance - Performance issues
|
19
|
-
[ ] Behaviour - Functions
|
20
|
-
[ ] Documentation - Inconsistency between the docs and behaviour
|
21
|
-
[ ] Other (Specify)
|
17
|
+
- [ ] Build - Cannot install or import the SDK
|
18
|
+
- [ ] Performance - Performance issues
|
19
|
+
- [ ] Behaviour - Functions are not working as expected (such as generate URL)
|
20
|
+
- [ ] Documentation - Inconsistency between the docs and behaviour
|
21
|
+
- [ ] Other (Specify)
|
22
22
|
|
23
23
|
## Steps to reproduce
|
24
24
|
… if applicable
|
@@ -27,16 +27,17 @@ Before proceeding, please update to latest version and test if the issue persist
|
|
27
27
|
…
|
28
28
|
|
29
29
|
## Operating System
|
30
|
-
[ ] Linux
|
31
|
-
[ ] Windows
|
32
|
-
[ ]
|
33
|
-
[ ] All
|
30
|
+
- [ ] Linux
|
31
|
+
- [ ] Windows
|
32
|
+
- [ ] macOS
|
33
|
+
- [ ] All
|
34
34
|
|
35
35
|
## Environment and Libraries (fill in the version numbers)
|
36
|
-
Cloudinary Ruby SDK version - 0.0.0
|
37
|
-
Ruby Version - 0.0.0
|
38
|
-
Rails Version - 0.0.0
|
39
|
-
Other Libraries (Carrierwave, ActiveStorage, etc) - 0.0.0
|
36
|
+
- Cloudinary Ruby SDK version - 0.0.0
|
37
|
+
- Ruby Version - 0.0.0
|
38
|
+
- Rails Version - 0.0.0
|
39
|
+
- Other Libraries (Carrierwave, ActiveStorage, etc) - 0.0.0
|
40
40
|
|
41
41
|
## Repository
|
42
|
+
|
42
43
|
If possible, please provide a link to a reproducible repository that showcases the problem
|
@@ -4,21 +4,28 @@ Provide some context as to what was changed, from an implementation standpoint.
|
|
4
4
|
-->
|
5
5
|
|
6
6
|
#### What does this PR address?
|
7
|
-
[ ]
|
8
|
-
[ ] Refactoring
|
9
|
-
[ ] New feature
|
10
|
-
[ ] Bug fix
|
11
|
-
[ ] Adds more tests
|
7
|
+
- [ ] GitHub issue (Add reference - #XX)
|
8
|
+
- [ ] Refactoring
|
9
|
+
- [ ] New feature
|
10
|
+
- [ ] Bug fix
|
11
|
+
- [ ] Adds more tests
|
12
12
|
|
13
13
|
#### Are tests included?
|
14
|
-
[ ] Yes
|
15
|
-
[ ] No
|
14
|
+
- [ ] Yes
|
15
|
+
- [ ] No
|
16
16
|
|
17
|
-
#### Reviewer,
|
17
|
+
#### Reviewer, please note:
|
18
18
|
<!--
|
19
19
|
List anything here that the reviewer should pay special attention to. This might
|
20
20
|
include, for example:
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
* Dependence on other PRs
|
22
|
+
* Reference to other Cloudinary SDKs
|
23
|
+
* Changes that seem arbitrary without further explanations
|
24
24
|
-->
|
25
|
+
|
26
|
+
#### Checklist:
|
27
|
+
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
28
|
+
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
29
|
+
- [ ] My code follows the code style of this project.
|
30
|
+
- [ ] My change requires a change to the documentation.
|
31
|
+
- [ ] I ran the full test suite before pushing the changes and all the tests pass.
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
1.21.0 / 2021-08-23
|
2
|
+
==================
|
3
|
+
|
4
|
+
New functionality and features
|
5
|
+
------------------------------
|
6
|
+
|
7
|
+
* Add support for `create_slideshow` Upload API
|
8
|
+
* Add support for variables in text style
|
9
|
+
* Add support for `context` and `metadata` in `rename` Upload API
|
10
|
+
* Add support for `reorder_metadata_field_datasource` Admin API
|
11
|
+
* Add `verify_api_response_signature` and `verify_notification_signature` helpers
|
12
|
+
* Add `download_generated_sprite` and `download_multi` methods
|
13
|
+
* Add support for `urls` in multi and sprite APIs
|
14
|
+
* Add support for `live` parameter in upload presets
|
15
|
+
* Add support for `metadata` parameter in `resources` Admin APIs
|
16
|
+
|
17
|
+
Other Changes
|
18
|
+
-------------
|
19
|
+
|
20
|
+
* Fix `transformations` API call
|
21
|
+
* Fix named parameters normalization issue
|
22
|
+
* Remove duplicates in Search Api fields
|
23
|
+
* Improve configuration tests
|
24
|
+
* Add tests for Provisioning API
|
25
|
+
* Refactor metadata usage in tests
|
26
|
+
* Update GitHub templates
|
27
|
+
|
1
28
|
1.20.0 / 2021-03-26
|
2
29
|
==================
|
3
30
|
|
data/lib/cloudinary.rb
CHANGED
@@ -133,13 +133,22 @@ module Cloudinary
|
|
133
133
|
#
|
134
134
|
# @return [OpenStruct]
|
135
135
|
def self.make_new_config(config_module)
|
136
|
-
|
136
|
+
import_settings_from_file.tap do |config|
|
137
137
|
config.extend(config_module)
|
138
138
|
config.load_config_from_env
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
142
|
private_class_method :make_new_config
|
143
|
+
|
144
|
+
# Import settings from yaml file
|
145
|
+
#
|
146
|
+
# @return [OpenStruct]
|
147
|
+
def self.import_settings_from_file
|
148
|
+
OpenStruct.new((YAML.load(ERB.new(IO.read(config_dir.join("cloudinary.yml"))).result)[config_env] rescue {}))
|
149
|
+
end
|
150
|
+
|
151
|
+
private_class_method :import_settings_from_file
|
143
152
|
end
|
144
153
|
# Prevent require loop if included after Rails is already initialized.
|
145
154
|
require "cloudinary/helper" if defined?(::ActionView::Base)
|
@@ -128,23 +128,18 @@ class Cloudinary::AccountApi
|
|
128
128
|
end
|
129
129
|
|
130
130
|
# Lists users in the account.
|
131
|
-
# @param [Boolean] pending
|
131
|
+
# @param [Boolean] pending Limit results to pending users (true), users that are not pending (false), or all users (nil, the default)
|
132
132
|
# @param [Array<String>] user_ids A list of up to 100 user IDs. When provided, other parameters are ignored.
|
133
133
|
# @param [String] prefix Returns users where the name or email address begins with the specified case-insensitive string.
|
134
134
|
# @param [String] sub_account_id Only returns users who have access to the specified account.
|
135
135
|
# @param [Object] options additional options
|
136
136
|
def self.users(pending = nil, user_ids = [], prefix = nil, sub_account_id = nil, options = {})
|
137
|
-
params =
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
prefix: prefix,
|
144
|
-
sub_account_id: sub_account_id,
|
145
|
-
pending: pending
|
146
|
-
}
|
147
|
-
end
|
137
|
+
params = {
|
138
|
+
ids: user_ids,
|
139
|
+
prefix: prefix,
|
140
|
+
sub_account_id: sub_account_id,
|
141
|
+
pending: pending
|
142
|
+
}
|
148
143
|
|
149
144
|
call_account_api(:get, 'users', params, options.merge(content_type: :json))
|
150
145
|
end
|
data/lib/cloudinary/api.rb
CHANGED
@@ -34,25 +34,25 @@ class Cloudinary::Api
|
|
34
34
|
type = options[:type]
|
35
35
|
uri = "resources/#{resource_type}"
|
36
36
|
uri += "/#{type}" unless type.blank?
|
37
|
-
call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context, :moderations, :direction, :start_at), options)
|
37
|
+
call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context, :moderations, :direction, :start_at, :metadata), options)
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.resources_by_tag(tag, options={})
|
41
41
|
resource_type = options[:resource_type] || "image"
|
42
42
|
uri = "resources/#{resource_type}/tags/#{tag}"
|
43
|
-
call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction), options)
|
43
|
+
call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
|
44
44
|
end
|
45
45
|
|
46
46
|
def self.resources_by_moderation(kind, status, options={})
|
47
47
|
resource_type = options[:resource_type] || "image"
|
48
48
|
uri = "resources/#{resource_type}/moderations/#{kind}/#{status}"
|
49
|
-
call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction), options)
|
49
|
+
call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
|
50
50
|
end
|
51
51
|
|
52
52
|
def self.resources_by_context(key, value=nil, options={})
|
53
53
|
resource_type = options[:resource_type] || "image"
|
54
54
|
uri = "resources/#{resource_type}/context"
|
55
|
-
params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction
|
55
|
+
params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :key, :value, :metadata)
|
56
56
|
params[:key] = key
|
57
57
|
params[:value] = value
|
58
58
|
call_api(:get, uri, params, options)
|
@@ -177,24 +177,32 @@ class Cloudinary::Api
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def self.transformation(transformation, options={})
|
180
|
-
|
180
|
+
params = only(options, :next_cursor, :max_results)
|
181
|
+
params[:transformation] = Cloudinary::Utils.build_eager(transformation)
|
182
|
+
call_api(:get, "transformations", params, options)
|
181
183
|
end
|
182
184
|
|
183
185
|
def self.delete_transformation(transformation, options={})
|
184
|
-
call_api(:delete, "transformations
|
186
|
+
call_api(:delete, "transformations", {:transformation => Cloudinary::Utils.build_eager(transformation)}, options)
|
185
187
|
end
|
186
188
|
|
187
189
|
# updates - supports:
|
188
190
|
# "allowed_for_strict" boolean
|
189
191
|
# "unsafe_update" transformation params - updates a named transformation parameters without regenerating existing images
|
190
192
|
def self.update_transformation(transformation, updates, options={})
|
191
|
-
params
|
192
|
-
params[:unsafe_update]
|
193
|
-
|
193
|
+
params = only(updates, :allowed_for_strict)
|
194
|
+
params[:unsafe_update] = Cloudinary::Utils.build_eager(updates[:unsafe_update]) if updates[:unsafe_update]
|
195
|
+
params[:transformation] = Cloudinary::Utils.build_eager(transformation)
|
196
|
+
call_api(:put, "transformations", params, options)
|
194
197
|
end
|
195
198
|
|
196
199
|
def self.create_transformation(name, definition, options={})
|
197
|
-
|
200
|
+
params = {
|
201
|
+
:name => name,
|
202
|
+
:transformation => Cloudinary::Utils.build_eager(definition)
|
203
|
+
}
|
204
|
+
|
205
|
+
call_api(:post, "transformations", params, options)
|
198
206
|
end
|
199
207
|
|
200
208
|
# upload presets
|
@@ -212,12 +220,12 @@ class Cloudinary::Api
|
|
212
220
|
|
213
221
|
def self.update_upload_preset(name, options={})
|
214
222
|
params = Cloudinary::Uploader.build_upload_params(options)
|
215
|
-
call_api(:put, "upload_presets/#{name}", params.merge(only(options, :unsigned, :disallow_public_id)), options)
|
223
|
+
call_api(:put, "upload_presets/#{name}", params.merge(only(options, :unsigned, :disallow_public_id, :live)), options)
|
216
224
|
end
|
217
225
|
|
218
226
|
def self.create_upload_preset(options={})
|
219
227
|
params = Cloudinary::Uploader.build_upload_params(options)
|
220
|
-
call_api(:post, "upload_presets", params.merge(only(options, :name, :unsigned, :disallow_public_id)), options)
|
228
|
+
call_api(:post, "upload_presets", params.merge(only(options, :name, :unsigned, :disallow_public_id, :live)), options)
|
221
229
|
end
|
222
230
|
|
223
231
|
def self.root_folders(options={})
|
@@ -478,6 +486,23 @@ class Cloudinary::Api
|
|
478
486
|
call_metadata_api(:post, uri, params, options)
|
479
487
|
end
|
480
488
|
|
489
|
+
# Reorders metadata field datasource. Currently supports only value.
|
490
|
+
#
|
491
|
+
# @param [String] field_external_id The ID of the metadata field
|
492
|
+
# @param [String] order_by Criteria for the order. Currently supports only value
|
493
|
+
# @param [String] direction Optional (gets either asc or desc)
|
494
|
+
# @param [Hash] options Configuration options
|
495
|
+
#
|
496
|
+
# @return [Cloudinary::Api::Response]
|
497
|
+
#
|
498
|
+
# @raise [Cloudinary::Api::Error]
|
499
|
+
def self.reorder_metadata_field_datasource(field_external_id, order_by, direction = nil, options = {})
|
500
|
+
uri = [field_external_id, "datasource", "order"]
|
501
|
+
params = { :order_by => order_by, :direction => direction }
|
502
|
+
|
503
|
+
call_metadata_api(:post, uri, params, options)
|
504
|
+
end
|
505
|
+
|
481
506
|
protected
|
482
507
|
|
483
508
|
def self.call_api(method, uri, params, options)
|
data/lib/cloudinary/search.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
class Cloudinary::Search
|
2
|
+
SORT_BY = :sort_by
|
3
|
+
AGGREGATE = :aggregate
|
4
|
+
WITH_FIELD = :with_field
|
5
|
+
KEYS_WITH_UNIQUE_VALUES = [SORT_BY, AGGREGATE, WITH_FIELD].freeze
|
6
|
+
|
2
7
|
def initialize
|
3
8
|
@query_hash = {
|
4
|
-
|
5
|
-
|
6
|
-
|
9
|
+
SORT_BY => {},
|
10
|
+
AGGREGATE => {},
|
11
|
+
WITH_FIELD => {}
|
7
12
|
}
|
8
13
|
end
|
9
14
|
|
@@ -28,23 +33,51 @@ class Cloudinary::Search
|
|
28
33
|
self
|
29
34
|
end
|
30
35
|
|
36
|
+
# Sets the `sort_by` field.
|
37
|
+
#
|
38
|
+
# @param [String] field_name The field to sort by. You can specify more than one sort_by parameter;
|
39
|
+
# results will be sorted according to the order of the fields provided.
|
40
|
+
# @param [String] dir Sort direction. Valid sort directions are 'asc' or 'desc'. Default: 'desc'.
|
41
|
+
#
|
42
|
+
# @return [Cloudinary::Search]
|
31
43
|
def sort_by(field_name, dir = 'desc')
|
32
|
-
@query_hash[
|
44
|
+
@query_hash[SORT_BY][field_name] = { field_name => dir }
|
33
45
|
self
|
34
46
|
end
|
35
47
|
|
48
|
+
# The name of a field (attribute) for which an aggregation count should be calculated and returned in the response.
|
49
|
+
#
|
50
|
+
# You can specify more than one aggregate parameter.
|
51
|
+
#
|
52
|
+
# @param [String] value Supported values: resource_type, type, pixels (only the image assets in the response are
|
53
|
+
# aggregated), duration (only the video assets in the response are aggregated), format, and
|
54
|
+
# bytes. For aggregation fields without discrete values, the results are divided into
|
55
|
+
# categories.
|
56
|
+
# @return [Cloudinary::Search]
|
36
57
|
def aggregate(value)
|
37
|
-
@query_hash[
|
58
|
+
@query_hash[AGGREGATE][value] = value
|
38
59
|
self
|
39
60
|
end
|
40
61
|
|
62
|
+
# The name of an additional asset attribute to include for each asset in the response.
|
63
|
+
#
|
64
|
+
# @param [String] value Possible value: context, tags, and for Tier 2 also image_metadata, and image_analysis.
|
65
|
+
#
|
66
|
+
# @return [Cloudinary::Search]
|
41
67
|
def with_field(value)
|
42
|
-
@query_hash[
|
68
|
+
@query_hash[WITH_FIELD][value] = value
|
43
69
|
self
|
44
70
|
end
|
45
71
|
|
72
|
+
# Returns the query as an hash.
|
73
|
+
#
|
74
|
+
# @return [Hash]
|
46
75
|
def to_h
|
47
|
-
@query_hash.
|
76
|
+
@query_hash.each_with_object({}) do |(key, value), query|
|
77
|
+
next if value.nil? || ((value.is_a?(Array) || value.is_a?(Hash)) && value.blank?)
|
78
|
+
|
79
|
+
query[key] = KEYS_WITH_UNIQUE_VALUES.include?(key) ? value.values : value
|
80
|
+
end
|
48
81
|
end
|
49
82
|
|
50
83
|
def execute(options = {})
|
data/lib/cloudinary/uploader.rb
CHANGED
@@ -159,7 +159,9 @@ class Cloudinary::Uploader
|
|
159
159
|
:from_public_id => from_public_id,
|
160
160
|
:to_public_id => to_public_id,
|
161
161
|
:to_type => options[:to_type],
|
162
|
-
:invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate])
|
162
|
+
:invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate]),
|
163
|
+
:context => options[:context],
|
164
|
+
:metadata => options[:metadata]
|
163
165
|
}
|
164
166
|
end
|
165
167
|
end
|
@@ -207,17 +209,42 @@ class Cloudinary::Uploader
|
|
207
209
|
end
|
208
210
|
end
|
209
211
|
|
210
|
-
|
212
|
+
SLIDESHOW_PARAMS = [:notification_url, :public_id, :upload_preset]
|
213
|
+
|
214
|
+
# Creates auto-generated video slideshow.
|
215
|
+
#
|
216
|
+
# @param [Hash] options Additional options.
|
217
|
+
#
|
218
|
+
# @return [Hash] Hash with meta information URLs of generated slideshow resources.
|
219
|
+
def self.create_slideshow(options = {})
|
220
|
+
options[:resource_type] ||= :video
|
221
|
+
|
222
|
+
call_api("create_slideshow", options) do
|
223
|
+
params = {
|
224
|
+
:timestamp => Time.now.to_i,
|
225
|
+
:transformation => Cloudinary::Utils.build_eager(options[:transformation]),
|
226
|
+
:manifest_transformation => Cloudinary::Utils.build_eager(options[:manifest_transformation]),
|
227
|
+
:manifest_json => options[:manifest_json] && options[:manifest_json].to_json,
|
228
|
+
:tags => options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
|
229
|
+
:overwrite => Cloudinary::Utils.as_safe_bool(options[:overwrite])
|
230
|
+
}
|
231
|
+
SLIDESHOW_PARAMS.each { |k| params[k] = options[k] unless options[k].nil? }
|
232
|
+
|
233
|
+
params
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Generates sprites by merging multiple images into a single large image.
|
238
|
+
#
|
239
|
+
# @param [String|Hash] tag Treated as additional options when hash is passed, otherwise as a tag
|
240
|
+
# @param [Hash] options Additional options. Should be omitted when +tag_or_options+ is a Hash
|
241
|
+
#
|
242
|
+
# @return [Hash] Hash with meta information URLs of generated sprite resources
|
243
|
+
def self.generate_sprite(tag, options = {})
|
211
244
|
version_store = options.delete(:version_store)
|
212
245
|
|
213
246
|
result = call_api("sprite", options) do
|
214
|
-
|
215
|
-
:timestamp => (options[:timestamp] || Time.now.to_i),
|
216
|
-
:tag => tag,
|
217
|
-
:async => options[:async],
|
218
|
-
:notification_url => options[:notification_url],
|
219
|
-
:transformation => Cloudinary::Utils.generate_transformation_string(options.merge(:fetch_format => options[:format]))
|
220
|
-
}
|
247
|
+
Cloudinary::Utils.build_multi_and_sprite_params(tag, options)
|
221
248
|
end
|
222
249
|
|
223
250
|
if version_store == :file && result && result["version"]
|
@@ -229,16 +256,15 @@ class Cloudinary::Uploader
|
|
229
256
|
return result
|
230
257
|
end
|
231
258
|
|
232
|
-
|
259
|
+
# Creates either a single animated image, video or a PDF.
|
260
|
+
#
|
261
|
+
# @param [String|Hash] tag Treated as additional options when hash is passed, otherwise as a tag
|
262
|
+
# @param [Hash] options Additional options. Should be omitted when +tag_or_options+ is a Hash
|
263
|
+
#
|
264
|
+
# @return [Hash] Hash with meta information URLs of the generated file
|
265
|
+
def self.multi(tag, options = {})
|
233
266
|
call_api("multi", options) do
|
234
|
-
|
235
|
-
:timestamp => (options[:timestamp] || Time.now.to_i),
|
236
|
-
:tag => tag,
|
237
|
-
:format => options[:format],
|
238
|
-
:async => options[:async],
|
239
|
-
:notification_url => options[:notification_url],
|
240
|
-
:transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
|
241
|
-
}
|
267
|
+
Cloudinary::Utils.build_multi_and_sprite_params(tag, options)
|
242
268
|
end
|
243
269
|
end
|
244
270
|
|
data/lib/cloudinary/utils.rb
CHANGED
@@ -13,6 +13,7 @@ require 'cloudinary/responsive'
|
|
13
13
|
class Cloudinary::Utils
|
14
14
|
# @deprecated Use Cloudinary::SHARED_CDN
|
15
15
|
SHARED_CDN = Cloudinary::SHARED_CDN
|
16
|
+
MODE_DOWNLOAD = "download"
|
16
17
|
DEFAULT_RESPONSIVE_WIDTH_TRANSFORMATION = {:width => :auto, :crop => :limit}
|
17
18
|
CONDITIONAL_OPERATORS = {
|
18
19
|
"=" => 'eq',
|
@@ -334,7 +335,7 @@ class Cloudinary::Utils
|
|
334
335
|
"if_" + normalize_expression(if_value) unless if_value.to_s.empty?
|
335
336
|
end
|
336
337
|
|
337
|
-
EXP_REGEXP = Regexp.new('(\$_*[^_ ]+)|(
|
338
|
+
EXP_REGEXP = Regexp.new('(\$_*[^_ ]+)|(?<![\$:])('+PREDEFINED_VARS.keys.join("|")+')'+'|('+CONDITIONAL_OPERATORS.keys.reverse.map { |k| Regexp.escape(k) }.join('|')+')(?=[ _])')
|
338
339
|
EXP_REPLACEMENT = PREDEFINED_VARS.merge(CONDITIONAL_OPERATORS)
|
339
340
|
|
340
341
|
def self.normalize_expression(expression)
|
@@ -430,6 +431,8 @@ class Cloudinary::Utils
|
|
430
431
|
]
|
431
432
|
|
432
433
|
def self.text_style(layer)
|
434
|
+
return layer[:text_style] if layer[:text_style].present?
|
435
|
+
|
433
436
|
font_family = layer[:font_family]
|
434
437
|
font_size = layer[:font_size]
|
435
438
|
keywords = []
|
@@ -719,6 +722,43 @@ class Cloudinary::Utils
|
|
719
722
|
params
|
720
723
|
end
|
721
724
|
|
725
|
+
# Helper method for generating download URLs
|
726
|
+
#
|
727
|
+
# @param [String] action @see Cloudinary::Utils.cloudinary_api_url
|
728
|
+
# @param [Hash] params Query parameters in generated URL
|
729
|
+
# @param [Hash] options Additional options
|
730
|
+
# @yield [query_parameters] Invokes the block with query parameters to override how to encode them
|
731
|
+
#
|
732
|
+
# @return [String]
|
733
|
+
def self.cloudinary_api_download_url(action, params, options = {})
|
734
|
+
cloudinary_params = sign_request(params.merge(mode: MODE_DOWNLOAD), options)
|
735
|
+
|
736
|
+
"#{Cloudinary::Utils.cloudinary_api_url(action, options)}?#{hash_query_params(cloudinary_params)}"
|
737
|
+
end
|
738
|
+
private_class_method :cloudinary_api_download_url
|
739
|
+
|
740
|
+
# Return a signed URL to the 'generate_sprite' endpoint with 'mode=download'.
|
741
|
+
#
|
742
|
+
# @param [String|Hash] tag Treated as additional options when hash is passed, otherwise as a tag
|
743
|
+
# @param [Hash] options Additional options. Should be omitted when +tag_or_options+ is a Hash
|
744
|
+
#
|
745
|
+
# @return [String] The signed URL to download sprite
|
746
|
+
def self.download_generated_sprite(tag, options = {})
|
747
|
+
params = build_multi_and_sprite_params(tag, options)
|
748
|
+
cloudinary_api_download_url("sprite", params, options)
|
749
|
+
end
|
750
|
+
|
751
|
+
# Return a signed URL to the 'multi' endpoint with 'mode=download'.
|
752
|
+
#
|
753
|
+
# @param [String|Hash] tag Treated as additional options when hash is passed, otherwise as a tag
|
754
|
+
# @param [Hash] options Additional options. Should be omitted when +tag_or_options+ is a Hash
|
755
|
+
#
|
756
|
+
# @return [String] The signed URL to download multi
|
757
|
+
def self.download_multi(tag, options = {})
|
758
|
+
params = build_multi_and_sprite_params(tag, options)
|
759
|
+
cloudinary_api_download_url("multi", params, options)
|
760
|
+
end
|
761
|
+
|
722
762
|
def self.private_download_url(public_id, format, options = {})
|
723
763
|
cloudinary_params = sign_request({
|
724
764
|
:timestamp=>Time.now.to_i,
|
@@ -767,11 +807,10 @@ class Cloudinary::Utils
|
|
767
807
|
# @option options [String] :keep_derived (false) keep the derived images used for generating the archive
|
768
808
|
# @return [String] archive url
|
769
809
|
def self.download_archive_url(options = {})
|
770
|
-
|
771
|
-
|
810
|
+
params = Cloudinary::Utils.archive_params(options)
|
811
|
+
cloudinary_api_download_url("generate_archive", params, options)
|
772
812
|
end
|
773
813
|
|
774
|
-
|
775
814
|
# Returns a URL that when invokes creates an zip archive and returns it.
|
776
815
|
# @see download_archive_url
|
777
816
|
def self.download_zip_url(options = {})
|
@@ -1191,6 +1230,41 @@ class Cloudinary::Utils
|
|
1191
1230
|
REMOTE_URL_REGEX === url
|
1192
1231
|
end
|
1193
1232
|
|
1233
|
+
# Build params for multi, download_multi, generate_sprite, and download_generated_sprite methods
|
1234
|
+
#
|
1235
|
+
# @param [String|Hash] tag_or_options Treated as additional options when hash is passed, otherwise as a tag
|
1236
|
+
# @param [Hash] options Additional options. Should be omitted when +tag_or_options+ is a Hash
|
1237
|
+
#
|
1238
|
+
# @return [Hash]
|
1239
|
+
#
|
1240
|
+
# @private
|
1241
|
+
def self.build_multi_and_sprite_params(tag_or_options, options)
|
1242
|
+
if tag_or_options.is_a?(Hash)
|
1243
|
+
if options.blank?
|
1244
|
+
options = tag_or_options
|
1245
|
+
tag_or_options = nil
|
1246
|
+
else
|
1247
|
+
raise "First argument must be a tag when additional options are passed"
|
1248
|
+
end
|
1249
|
+
end
|
1250
|
+
urls = options.delete(:urls)
|
1251
|
+
|
1252
|
+
if tag_or_options.blank? && urls.blank?
|
1253
|
+
raise "Either tag or urls are required"
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
{
|
1257
|
+
:tag => tag_or_options,
|
1258
|
+
:urls => urls,
|
1259
|
+
:transformation => Cloudinary::Utils.generate_transformation_string(options.merge(:fetch_format => options[:format])),
|
1260
|
+
:notification_url => options[:notification_url],
|
1261
|
+
:format => options[:format],
|
1262
|
+
:async => options[:async],
|
1263
|
+
:mode => options[:mode],
|
1264
|
+
:timestamp => (options[:timestamp] || Time.now.to_i)
|
1265
|
+
}
|
1266
|
+
end
|
1267
|
+
|
1194
1268
|
# The returned url should allow downloading the backedup asset based on the version and asset id
|
1195
1269
|
#
|
1196
1270
|
# asset and version id are returned with resource(<PUBLIC_ID1>, { versions: true })
|
@@ -1224,10 +1298,53 @@ class Cloudinary::Utils
|
|
1224
1298
|
end
|
1225
1299
|
end
|
1226
1300
|
|
1301
|
+
# Verifies the authenticity of an API response signature.
|
1302
|
+
#
|
1303
|
+
# @param [String] public_id he public id of the asset as returned in the API response
|
1304
|
+
# @param [Fixnum] version The version of the asset as returned in the API response
|
1305
|
+
# @param [String] signature Actual signature. Can be retrieved from the X-Cld-Signature header
|
1306
|
+
# @param [Symbol|nil] signature_algorithm Algorithm to use for computing hash
|
1307
|
+
# @param [Hash] options
|
1308
|
+
# @option options [String] :api_secret API secret, if not passed taken from global config
|
1309
|
+
#
|
1310
|
+
# @return [Boolean]
|
1311
|
+
def self.verify_api_response_signature(public_id, version, signature, signature_algorithm = nil, options = {})
|
1312
|
+
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise("Must supply api_secret")
|
1313
|
+
|
1314
|
+
parameters_to_sign = {
|
1315
|
+
:public_id => public_id,
|
1316
|
+
:version => version
|
1317
|
+
}
|
1318
|
+
|
1319
|
+
signature == api_sign_request(parameters_to_sign, api_secret, signature_algorithm)
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
# Verifies the authenticity of a notification signature.
|
1323
|
+
#
|
1324
|
+
# @param [String] body JSON of the request's body
|
1325
|
+
# @param [Fixnum] timestamp Unix timestamp. Can be retrieved from the X-Cld-Timestamp header
|
1326
|
+
# @param [String] signature Actual signature. Can be retrieved from the X-Cld-Signature header
|
1327
|
+
# @param [Fixnum] valid_for The desired time in seconds for considering the request valid
|
1328
|
+
# @param [Symbol|nil] signature_algorithm Algorithm to use for computing hash
|
1329
|
+
# @param [Hash] options
|
1330
|
+
# @option options [String] :api_secret API secret, if not passed taken from global config
|
1331
|
+
#
|
1332
|
+
# @return [Boolean]
|
1333
|
+
def self.verify_notification_signature(body, timestamp, signature, valid_for = 7200, signature_algorithm = nil, options = {})
|
1334
|
+
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise("Must supply api_secret")
|
1335
|
+
raise("Body should be of String type") unless body.is_a?(String)
|
1336
|
+
# verify that signature is valid for the given timestamp
|
1337
|
+
return false if timestamp < (Time.now - valid_for).to_i
|
1338
|
+
|
1339
|
+
payload_hash = hash("#{body}#{timestamp}#{api_secret}", signature_algorithm, :hexdigest)
|
1340
|
+
|
1341
|
+
signature == payload_hash
|
1342
|
+
end
|
1343
|
+
|
1227
1344
|
# Computes hash from input string using specified algorithm.
|
1228
1345
|
#
|
1229
1346
|
# @param [String] input String which to compute hash from
|
1230
|
-
# @param [
|
1347
|
+
# @param [Symbol|nil] signature_algorithm Algorithm to use for computing hash
|
1231
1348
|
# @param [Symbol] hash_method Hash method applied to a signature algorithm (:digest or :hexdigest)
|
1232
1349
|
#
|
1233
1350
|
# @return [String] Computed hash value
|
data/lib/cloudinary/version.rb
CHANGED
@@ -4302,12 +4302,20 @@ var slice = [].slice,
|
|
4302
4302
|
switch (false) {
|
4303
4303
|
case !/w_auto:breakpoints/.test(dataSrc):
|
4304
4304
|
requiredWidth = maxWidth(containerWidth, tag);
|
4305
|
-
|
4305
|
+
if (requiredWidth) {
|
4306
|
+
dataSrc = dataSrc.replace(/w_auto:breakpoints([_0-9]*)(:[0-9]+)?/, "w_auto:breakpoints$1:" + requiredWidth);
|
4307
|
+
} else {
|
4308
|
+
setUrl = false;
|
4309
|
+
}
|
4306
4310
|
break;
|
4307
4311
|
case !(match = /w_auto(:(\d+))?/.exec(dataSrc)):
|
4308
4312
|
requiredWidth = applyBreakpoints.call(this, tag, containerWidth, match[2], options);
|
4309
4313
|
requiredWidth = maxWidth(requiredWidth, tag);
|
4310
|
-
|
4314
|
+
if (requiredWidth) {
|
4315
|
+
dataSrc = dataSrc.replace(/w_auto[^,\/]*/g, "w_" + requiredWidth);
|
4316
|
+
} else {
|
4317
|
+
setUrl = false;
|
4318
|
+
}
|
4311
4319
|
}
|
4312
4320
|
Util.removeAttribute(tag, 'width');
|
4313
4321
|
if (!options.responsive_preserve_height) {
|
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.21.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-
|
13
|
+
date: 2021-08-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws_cf_signer
|