cloudinary 1.28.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -657,7 +649,7 @@ class Cloudinary::Api
657
649
  #
658
650
  # @see https://cloudinary.com/documentation/admin_api#update_an_upload_preset
659
651
  def self.update_upload_preset(name, options={})
660
- params = Cloudinary::Uploader.build_upload_params(options)
652
+ params = Cloudinary::Uploader.build_upload_params(options, true)
661
653
  call_api(:put, "upload_presets/#{name}", params.merge(only(options, :unsigned, :disallow_public_id, :live)), options)
662
654
  end
663
655
 
@@ -672,7 +664,7 @@ class Cloudinary::Api
672
664
  #
673
665
  # @see https://cloudinary.com/documentation/admin_api#create_an_upload_preset
674
666
  def self.create_upload_preset(options={})
675
- params = Cloudinary::Uploader.build_upload_params(options)
667
+ params = Cloudinary::Uploader.build_upload_params(options, true)
676
668
  call_api(:post, "upload_presets", params.merge(only(options, :name, :unsigned, :disallow_public_id, :live)), options)
677
669
  end
678
670
 
@@ -1230,6 +1222,25 @@ class Cloudinary::Api
1230
1222
  call_metadata_rules_api(:delete, uri, {}, options)
1231
1223
  end
1232
1224
 
1225
+ # Analyzes an asset with the requested analysis type.
1226
+ #
1227
+ # @param [Object] input_type The type of input for the asset to analyze ('uri').
1228
+ # @param [Object] analysis_type The type of analysis to run ('google_tagging', 'captioning', 'fashion').
1229
+ # @param [Hash] options The optional parameters.
1230
+ #
1231
+ # @return [Cloudinary::Api::Response]
1232
+ #
1233
+ # @raise [Cloudinary::Api::Error]
1234
+ def self.analyze(input_type, analysis_type, options = {})
1235
+ api_uri = ["analysis", "analyze", input_type]
1236
+ params = only(options, :uri, :parameters)
1237
+ params["analysis_type"] = analysis_type
1238
+
1239
+ options[:api_version] = 'v2'
1240
+
1241
+ call_api(:post, api_uri, params, options)
1242
+ end
1243
+
1233
1244
  protected
1234
1245
 
1235
1246
  # Execute a call api for input params.
@@ -1244,13 +1255,14 @@ class Cloudinary::Api
1244
1255
  api_key = options[:api_key] || Cloudinary.config.api_key
1245
1256
  api_secret = options[:api_secret] || Cloudinary.config.api_secret
1246
1257
  oauth_token = options[:oauth_token] || Cloudinary.config.oauth_token
1258
+ api_version = options[:api_version] || Cloudinary.config.api_version || 'v1_1'
1247
1259
 
1248
1260
  validate_authorization(api_key, api_secret, oauth_token)
1249
1261
 
1250
1262
  auth = { :key => api_key, :secret => api_secret, :oauth_token => oauth_token }
1251
1263
 
1252
1264
  call_cloudinary_api(method, uri, auth, params, options) do |cloudinary, inner_uri|
1253
- [cloudinary, 'v1_1', cloud_name, inner_uri]
1265
+ [cloudinary, api_version, cloud_name, inner_uri]
1254
1266
  end
1255
1267
  end
1256
1268
 
@@ -1262,7 +1274,7 @@ class Cloudinary::Api
1262
1274
  return Cloudinary::Utils.json_decode(response.body)
1263
1275
  rescue => e
1264
1276
  # Error is parsing json
1265
- raise GeneralError.new("Error parsing server response (#{response.code}) - #{response.body}. Got - #{e}")
1277
+ raise GeneralError.new("Error parsing server response (#{response.status}) - #{response.body}. Got - #{e}")
1266
1278
  end
1267
1279
 
1268
1280
  # Protected function that assists with performing an API call to the metadata_fields part of the Admin API.
@@ -1399,4 +1411,19 @@ class Cloudinary::Api
1399
1411
  params[by_key] = value
1400
1412
  call_api("post", "resources/#{resource_type}/#{type}/update_access_mode", params, options)
1401
1413
  end
1414
+
1415
+ private
1416
+
1417
+ RESOURCES_PARAMS = [:tags, :context, :metadata, :moderations, :fields].freeze
1418
+ LIST_RESOURCES_PARAMS = [:next_cursor, :max_results, :direction].freeze
1419
+
1420
+ def self.resources_params(options, params = {})
1421
+ params.merge!(only(options, *RESOURCES_PARAMS))
1422
+ params[:fields] = Cloudinary::Utils.build_array(options[:fields]).join(",") unless params[:fields].nil?
1423
+ params
1424
+ end
1425
+
1426
+ def self.list_resources_params(options, params = {})
1427
+ params.merge(resources_params(options)).merge!(only(options, *LIST_RESOURCES_PARAMS))
1428
+ end
1402
1429
  end
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openssl'
4
- if RUBY_VERSION > "2"
5
- require "ostruct"
6
- else
7
- require "cloudinary/ostruct2"
8
- end
4
+ require "ostruct"
9
5
 
10
6
 
11
7
  module Cloudinary
@@ -1,7 +1,8 @@
1
- require "rest_client"
1
+ require "faraday"
2
2
  require "json"
3
3
 
4
4
  module Cloudinary::BaseApi
5
+ @adapter = nil
5
6
  class Error < CloudinaryException; end
6
7
  class NotFound < Error; end
7
8
  class NotAllowed < Error; end
@@ -15,17 +16,19 @@ module Cloudinary::BaseApi
15
16
  attr_reader :rate_limit_reset_at, :rate_limit_remaining, :rate_limit_allowed
16
17
 
17
18
  def initialize(response=nil)
18
- if response
19
- # This sets the instantiated self as the response Hash
20
- update Cloudinary::Api.parse_json_response response
19
+ unless response
20
+ return
21
+ end
21
22
 
22
- # According to RFC 2616, header names are case-insensitive.
23
- lc_headers = response.headers.transform_keys(&:downcase)
23
+ # This sets the instantiated self as the response Hash
24
+ update Cloudinary::Api.parse_json_response response
24
25
 
25
- @rate_limit_allowed = lc_headers[:x_featureratelimit_limit].to_i if lc_headers[:x_featureratelimit_limit]
26
- @rate_limit_reset_at = Time.parse(lc_headers[:x_featureratelimit_reset]) if lc_headers[:x_featureratelimit_reset]
27
- @rate_limit_remaining = lc_headers[:x_featureratelimit_remaining].to_i if lc_headers[:x_featureratelimit_remaining]
28
- end
26
+ # According to RFC 2616, header names are case-insensitive.
27
+ lc_headers = response.headers.transform_keys(&:downcase)
28
+
29
+ @rate_limit_allowed = lc_headers["x-featureratelimit-limit"].to_i if lc_headers["x-featureratelimit-limit"]
30
+ @rate_limit_reset_at = Time.parse(lc_headers["x-featureratelimit-reset"]) if lc_headers["x-featureratelimit-reset"]
31
+ @rate_limit_remaining = lc_headers["x-featureratelimit-remaining"].to_i if lc_headers["x-featureratelimit-remaining"]
29
32
  end
30
33
  end
31
34
 
@@ -36,28 +39,30 @@ module Cloudinary::BaseApi
36
39
  end
37
40
 
38
41
  def call_json_api(method, api_url, payload, timeout, headers, proxy = nil, user = nil, password = nil)
39
- RestClient::Request.execute(method: method,
40
- url: api_url,
41
- payload: payload,
42
- timeout: timeout,
43
- headers: headers,
44
- proxy: proxy,
45
- user: user,
46
- password: password) do |response|
47
- return Response.new(response) if response.code == 200
48
- exception_class = case response.code
49
- when 400 then BadRequest
50
- when 401 then AuthorizationRequired
51
- when 403 then NotAllowed
52
- when 404 then NotFound
53
- when 409 then AlreadyExists
54
- when 420 then RateLimited
55
- when 500 then GeneralError
56
- else raise GeneralError.new("Server returned unexpected status code - #{response.code} - #{response.body}")
57
- end
58
- json = Cloudinary::Api.parse_json_response(response)
59
- raise exception_class.new(json["error"]["message"])
42
+ conn = Faraday.new(url: api_url) do |faraday|
43
+ faraday.proxy = proxy if proxy
44
+ faraday.request :json
45
+ faraday.adapter @adapter || Faraday.default_adapter
60
46
  end
47
+
48
+ response = conn.run_request(method.downcase.to_sym, nil, payload, headers) do |req|
49
+ req.options.timeout = timeout if timeout
50
+ req.basic_auth(user, password) if user && password
51
+ end
52
+
53
+ return Response.new(response) if response.status == 200
54
+ exception_class = case response.status
55
+ when 400 then BadRequest
56
+ when 401 then AuthorizationRequired
57
+ when 403 then NotAllowed
58
+ when 404 then NotFound
59
+ when 409 then AlreadyExists
60
+ when 420 then RateLimited
61
+ when 500 then GeneralError
62
+ else raise GeneralError.new("Server returned unexpected status code - #{response.status} - #{response.body}")
63
+ end
64
+ json = Cloudinary::Api.parse_json_response(response)
65
+ raise exception_class.new(json["error"]["message"])
61
66
  end
62
67
 
63
68
  private
@@ -36,7 +36,8 @@ class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
36
36
  params[:type]=uploader.class.storage_type
37
37
 
38
38
  params[:resource_type] ||= :auto
39
- uploader.metadata = Cloudinary::Uploader.upload(data, params)
39
+ upload_method = uploader.upload_chunked? ? "upload_large" : "upload"
40
+ uploader.metadata = Cloudinary::Uploader.send(upload_method, data, params)
40
41
  if uploader.metadata["error"]
41
42
  raise Cloudinary::CarrierWave::UploadError.new(uploader.metadata["error"]["message"], uploader.metadata["error"]["http_code"])
42
43
  end
@@ -192,11 +192,6 @@ module Cloudinary::CarrierWave
192
192
 
193
193
  end
194
194
 
195
- # @deprecated
196
- def self.split_format(identifier)
197
- return Cloudinary::PreloadedFile.split_format(identifier)
198
- end
199
-
200
195
  def default_format
201
196
  "png"
202
197
  end
@@ -286,13 +286,6 @@ module CloudinaryHelper
286
286
  Cloudinary::Utils.private_download_url(public_id, format, options)
287
287
  end
288
288
 
289
- # Helper method that uses the deprecated ZIP download API.
290
- # Replaced by cl_download_zip_url that uses the more advanced and robust archive generation and download API
291
- # @deprecated
292
- def cl_zip_download_url(tag, options = {})
293
- Cloudinary::Utils.zip_download_url(tag, options)
294
- end
295
-
296
289
  # @see {Cloudinary::Utils.download_archive_url}
297
290
  def cl_download_archive_url(options = {})
298
291
  Cloudinary::Utils.download_archive_url(options)
@@ -304,13 +297,13 @@ module CloudinaryHelper
304
297
  end
305
298
 
306
299
  def cl_signed_download_url(public_id, options = {})
307
- Cloudinary::Utils.signed_download_url(public_id, options)
300
+ Cloudinary::Utils.cloudinary_url(public_id, options)
308
301
  end
309
302
 
310
303
  def self.included(base)
311
304
  ActionView::Helpers::FormBuilder.send(:include, Cloudinary::FormBuilder)
312
305
  base.class_eval do
313
- if !method_defined?(:image_tag)
306
+ unless method_defined?(:image_tag)
314
307
  include ActionView::Helpers::AssetTagHelper
315
308
  end
316
309
  alias_method :image_tag_without_cloudinary, :image_tag unless public_method_defined? :image_tag_without_cloudinary
@@ -325,7 +318,6 @@ module CloudinaryHelper
325
318
  private
326
319
 
327
320
  def cloudinary_url_internal(source, options = {})
328
- options[:ssl_detected] = request.ssl? if defined?(request) && request && request.respond_to?(:ssl?)
329
321
  if defined?(CarrierWave::Uploader::Base) && source.is_a?(CarrierWave::Uploader::Base)
330
322
  if source.version_name.present?
331
323
  options[:transformation] = Cloudinary::Utils.build_array(source.transformation) + Cloudinary::Utils.build_array(options[:transformation])