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.
@@ -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)}"
@@ -59,13 +59,14 @@ module Cloudinary::BaseApi
59
59
 
60
60
  private
61
61
 
62
- def call_cloudinary_api(method, uri, user, password, params, options, &api_url_builder)
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, user, password)
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
@@ -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
- unless options[:unsigned]
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 = Cloudinary::Utils.cloudinary_api_url(action, options)
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)
@@ -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] || "upload"
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" && public_id.match(%r(^https?:/)i)
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 text.blank? && resource_type != "text"
375
- if public_id.blank?
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]+)"
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.21.0"
3
+ VERSION = "1.22.0"
4
4
  end
@@ -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.21.0
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: 2021-08-23 00:00:00.000000000 Z
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
- rubygems_version: 3.1.2
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