cloudinary 1.28.0 → 2.0.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/.travis.yml +8 -14
- data/CHANGELOG.md +51 -0
- data/README.md +7 -5
- data/cloudinary.gemspec +21 -51
- data/lib/active_storage/service/cloudinary_service.rb +6 -2
- data/lib/cloudinary/account_api.rb +76 -25
- data/lib/cloudinary/analytics.rb +157 -0
- data/lib/cloudinary/api.rb +63 -36
- data/lib/cloudinary/auth_token.rb +1 -5
- data/lib/cloudinary/base_api.rb +36 -31
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/carrier_wave.rb +0 -5
- data/lib/cloudinary/helper.rb +2 -10
- data/lib/cloudinary/migrator.rb +70 -71
- data/lib/cloudinary/railtie.rb +3 -1
- data/lib/cloudinary/search.rb +18 -3
- data/lib/cloudinary/uploader.rb +70 -90
- data/lib/cloudinary/utils.rb +39 -55
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary/video_helper.rb +3 -2
- data/lib/cloudinary.rb +3 -9
- data/lib/tasks/cloudinary/fetch_assets.rake +9 -3
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +3 -3
- metadata +164 -38
- data/lib/cloudinary/ostruct2.rb +0 -284
data/lib/cloudinary/api.rb
CHANGED
@@ -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, :
|
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,
|
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,
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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,
|
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.
|
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
|
data/lib/cloudinary/base_api.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
require "
|
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
|
-
|
19
|
-
|
20
|
-
|
19
|
+
unless response
|
20
|
+
return
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
# This sets the instantiated self as the response Hash
|
24
|
+
update Cloudinary::Api.parse_json_response response
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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.
|
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
|
data/lib/cloudinary/helper.rb
CHANGED
@@ -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.
|
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
|
-
|
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])
|