cloudinary 1.28.0 → 1.29.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97b754051e806086f5dfb98479292bb84bed48968c242d8c55dfa073a8d90e52
4
- data.tar.gz: 6a6484d454b0b074fa177b68e90bb62a100c90aa3f4b3ab33dad9acd64d7ec4d
3
+ metadata.gz: 0ec56a8224fa9a3318d7e0d3e7ce7747c888767a4b365a752310e38b7747f4a3
4
+ data.tar.gz: 58f0148449592fb70e8a87bc292ddeea43a09b0f879fca9c62c1594b3ff487cc
5
5
  SHA512:
6
- metadata.gz: dd822c6ec7144df3f7ab863d834802c486bc31ef5051cafbb9d331279a0f3092906990c211ccf1802515d53d51f64e71fd1bd73acc8a2f368c22bddd90ea3a38
7
- data.tar.gz: cc2299facddd71188d08c0f934ad8483bc0c9414364699e3f84a20eee489f0883adca4ba838a9534d417e11580ff194761d0d26cc978079c9e3b2f42cceeaa48
6
+ metadata.gz: 44e6c4cefaebd3853f8da9c40123d05205b6fa57fd58eb22e1a8a419bad658b3184eb2bd068f79b8d54601793295c333e6a02720d6a5bdbcb699b234432603e2
7
+ data.tar.gz: de7032533e031e15c51ccc17ff8e77a2aabc6f9aea4958a58d2313b30aeadc8b14574e36090c99a9e58788e3a376bc9330cfdd0e8d77fcb96d3d4deea7cbfd57
data/.travis.yml CHANGED
@@ -1,22 +1,17 @@
1
- dist: focal
1
+ dist: jammy
2
2
  language: ruby
3
3
  rvm:
4
- - 2.6.7
5
- - 2.7.4
6
- - 3.0.2
4
+ - 2.7.8
5
+ - 3.1.4
6
+ - 3.2.2
7
+ - 3.3.0
7
8
 
8
9
  matrix:
9
10
  include:
10
- - name: "Ruby 1.9"
11
- dist: precise
12
- rvm: 1.9.3
13
- before_install:
14
- - gem install bundler -v 1.17.3
15
- - name: "Ruby 2.5.9"
16
- dist: xenial
17
- rvm: ruby-2.5.9
18
- before_install:
19
- - gem install bundler -v 2.3.26
11
+ # There is an OpenSSL issue on Jammy with Ruby 3.0
12
+ - name: "Ruby: 3.0.6"
13
+ dist: focal
14
+ rvm: 3.0.6
20
15
 
21
16
  before_script: >
22
17
  export CLOUDINARY_URL=$(bash tools/get_test_cloud.sh);
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ 1.29.0 / 2024-02-26
2
+ ==================
3
+
4
+ New functionality and features
5
+ ------------------------------
6
+
7
+ * Add support for `context` parameter in `url_for_direct_upload`
8
+ * Add support for `use_fetch_format` parameter in `cl_video_tag`
9
+ * Add support for `fields` parameter in Search and Admin APIs
10
+ * Add support for access keys management in Account Provisioning API
11
+
12
+ Other Changes
13
+ -------------
14
+
15
+ * Avoid early loading of `ActionView::Base`
16
+ * Fix `sqlite3` dependency version
17
+ * Add Rails 7.x to supported versions on `README.md`
18
+
1
19
  1.28.0 / 2023-11-06
2
20
  ==================
3
21
 
data/README.md CHANGED
@@ -42,9 +42,9 @@ the [Ruby on Rails SDK Guide](https://cloudinary.com/documentation/rails_integra
42
42
  |-------------|------------|----------|----------|
43
43
  | 1.x | v | v | v |
44
44
 
45
- | SDK Version | Rails 5.x | Rails 6.x |
46
- |-------------|-----------|-----------|
47
- | 1.x | v | v |
45
+ | SDK Version | Rails 5.x | Rails 6.x | Rails 7.x |
46
+ |-------------|-----------|-----------|-----------|
47
+ | 1.x | v | v | v |
48
48
 
49
49
  ## Installation
50
50
 
data/cloudinary.gemspec CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
39
39
  else
40
40
  s.add_development_dependency "rake", "<= 12.2.1"
41
41
  end
42
- if RUBY_VERSION >= "2.7.0"
42
+ if RUBY_VERSION >= "3.0.0"
43
43
  s.add_development_dependency "sqlite3"
44
44
  else
45
45
  s.add_development_dependency "sqlite3", "< 1.6.0"
@@ -81,7 +81,9 @@ module ActiveStorage
81
81
  # through direct upload (client side js), filename is missing, and that leads to inconsistent/broken URLs.
82
82
  # To avoid that, we explicitly pass file format in options.
83
83
  options[:format] = ext_for_file(key) if options[:resource_type] == "raw"
84
+ context = options.delete(:context)
84
85
  options[:context] = {active_storage_key: key}
86
+ options[:context].reverse_merge!(context) if context.respond_to?(:merge)
85
87
  options.delete(:file)
86
88
  payload[:url] = api_uri("upload", options)
87
89
  end
@@ -13,10 +13,10 @@ class Cloudinary::AccountApi
13
13
  # @param [Object] options additional options
14
14
  def self.create_sub_account(name, cloud_name = nil, custom_attributes = {}, enabled = nil, base_account = nil, options = {})
15
15
  params = {
16
- name: name,
17
- cloud_name: cloud_name,
18
- custom_attributes: custom_attributes,
19
- enabled: enabled,
16
+ name: name,
17
+ cloud_name: cloud_name,
18
+ custom_attributes: custom_attributes,
19
+ enabled: enabled,
20
20
  base_sub_account_id: base_account
21
21
  }
22
22
 
@@ -35,10 +35,10 @@ class Cloudinary::AccountApi
35
35
  # @param [Object] options additional options
36
36
  def self.update_sub_account(sub_account_id, name = nil, cloud_name = nil, custom_attributes = nil, enabled = nil, options = {})
37
37
  params = {
38
- name: name,
39
- cloud_name: cloud_name,
38
+ name: name,
39
+ cloud_name: cloud_name,
40
40
  custom_attributes: custom_attributes,
41
- enabled: enabled
41
+ enabled: enabled
42
42
  }
43
43
 
44
44
  call_account_api(:put, ['sub_accounts', sub_account_id], params, options.merge(content_type: :json))
@@ -53,8 +53,8 @@ class Cloudinary::AccountApi
53
53
  def self.sub_accounts(enabled = nil, ids = [], prefix = nil, options = {})
54
54
  params = {
55
55
  enabled: enabled,
56
- ids: ids,
57
- prefix: prefix
56
+ ids: ids,
57
+ prefix: prefix
58
58
  }
59
59
 
60
60
  call_account_api(:get, 'sub_accounts', params, options.merge(content_type: :json))
@@ -84,9 +84,9 @@ class Cloudinary::AccountApi
84
84
  # @param [Object] options additional options
85
85
  def self.create_user(name, email, role, sub_account_ids = [], options = {})
86
86
  params = {
87
- name: name,
88
- email: email,
89
- role: role,
87
+ name: name,
88
+ email: email,
89
+ role: role,
90
90
  sub_account_ids: sub_account_ids
91
91
  }
92
92
 
@@ -111,9 +111,9 @@ class Cloudinary::AccountApi
111
111
  # @param [Object] options additional options
112
112
  def self.update_user(user_id, name = nil, email = nil, role = nil, sub_account_ids = nil, options = {})
113
113
  params = {
114
- name: name,
115
- email: email,
116
- role: role,
114
+ name: name,
115
+ email: email,
116
+ role: role,
117
117
  sub_account_ids: sub_account_ids
118
118
  }
119
119
 
@@ -135,10 +135,10 @@ class Cloudinary::AccountApi
135
135
  # @param [Object] options additional options
136
136
  def self.users(pending = nil, user_ids = [], prefix = nil, sub_account_id = nil, options = {})
137
137
  params = {
138
- ids: user_ids,
139
- prefix: prefix,
138
+ ids: user_ids,
139
+ prefix: prefix,
140
140
  sub_account_id: sub_account_id,
141
- pending: pending
141
+ pending: pending
142
142
  }
143
143
 
144
144
  call_account_api(:get, 'users', params, options.merge(content_type: :json))
@@ -210,6 +210,44 @@ class Cloudinary::AccountApi
210
210
  call_account_api(:get, ['user_groups', group_id, 'users'], {}, options.merge(content_type: :json))
211
211
  end
212
212
 
213
+ # Lists access keys.
214
+ #
215
+ # @param [String] sub_account_id The ID of the sub-account.
216
+ # @param [Object] options Additional options.
217
+ def self.access_keys(sub_account_id, options = {})
218
+ params = Cloudinary::Api.only(options, :page_size, :page, :sort_by, :sort_order)
219
+ call_account_api(:get, ['sub_accounts', sub_account_id, 'access_keys'], params, options)
220
+ end
221
+
222
+ # Generates access key.
223
+ #
224
+ # @param [String] sub_account_id The ID of the sub-account.
225
+ # @param [String] name The display name as shown in the management console.
226
+ # @param [Boolean] enabled Whether to create the access key as enabled (default is enabled).
227
+ # @param [Object] options Additional options.
228
+ def self.generate_access_key(sub_account_id, name = nil, enabled = nil, options = {})
229
+ params = {
230
+ name: name,
231
+ enabled: enabled,
232
+ }
233
+ call_account_api(:post, ['sub_accounts', sub_account_id, 'access_keys'], params, options.merge(content_type: :json))
234
+ end
235
+
236
+ # Updates access key.
237
+ #
238
+ # @param [String] sub_account_id The ID of the sub-account.
239
+ # @param [String] api_key The API key.
240
+ # @param [String] name The display name as shown in the management console.
241
+ # @param [Boolean] enabled Enable or disable the access key.
242
+ # @param [Object] options Additional options.
243
+ def self.update_access_key(sub_account_id, api_key, name = nil, enabled = nil, options = {})
244
+ params = {
245
+ name: name,
246
+ enabled: enabled,
247
+ }
248
+ call_account_api(:put, ['sub_accounts', sub_account_id, 'access_keys', api_key], params, options.merge(content_type: :json))
249
+ end
250
+
213
251
  def self.call_account_api(method, uri, params, options)
214
252
  account_id = options[:account_id] || Cloudinary.account_config.account_id || raise('Must supply account_id')
215
253
  api_key = options[:provisioning_api_key] || Cloudinary.account_config.provisioning_api_key || raise('Must supply provisioning api_key')
@@ -68,7 +68,7 @@ class Cloudinary::Api
68
68
  type = options[:type]
69
69
  uri = "resources/#{resource_type}"
70
70
  uri += "/#{type}" unless type.blank?
71
- call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context, :moderations, :direction, :start_at, :metadata), options)
71
+ call_api(:get, uri, list_resources_params(options).merge(only(options, :prefix, :start_at)), options)
72
72
  end
73
73
 
74
74
  # Lists assets with the specified tag.
@@ -87,7 +87,7 @@ class Cloudinary::Api
87
87
  def self.resources_by_tag(tag, options={})
88
88
  resource_type = options[:resource_type] || "image"
89
89
  uri = "resources/#{resource_type}/tags/#{tag}"
90
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
90
+ call_api(:get, uri, list_resources_params(options), options)
91
91
  end
92
92
 
93
93
  # Lists assets currently in the specified moderation queue and status.
@@ -107,7 +107,7 @@ class Cloudinary::Api
107
107
  def self.resources_by_moderation(kind, status, options={})
108
108
  resource_type = options[:resource_type] || "image"
109
109
  uri = "resources/#{resource_type}/moderations/#{kind}/#{status}"
110
- call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :metadata), options)
110
+ call_api(:get, uri, list_resources_params(options), options)
111
111
  end
112
112
 
113
113
  # Lists assets with the specified contextual metadata.
@@ -129,30 +129,9 @@ class Cloudinary::Api
129
129
  def self.resources_by_context(key, value=nil, options={})
130
130
  resource_type = options[:resource_type] || "image"
131
131
  uri = "resources/#{resource_type}/context"
132
- params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :key, :value, :metadata)
133
- params[:key] = key
134
- params[:value] = value
135
- call_api(:get, uri, params, options)
132
+ call_api(:get, uri, list_resources_params(options, :key => key, :value => value), options)
136
133
  end
137
134
 
138
- # Returns the details of the specified asset and all its derived assets by asset id.
139
- #
140
- # Note that if you only need details about the original asset,
141
- # you can also use the Uploader::upload or Uploader::explicit methods, which return the same information and
142
- # are not rate limited.
143
- #
144
- # @param [String] asset_id The Asset ID of the asset.
145
- # @param [Hash] options The optional parameters. See the <a href=https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource target="_blank"> Admin API</a> documentation.
146
- #
147
- # @return [Cloudinary::Api::Response]
148
- #
149
- # @see https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource
150
- def self.resource_by_asset_id(asset_id, options={})
151
- uri = "resources/#{asset_id}"
152
- params = prepare_resource_details_params(options)
153
- call_api(:get, uri, params, options)
154
- end
155
-
156
135
  # Lists assets with the specified public IDs.
157
136
  #
158
137
  # @param [String|Array] public_ids The requested public_ids (up to 100).
@@ -168,7 +147,7 @@ class Cloudinary::Api
168
147
  resource_type = options[:resource_type] || "image"
169
148
  type = options[:type] || "upload"
170
149
  uri = "resources/#{resource_type}/#{type}"
171
- call_api(:get, uri, only(options, :tags, :context, :moderations).merge(:public_ids => public_ids), options)
150
+ call_api(:get, uri, resources_params(options, :public_ids => public_ids), options)
172
151
  end
173
152
 
174
153
  # Lists assets with the specified asset IDs.
@@ -184,9 +163,7 @@ class Cloudinary::Api
184
163
  # @see https://cloudinary.com/documentation/admin_api#get_resources
185
164
  def self.resources_by_asset_ids(asset_ids, options={})
186
165
  uri = "resources/by_asset_ids"
187
- params = only(options, :public_ids, :tags, :moderations, :context)
188
- params[:asset_ids] = asset_ids
189
- call_api(:get, uri, params, options)
166
+ call_api(:get, uri, resources_params(options, :asset_ids => asset_ids), options)
190
167
  end
191
168
 
192
169
  # Returns all assets stored directly in a specified asset folder, regardless of the public ID paths of those assets.
@@ -202,9 +179,7 @@ class Cloudinary::Api
202
179
  # @see https://cloudinary.com/documentation/dynamic_folders#new_admin_api_endpoints
203
180
  def self.resources_by_asset_folder(asset_folder, options={})
204
181
  uri = "resources/by_asset_folder"
205
- params = only(options, :next_cursor, :max_results, :tags, :context, :moderations, :direction, :key, :value, :metadata)
206
- params[:asset_folder] = asset_folder
207
- call_api(:get, uri, params, options)
182
+ call_api(:get, uri, list_resources_params(options, :asset_folder => asset_folder), options)
208
183
  end
209
184
 
210
185
  # Find images based on their visual content.
@@ -243,6 +218,23 @@ class Cloudinary::Api
243
218
  call_api(:get, uri, prepare_resource_details_params(options), options)
244
219
  end
245
220
 
221
+ # Returns the details of the specified asset and all its derived assets by asset id.
222
+ #
223
+ # Note that if you only need details about the original asset,
224
+ # you can also use the Uploader::upload or Uploader::explicit methods, which return the same information and
225
+ # are not rate limited.
226
+ #
227
+ # @param [String] asset_id The Asset ID of the asset.
228
+ # @param [Hash] options The optional parameters. See the <a href=https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource target="_blank"> Admin API</a> documentation.
229
+ #
230
+ # @return [Cloudinary::Api::Response]
231
+ #
232
+ # @see https://cloudinary.com/documentation/admin_api#get_the_details_of_a_single_resource
233
+ def self.resource_by_asset_id(asset_id, options={})
234
+ uri = "resources/#{asset_id}"
235
+ call_api(:get, uri, prepare_resource_details_params(options), options)
236
+ end
237
+
246
238
  # Reverts to the latest backed up version of the specified deleted assets.
247
239
  #
248
240
  # @param [String|Array] public_ids The public IDs of the backed up assets to restore. They can be existing or
@@ -1399,4 +1391,19 @@ class Cloudinary::Api
1399
1391
  params[by_key] = value
1400
1392
  call_api("post", "resources/#{resource_type}/#{type}/update_access_mode", params, options)
1401
1393
  end
1394
+
1395
+ private
1396
+
1397
+ RESOURCES_PARAMS = [:tags, :context, :metadata, :moderations, :fields].freeze
1398
+ LIST_RESOURCES_PARAMS = [:next_cursor, :max_results, :direction].freeze
1399
+
1400
+ def self.resources_params(options, params = {})
1401
+ params.merge!(only(options, *RESOURCES_PARAMS))
1402
+ params[:fields] = Cloudinary::Utils.build_array(options[:fields]).join(",") unless params[:fields].nil?
1403
+ params
1404
+ end
1405
+
1406
+ def self.list_resources_params(options, params = {})
1407
+ params.merge(resources_params(options)).merge!(only(options, *LIST_RESOURCES_PARAMS))
1408
+ end
1402
1409
  end
@@ -3,7 +3,9 @@ class Cloudinary::Railtie < Rails::Railtie
3
3
  Dir[File.join(File.dirname(__FILE__),'../tasks/**/*.rake')].each { |f| load f }
4
4
  end
5
5
  config.after_initialize do |app|
6
- ActionView::Base.send :include, CloudinaryHelper
6
+ ActiveSupport.on_load(:action_view) do
7
+ ActionView::Base.send :include, CloudinaryHelper
8
+ end
7
9
  end
8
10
 
9
11
  ActiveSupport.on_load(:action_controller_base) do
@@ -4,7 +4,8 @@ class Cloudinary::Search
4
4
  SORT_BY = :sort_by
5
5
  AGGREGATE = :aggregate
6
6
  WITH_FIELD = :with_field
7
- KEYS_WITH_UNIQUE_VALUES = [SORT_BY, AGGREGATE, WITH_FIELD].freeze
7
+ FIELDS = :fields
8
+ KEYS_WITH_UNIQUE_VALUES = [SORT_BY, AGGREGATE, WITH_FIELD, FIELDS].freeze
8
9
 
9
10
  TTL = 300 # Used for search URLs
10
11
 
@@ -12,7 +13,8 @@ class Cloudinary::Search
12
13
  @query_hash = {
13
14
  SORT_BY => {},
14
15
  AGGREGATE => {},
15
- WITH_FIELD => {}
16
+ WITH_FIELD => {},
17
+ FIELDS => {},
16
18
  }
17
19
 
18
20
  @endpoint = self.class::ENDPOINT
@@ -59,7 +61,7 @@ class Cloudinary::Search
59
61
  #
60
62
  # @param [String] value Supported values: resource_type, type, pixels (only the image assets in the response are
61
63
  # aggregated), duration (only the video assets in the response are aggregated), format, and
62
- # bytes. For aggregation fields without discrete values, the results are divided into
64
+ # bytes. For aggregation fields without discrete values, the results are divided into
63
65
  # categories.
64
66
  # @return [Cloudinary::Search]
65
67
  def aggregate(value)
@@ -77,6 +79,19 @@ class Cloudinary::Search
77
79
  self
78
80
  end
79
81
 
82
+
83
+ # The list of the asset attributes to include for each asset in the response.
84
+ #
85
+ # @param [Array] value The array of attributes' names.
86
+ #
87
+ # @return [Cloudinary::Search]
88
+ def fields(value)
89
+ Cloudinary::Utils.build_array(value).each do |field|
90
+ @query_hash[FIELDS][field] = field
91
+ end
92
+ self
93
+ end
94
+
80
95
  # Sets the time to live of the search URL.
81
96
  #
82
97
  # @param [Object] ttl The time to live in seconds.
@@ -998,6 +998,12 @@ class Cloudinary::Utils
998
998
  option_value.nil? ? default_value : option_value
999
999
  end
1000
1000
 
1001
+ def self.config_option_fetch(options, option_name, default_value = nil)
1002
+ return options.fetch(option_name) if options.include?(option_name)
1003
+ option_value = Cloudinary.config.send(option_name)
1004
+ option_value.nil? ? default_value : option_value
1005
+ end
1006
+
1001
1007
  def self.as_bool(value)
1002
1008
  case value
1003
1009
  when nil then nil
@@ -1250,7 +1256,8 @@ class Cloudinary::Utils
1250
1256
  # @param options url and transformation options. This argument may be changed by the function!
1251
1257
  #
1252
1258
  def self.patch_fetch_format(options={})
1253
- if options[:type] === :fetch
1259
+ use_fetch_format = config_option_consume(options, :use_fetch_format)
1260
+ if options[:type] === :fetch || use_fetch_format
1254
1261
  format_arg = options.delete(:format)
1255
1262
  options[:fetch_format] ||= format_arg
1256
1263
  end
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.28.0"
3
+ VERSION = "1.29.0"
4
4
  end
@@ -53,7 +53,7 @@ module CloudinaryHelper
53
53
  # }
54
54
  # ])
55
55
  def cl_video_tag(source, options = {}, &block)
56
- source = strip_known_ext(source)
56
+ source = strip_known_ext(source) unless Cloudinary::Utils.config_option_fetch(options, :use_fetch_format)
57
57
  video_attributes = [:autoplay,:controls,:loop,:muted,:poster, :preload]
58
58
  options = Cloudinary::Utils.deep_symbolize_keys(DEFAULT_VIDEO_OPTIONS.merge(options))
59
59
 
@@ -155,8 +155,9 @@ module CloudinaryHelper
155
155
  content_tag('video', tag_options.merge(video_options)) do
156
156
  source_tags = sources.map do |source|
157
157
  type = source[:type]
158
+ options[:format] = type
158
159
  transformation = source[:transformations] || {}
159
- cloudinary_tag("#{source_name}.#{type}", options.merge(transformation)) do |url, _tag_options|
160
+ cloudinary_tag(source_name, options.merge(transformation)) do |url, _tag_options|
160
161
  mime_type = "video/#{(type == 'ogv' ? 'ogg' : type)}"
161
162
  if source[:codecs]
162
163
  codecs = source[:codecs].is_a?(Array) ? source[:codecs].join(", ") : source[:codecs]
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.28.0
4
+ version: 1.29.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: 2023-11-06 00:00:00.000000000 Z
13
+ date: 2024-02-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws_cf_signer
@@ -86,16 +86,16 @@ dependencies:
86
86
  name: sqlite3
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - ">="
89
+ - - "<"
90
90
  - !ruby/object:Gem::Version
91
- version: '0'
91
+ version: 1.6.0
92
92
  type: :development
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
- - - ">="
96
+ - - "<"
97
97
  - !ruby/object:Gem::Version
98
- version: '0'
98
+ version: 1.6.0
99
99
  - !ruby/object:Gem::Dependency
100
100
  name: rspec
101
101
  requirement: !ruby/object:Gem::Requirement