cloudinary 1.21.0 → 1.22.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 +12 -2
- data/CHANGELOG.md +23 -0
- data/README.md +87 -237
- data/cloudinary.gemspec +10 -1
- data/lib/cloudinary/account_api.rb +2 -1
- data/lib/cloudinary/api.rb +737 -112
- data/lib/cloudinary/auth_token.rb +1 -1
- data/lib/cloudinary/base_api.rb +18 -2
- data/lib/cloudinary/uploader.rb +15 -7
- data/lib/cloudinary/utils.rb +26 -12
- data/lib/cloudinary/version.rb +1 -1
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +10 -1
- metadata +4 -3
@@ -43,7 +43,7 @@ module Cloudinary
|
|
43
43
|
token << "exp=#{expiration}"
|
44
44
|
token << "acl=#{escape_to_lower(acl)}" if acl
|
45
45
|
to_sign = token.clone
|
46
|
-
to_sign << "url=#{escape_to_lower(url)}" if url
|
46
|
+
to_sign << "url=#{escape_to_lower(url)}" if url && acl.blank?
|
47
47
|
auth = digest(to_sign.join(SEPARATOR), key)
|
48
48
|
token << "hmac=#{auth}"
|
49
49
|
"#{name}=#{token.join(SEPARATOR)}"
|
data/lib/cloudinary/base_api.rb
CHANGED
@@ -59,13 +59,14 @@ module Cloudinary::BaseApi
|
|
59
59
|
|
60
60
|
private
|
61
61
|
|
62
|
-
def call_cloudinary_api(method, uri,
|
62
|
+
def call_cloudinary_api(method, uri, auth, params, options, &api_url_builder)
|
63
63
|
cloudinary = options[:upload_prefix] || Cloudinary.config.upload_prefix || 'https://api.cloudinary.com'
|
64
64
|
api_url = Cloudinary::Utils.smart_escape(api_url_builder.call(cloudinary, uri).flatten.join('/'))
|
65
65
|
timeout = options[:timeout] || Cloudinary.config.timeout || 60
|
66
66
|
proxy = options[:api_proxy] || Cloudinary.config.api_proxy
|
67
67
|
|
68
68
|
headers = { "User-Agent" => Cloudinary::USER_AGENT }
|
69
|
+
headers.merge!("Authorization" => get_authorization_header_value(auth))
|
69
70
|
|
70
71
|
if options[:content_type] == :json
|
71
72
|
payload = params.to_json
|
@@ -74,6 +75,21 @@ module Cloudinary::BaseApi
|
|
74
75
|
payload = params.reject { |_, v| v.nil? || v == "" }
|
75
76
|
end
|
76
77
|
|
77
|
-
call_json_api(method, api_url, payload, timeout, headers, proxy
|
78
|
+
call_json_api(method, api_url, payload, timeout, headers, proxy)
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_authorization_header_value(auth)
|
82
|
+
if auth[:oauth_token].present?
|
83
|
+
"Bearer #{auth[:oauth_token]}"
|
84
|
+
else
|
85
|
+
"Basic #{Base64.urlsafe_encode64("#{auth[:key]}:#{auth[:secret]}")}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_authorization(api_key, api_secret, oauth_token)
|
90
|
+
return if oauth_token.present?
|
91
|
+
|
92
|
+
raise("Must supply api_key") if api_key.nil?
|
93
|
+
raise("Must supply api_secret") if api_secret.nil?
|
78
94
|
end
|
79
95
|
end
|
data/lib/cloudinary/uploader.rb
CHANGED
@@ -21,6 +21,7 @@ class Cloudinary::Uploader
|
|
21
21
|
:access_control => Cloudinary::Utils.json_array_param(options[:access_control]),
|
22
22
|
:access_mode => options[:access_mode],
|
23
23
|
:allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
|
24
|
+
:asset_folder => options[:asset_folder],
|
24
25
|
:async => Cloudinary::Utils.as_safe_bool(options[:async]),
|
25
26
|
:auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f,
|
26
27
|
:background_removal => options[:background_removal],
|
@@ -33,6 +34,7 @@ class Cloudinary::Uploader
|
|
33
34
|
:custom_coordinates => Cloudinary::Utils.encode_double_array(options[:custom_coordinates]),
|
34
35
|
:detection => options[:detection],
|
35
36
|
:discard_original_filename => Cloudinary::Utils.as_safe_bool(options[:discard_original_filename]),
|
37
|
+
:display_name => options[:display_name],
|
36
38
|
:eager => Cloudinary::Utils.build_eager(options[:eager]),
|
37
39
|
:eager_async => Cloudinary::Utils.as_safe_bool(options[:eager_async]),
|
38
40
|
:eager_notification_url => options[:eager_notification_url],
|
@@ -53,6 +55,7 @@ class Cloudinary::Uploader
|
|
53
55
|
:phash => Cloudinary::Utils.as_safe_bool(options[:phash]),
|
54
56
|
:proxy => options[:proxy],
|
55
57
|
:public_id => options[:public_id],
|
58
|
+
:public_id_prefix => options[:public_id_prefix],
|
56
59
|
:quality_analysis => Cloudinary::Utils.as_safe_bool(options[:quality_analysis]),
|
57
60
|
:quality_override => options[:quality_override],
|
58
61
|
:raw_convert => options[:raw_convert],
|
@@ -66,6 +69,7 @@ class Cloudinary::Uploader
|
|
66
69
|
:unique_filename => Cloudinary::Utils.as_safe_bool(options[:unique_filename]),
|
67
70
|
:upload_preset => options[:upload_preset],
|
68
71
|
:use_filename => Cloudinary::Utils.as_safe_bool(options[:use_filename]),
|
72
|
+
:use_filename_as_display_name => Cloudinary::Utils.as_safe_bool(options[:use_filename_as_display_name]),
|
69
73
|
:accessibility_analysis => Cloudinary::Utils.as_safe_bool(options[:accessibility_analysis]),
|
70
74
|
:metadata => Cloudinary::Utils.encode_context(options[:metadata])
|
71
75
|
}
|
@@ -363,11 +367,19 @@ class Cloudinary::Uploader
|
|
363
367
|
options = options.clone
|
364
368
|
return_error = options.delete(:return_error)
|
365
369
|
use_cache = options[:use_cache] || Cloudinary.config.use_cache
|
366
|
-
|
367
370
|
params, non_signable = yield
|
368
371
|
non_signable ||= []
|
369
372
|
|
370
|
-
|
373
|
+
headers = { "User-Agent" => Cloudinary::USER_AGENT }
|
374
|
+
headers['Content-Range'] = options[:content_range] if options[:content_range]
|
375
|
+
headers['X-Unique-Upload-Id'] = options[:unique_upload_id] if options[:unique_upload_id]
|
376
|
+
headers.merge!(options[:extra_headers]) if options[:extra_headers]
|
377
|
+
|
378
|
+
oauth_token = options[:oauth_token] || Cloudinary.config.oauth_token
|
379
|
+
|
380
|
+
if oauth_token
|
381
|
+
headers["Authorization"] = "Bearer #{oauth_token}"
|
382
|
+
elsif !options[:unsigned]
|
371
383
|
api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
|
372
384
|
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
|
373
385
|
signature_algorithm = options[:signature_algorithm]
|
@@ -379,11 +391,7 @@ class Cloudinary::Uploader
|
|
379
391
|
|
380
392
|
result = nil
|
381
393
|
|
382
|
-
api_url
|
383
|
-
headers = { "User-Agent" => Cloudinary::USER_AGENT }
|
384
|
-
headers['Content-Range'] = options[:content_range] if options[:content_range]
|
385
|
-
headers['X-Unique-Upload-Id'] = options[:unique_upload_id] if options[:unique_upload_id]
|
386
|
-
headers.merge!(options[:extra_headers]) if options[:extra_headers]
|
394
|
+
api_url = Cloudinary::Utils.cloudinary_api_url(action, options)
|
387
395
|
RestClient::Request.execute(:method => :post, :url => api_url, :payload => params.reject { |k, v| v.nil? || v=="" }, :timeout => timeout, :headers => headers, :proxy => proxy) do
|
388
396
|
|response, request, tmpresult|
|
389
397
|
raise CloudinaryException, "Server returned unexpected status code - #{response.code} - #{response.body}" unless [200, 400, 401, 403, 404, 500].include?(response.code)
|
data/lib/cloudinary/utils.rb
CHANGED
@@ -352,18 +352,30 @@ class Cloudinary::Utils
|
|
352
352
|
# @return [string] layer transformation string
|
353
353
|
# @private
|
354
354
|
def self.process_layer(layer)
|
355
|
+
if layer.is_a? String and layer.start_with?("fetch:")
|
356
|
+
layer = {:url => layer[6..-1]} # omit "fetch:" prefix
|
357
|
+
end
|
355
358
|
if layer.is_a? Hash
|
356
359
|
layer = symbolize_keys layer
|
357
360
|
public_id = layer[:public_id]
|
358
361
|
format = layer[:format]
|
362
|
+
fetch = layer[:url]
|
359
363
|
resource_type = layer[:resource_type] || "image"
|
360
|
-
type = layer[:type]
|
364
|
+
type = layer[:type]
|
361
365
|
text = layer[:text]
|
362
366
|
text_style = nil
|
363
367
|
components = []
|
364
368
|
|
369
|
+
if type.nil?
|
370
|
+
if fetch.nil?
|
371
|
+
type = "upload"
|
372
|
+
else
|
373
|
+
type = "fetch"
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
365
377
|
if public_id.present?
|
366
|
-
if type == "fetch"
|
378
|
+
if type == "fetch" and public_id.match(%r(^https?:/)i)
|
367
379
|
public_id = Base64.urlsafe_encode64(public_id)
|
368
380
|
else
|
369
381
|
public_id = public_id.gsub("/", ":")
|
@@ -371,14 +383,15 @@ class Cloudinary::Utils
|
|
371
383
|
end
|
372
384
|
end
|
373
385
|
|
374
|
-
if
|
375
|
-
|
386
|
+
if fetch.present? && fetch.match(%r(^https?:/)i)
|
387
|
+
fetch = Base64.urlsafe_encode64(fetch)
|
388
|
+
elsif text.blank? && resource_type != "text"
|
389
|
+
if public_id.blank? && type != "fetch"
|
376
390
|
raise(CloudinaryException, "Must supply public_id for resource_type layer_parameter")
|
377
391
|
end
|
378
392
|
if resource_type == "subtitles"
|
379
393
|
text_style = text_style(layer)
|
380
394
|
end
|
381
|
-
|
382
395
|
else
|
383
396
|
resource_type = "text"
|
384
397
|
type = nil
|
@@ -404,6 +417,7 @@ class Cloudinary::Utils
|
|
404
417
|
components.push(type) if type != "upload"
|
405
418
|
components.push(text_style)
|
406
419
|
components.push(public_id)
|
420
|
+
components.push(fetch)
|
407
421
|
components.push(text)
|
408
422
|
layer = components.reject(&:blank?).join(":")
|
409
423
|
end
|
@@ -1089,7 +1103,7 @@ class Cloudinary::Utils
|
|
1089
1103
|
Cloudinary::AuthToken.generate options
|
1090
1104
|
|
1091
1105
|
end
|
1092
|
-
|
1106
|
+
|
1093
1107
|
private
|
1094
1108
|
|
1095
1109
|
|
@@ -1106,24 +1120,24 @@ class Cloudinary::Utils
|
|
1106
1120
|
source
|
1107
1121
|
end
|
1108
1122
|
private_class_method :fully_unescape
|
1109
|
-
|
1123
|
+
|
1110
1124
|
def self.hash_query_params(hash)
|
1111
1125
|
if hash.respond_to?("to_query")
|
1112
1126
|
hash.to_query
|
1113
1127
|
else
|
1114
|
-
flat_hash_to_query_params(hash)
|
1128
|
+
flat_hash_to_query_params(hash)
|
1115
1129
|
end
|
1116
1130
|
end
|
1117
1131
|
|
1118
1132
|
def self.flat_hash_to_query_params(hash)
|
1119
|
-
hash.collect do |key, value|
|
1133
|
+
hash.collect do |key, value|
|
1120
1134
|
if value.is_a?(Array)
|
1121
1135
|
value.map{|v| "#{CGI.escape(key.to_s)}[]=#{CGI.escape(v.to_s)}"}.join("&")
|
1122
|
-
else
|
1136
|
+
else
|
1123
1137
|
"#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
|
1124
|
-
end
|
1138
|
+
end
|
1125
1139
|
end.compact.sort!.join('&')
|
1126
|
-
end
|
1140
|
+
end
|
1127
1141
|
|
1128
1142
|
def self.number_pattern
|
1129
1143
|
"([0-9]*)\\.([0-9]+)|([0-9]+)"
|
data/lib/cloudinary/version.rb
CHANGED
@@ -802,7 +802,7 @@ var slice = [].slice,
|
|
802
802
|
function TextLayer(options) {
|
803
803
|
var keys;
|
804
804
|
TextLayer.__super__.constructor.call(this, options);
|
805
|
-
keys = ["resourceType", "resourceType", "fontFamily", "fontSize", "fontWeight", "fontStyle", "textDecoration", "textAlign", "stroke", "letterSpacing", "lineSpacing", "fontHinting", "fontAntialiasing", "text"];
|
805
|
+
keys = ["resourceType", "resourceType", "fontFamily", "fontSize", "fontWeight", "fontStyle", "textDecoration", "textAlign", "stroke", "letterSpacing", "lineSpacing", "fontHinting", "fontAntialiasing", "text", "textStyle"];
|
806
806
|
if (options != null) {
|
807
807
|
keys.forEach((function(_this) {
|
808
808
|
return function(key) {
|
@@ -886,6 +886,11 @@ var slice = [].slice,
|
|
886
886
|
return this;
|
887
887
|
};
|
888
888
|
|
889
|
+
TextLayer.prototype.textStyle = function(textStyle) {
|
890
|
+
this.options.textStyle = textStyle;
|
891
|
+
return this;
|
892
|
+
};
|
893
|
+
|
889
894
|
|
890
895
|
/**
|
891
896
|
* generate the string representation of the layer
|
@@ -921,6 +926,10 @@ var slice = [].slice,
|
|
921
926
|
};
|
922
927
|
|
923
928
|
TextLayer.prototype.textStyleIdentifier = function() {
|
929
|
+
// Note: if a text-style argument is provided as a whole, it overrides everything else, no mix and match.
|
930
|
+
if (!Util.isEmpty(this.options.textStyle)) {
|
931
|
+
return this.options.textStyle;
|
932
|
+
}
|
924
933
|
var components;
|
925
934
|
components = [];
|
926
935
|
if (this.options.fontWeight !== "normal") {
|
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.22.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:
|
13
|
+
date: 2022-02-17 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws_cf_signer
|
@@ -276,7 +276,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
276
276
|
- !ruby/object:Gem::Version
|
277
277
|
version: '0'
|
278
278
|
requirements: []
|
279
|
-
|
279
|
+
rubyforge_project: cloudinary
|
280
|
+
rubygems_version: 2.7.6
|
280
281
|
signing_key:
|
281
282
|
specification_version: 4
|
282
283
|
summary: Client library for easily using the Cloudinary service
|