cloudinary 1.11.1 → 1.18.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/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/.github/pull_request_template.md +24 -0
- data/.gitignore +6 -1
- data/.travis.yml +15 -5
- data/CHANGELOG.md +149 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +20 -4
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +229 -0
- data/lib/cloudinary.rb +31 -22
- data/lib/cloudinary/api.rb +173 -5
- data/lib/cloudinary/auth_token.rb +6 -4
- data/lib/cloudinary/carrier_wave.rb +3 -1
- data/lib/cloudinary/carrier_wave/remote.rb +3 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/cloudinary_controller.rb +2 -4
- data/lib/cloudinary/helper.rb +30 -3
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/uploader.rb +35 -6
- data/lib/cloudinary/utils.rb +112 -40
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary/video_helper.rb +96 -22
- data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
- data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
- data/tools/allocate_test_cloud.sh +9 -0
- data/tools/get_test_cloud.sh +9 -0
- data/tools/update_version +29 -11
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +48 -14
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
- data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
- data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
- metadata +62 -67
- data/spec/access_control_spec.rb +0 -102
- data/spec/api_spec.rb +0 -567
- data/spec/archive_spec.rb +0 -129
- data/spec/auth_token_spec.rb +0 -77
- data/spec/cache_spec.rb +0 -109
- data/spec/cloudinary_helper_spec.rb +0 -325
- data/spec/cloudinary_spec.rb +0 -32
- data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
- data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
- data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
- data/spec/docx.docx +0 -0
- data/spec/favicon.ico +0 -0
- data/spec/image_spec.rb +0 -107
- data/spec/logo.png +0 -0
- data/spec/rake_spec.rb +0 -160
- data/spec/sample_asset_file.tsv +0 -4
- data/spec/search_spec.rb +0 -109
- data/spec/spec_helper.rb +0 -266
- data/spec/storage_spec.rb +0 -44
- data/spec/streaminig_profiles_api_spec.rb +0 -74
- data/spec/support/helpers/temp_file_helpers.rb +0 -22
- data/spec/support/shared_contexts/rake.rb +0 -19
- data/spec/uploader_spec.rb +0 -392
- data/spec/utils_methods_spec.rb +0 -54
- data/spec/utils_spec.rb +0 -970
- data/spec/video_tag_spec.rb +0 -253
- data/spec/video_url_spec.rb +0 -185
data/lib/cloudinary.rb
CHANGED
@@ -29,8 +29,8 @@ module Cloudinary
|
|
29
29
|
OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net"
|
30
30
|
SHARED_CDN = AKAMAI_SHARED_CDN
|
31
31
|
|
32
|
-
USER_AGENT = "CloudinaryRuby
|
33
|
-
@@user_platform = ""
|
32
|
+
USER_AGENT = "CloudinaryRuby/#{VERSION} (Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
|
33
|
+
@@user_platform = defined?(Rails.version) ? "Rails/#{Rails.version}" : ""
|
34
34
|
|
35
35
|
# Add platform information to the USER_AGENT header
|
36
36
|
# This is intended for platform information and not individual applications!
|
@@ -44,7 +44,7 @@ module Cloudinary
|
|
44
44
|
|
45
45
|
def self.USER_AGENT
|
46
46
|
if @@user_platform.empty?
|
47
|
-
|
47
|
+
USER_AGENT
|
48
48
|
else
|
49
49
|
"#{@@user_platform} #{USER_AGENT}"
|
50
50
|
end
|
@@ -64,19 +64,7 @@ module Cloudinary
|
|
64
64
|
first_time = @@config.nil?
|
65
65
|
@@config ||= OpenStruct.new((YAML.load(ERB.new(IO.read(config_dir.join("cloudinary.yml"))).result)[config_env] rescue {}))
|
66
66
|
|
67
|
-
|
68
|
-
if first_time && ENV["CLOUDINARY_CLOUD_NAME"]
|
69
|
-
set_config(
|
70
|
-
"cloud_name" => ENV["CLOUDINARY_CLOUD_NAME"],
|
71
|
-
"api_key" => ENV["CLOUDINARY_API_KEY"],
|
72
|
-
"api_secret" => ENV["CLOUDINARY_API_SECRET"],
|
73
|
-
"secure_distribution" => ENV["CLOUDINARY_SECURE_DISTRIBUTION"],
|
74
|
-
"private_cdn" => ENV["CLOUDINARY_PRIVATE_CDN"].to_s == 'true',
|
75
|
-
"secure" => ENV["CLOUDINARY_SECURE"].to_s == 'true'
|
76
|
-
)
|
77
|
-
elsif first_time && ENV["CLOUDINARY_URL"]
|
78
|
-
config_from_url(ENV["CLOUDINARY_URL"])
|
79
|
-
end
|
67
|
+
config_from_env if first_time
|
80
68
|
|
81
69
|
set_config(new_config) if new_config
|
82
70
|
yield(@@config) if block_given?
|
@@ -86,7 +74,12 @@ module Cloudinary
|
|
86
74
|
|
87
75
|
def self.config_from_url(url)
|
88
76
|
@@config ||= OpenStruct.new
|
89
|
-
|
77
|
+
return unless url && !url.empty?
|
78
|
+
uri = URI.parse(url)
|
79
|
+
if !uri.scheme || "cloudinary" != uri.scheme.downcase
|
80
|
+
raise(CloudinaryException,
|
81
|
+
"Invalid CLOUDINARY_URL scheme. Expecting to start with 'cloudinary://'")
|
82
|
+
end
|
90
83
|
set_config(
|
91
84
|
"cloud_name" => uri.host,
|
92
85
|
"api_key" => uri.user,
|
@@ -100,7 +93,7 @@ module Cloudinary
|
|
100
93
|
if isNestedKey? key
|
101
94
|
putNestedKey key, value
|
102
95
|
else
|
103
|
-
set_config(key =>
|
96
|
+
set_config(key => Utils.smart_unescape(value))
|
104
97
|
end
|
105
98
|
end
|
106
99
|
end
|
@@ -135,18 +128,34 @@ module Cloudinary
|
|
135
128
|
end
|
136
129
|
|
137
130
|
private
|
138
|
-
|
131
|
+
|
132
|
+
def self.config_from_env
|
133
|
+
# Heroku support
|
134
|
+
if ENV["CLOUDINARY_CLOUD_NAME"]
|
135
|
+
config_keys = ENV.keys.select! { |key| key.start_with? "CLOUDINARY_" }
|
136
|
+
config_keys -= ["CLOUDINARY_URL"] # ignore it when explicit options are passed
|
137
|
+
config_keys.each do |full_key|
|
138
|
+
conf_key = full_key["CLOUDINARY_".length..-1].downcase # convert "CLOUDINARY_CONFIG_NAME" to "config_name"
|
139
|
+
conf_val = ENV[full_key]
|
140
|
+
conf_val = conf_val == 'true' if %w[true false].include?(conf_val) # cast relevant boolean values
|
141
|
+
set_config(conf_key => conf_val)
|
142
|
+
end
|
143
|
+
elsif ENV["CLOUDINARY_URL"]
|
144
|
+
config_from_url(ENV["CLOUDINARY_URL"])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
139
148
|
def self.config_env
|
140
149
|
return ENV["CLOUDINARY_ENV"] if ENV["CLOUDINARY_ENV"]
|
141
150
|
return Rails.env if defined? Rails::env
|
142
151
|
nil
|
143
152
|
end
|
144
|
-
|
153
|
+
|
145
154
|
def self.config_dir
|
146
|
-
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
155
|
+
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
147
156
|
self.app_root.join("config")
|
148
157
|
end
|
149
|
-
|
158
|
+
|
150
159
|
def self.set_config(new_config)
|
151
160
|
new_config.each{|k,v| @@config.send(:"#{k}=", v) if !v.nil?}
|
152
161
|
end
|
data/lib/cloudinary/api.rb
CHANGED
@@ -78,8 +78,9 @@ class Cloudinary::Api
|
|
78
78
|
resource_type = options[:resource_type] || "image"
|
79
79
|
type = options[:type] || "upload"
|
80
80
|
uri = "resources/#{resource_type}/#{type}/#{public_id}"
|
81
|
-
call_api(:get, uri,
|
82
|
-
only(options,
|
81
|
+
call_api(:get, uri,
|
82
|
+
only(options,
|
83
|
+
:cinemagraph_analysis,
|
83
84
|
:colors,
|
84
85
|
:coordinates,
|
85
86
|
:exif,
|
@@ -88,7 +89,9 @@ class Cloudinary::Api
|
|
88
89
|
:max_results,
|
89
90
|
:pages,
|
90
91
|
:phash,
|
91
|
-
:quality_analysis
|
92
|
+
:quality_analysis,
|
93
|
+
:derived_next_cursor,
|
94
|
+
:accessibility_analysis
|
92
95
|
), options)
|
93
96
|
end
|
94
97
|
|
@@ -226,11 +229,21 @@ class Cloudinary::Api
|
|
226
229
|
end
|
227
230
|
|
228
231
|
def self.root_folders(options={})
|
229
|
-
|
232
|
+
params = only(options, :max_results, :next_cursor)
|
233
|
+
call_api(:get, "folders", params, options)
|
230
234
|
end
|
231
235
|
|
232
236
|
def self.subfolders(of_folder_path, options={})
|
233
|
-
|
237
|
+
params = only(options, :max_results, :next_cursor)
|
238
|
+
call_api(:get, "folders/#{of_folder_path}", params, options)
|
239
|
+
end
|
240
|
+
|
241
|
+
def self.delete_folder(path, options={})
|
242
|
+
call_api(:delete, "folders/#{path}", {}, options)
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.create_folder(folder_name, options={})
|
246
|
+
call_api(:post, "folders/#{folder_name}", {}, options)
|
234
247
|
end
|
235
248
|
|
236
249
|
def self.upload_mappings(options={})
|
@@ -335,6 +348,144 @@ class Cloudinary::Api
|
|
335
348
|
call_json_api('GET', json_url, {}, 60, {})
|
336
349
|
end
|
337
350
|
|
351
|
+
# Returns a list of all metadata field definitions.
|
352
|
+
#
|
353
|
+
# @see https://cloudinary.com/documentation/admin_api#get_metadata_fields Get metadata fields API reference
|
354
|
+
#
|
355
|
+
# @param [Hash] options Additional options
|
356
|
+
# @return [Cloudinary::Api::Response]
|
357
|
+
# @raise [Cloudinary::Api::Error]
|
358
|
+
def self.list_metadata_fields(options = {})
|
359
|
+
call_metadata_api(:get, [], {}, options)
|
360
|
+
end
|
361
|
+
|
362
|
+
# Gets a metadata field by external id.
|
363
|
+
#
|
364
|
+
# @see https://cloudinary.com/documentation/admin_api#get_a_metadata_field_by_external_id Get metadata field by external ID API reference
|
365
|
+
#
|
366
|
+
# @param [String] field_external_id The ID of the metadata field to retrieve
|
367
|
+
# @param [Hash] options Additional options
|
368
|
+
# @return [Cloudinary::Api::Response]
|
369
|
+
# @raise [Cloudinary::Api::Error]
|
370
|
+
def self.metadata_field_by_field_id(field_external_id, options = {})
|
371
|
+
uri = [field_external_id]
|
372
|
+
|
373
|
+
call_metadata_api(:get, uri, {}, options)
|
374
|
+
end
|
375
|
+
|
376
|
+
# Creates a new metadata field definition.
|
377
|
+
#
|
378
|
+
# @see https://cloudinary.com/documentation/admin_api#create_a_metadata_field Create metadata field API reference
|
379
|
+
#
|
380
|
+
# @param [Hash] field The field to add
|
381
|
+
# @param [Hash] options Additional options
|
382
|
+
# @return [Cloudinary::Api::Response]
|
383
|
+
# @raise [Cloudinary::Api::Error]
|
384
|
+
def self.add_metadata_field(field, options = {})
|
385
|
+
params = only(field, :type, :external_id, :label, :mandatory, :default_value, :validation, :datasource)
|
386
|
+
|
387
|
+
call_metadata_api(:post, [], params, options)
|
388
|
+
end
|
389
|
+
|
390
|
+
# Updates a metadata field by external id.
|
391
|
+
#
|
392
|
+
# Updates a metadata field definition (partially, no need to pass the entire object) passed as JSON data.
|
393
|
+
# See https://cloudinary.com/documentation/admin_api#generic_structure_of_a_metadata_field for the generic structure
|
394
|
+
# of a metadata field.
|
395
|
+
#
|
396
|
+
# @see https://cloudinary.com/documentation/admin_api#update_a_metadata_field_by_external_id Update metadata field API reference
|
397
|
+
#
|
398
|
+
# @param [String] field_external_id The id of the metadata field to update
|
399
|
+
# @param [Hash] field The field definition
|
400
|
+
# @param [Hash] options Additional options
|
401
|
+
# @return [Cloudinary::Api::Response]
|
402
|
+
# @raise [Cloudinary::Api::Error]
|
403
|
+
def self.update_metadata_field(field_external_id, field, options = {})
|
404
|
+
uri = [field_external_id]
|
405
|
+
params = only(field, :label, :mandatory, :default_value, :validation)
|
406
|
+
|
407
|
+
call_metadata_api(:put, uri, params, options)
|
408
|
+
end
|
409
|
+
|
410
|
+
# Deletes a metadata field definition.
|
411
|
+
#
|
412
|
+
# The field should no longer be considered a valid candidate for all other endpoints.
|
413
|
+
#
|
414
|
+
# @see https://cloudinary.com/documentation/admin_api#delete_a_metadata_field_by_external_id Delete metadata field API reference
|
415
|
+
#
|
416
|
+
# @param [String] field_external_id The external id of the field to delete
|
417
|
+
# @param [Hash] options Additional options
|
418
|
+
# @return [Cloudinary::Api::Response] A hash with a "message" key. "ok" value indicates a successful deletion
|
419
|
+
# @raise [Cloudinary::Api::Error]
|
420
|
+
def self.delete_metadata_field(field_external_id, options = {})
|
421
|
+
uri = [field_external_id]
|
422
|
+
|
423
|
+
call_metadata_api(:delete, uri, {}, options)
|
424
|
+
end
|
425
|
+
|
426
|
+
# Deletes entries in a metadata field datasource.
|
427
|
+
#
|
428
|
+
# Deletes (blocks) the datasource entries for a specified metadata field definition. Sets the state of the
|
429
|
+
# entries to inactive. This is a soft delete, the entries still exist under the hood and can be activated
|
430
|
+
# again with the restore datasource entries method.
|
431
|
+
#
|
432
|
+
# @see https://cloudinary.com/documentation/admin_api#delete_entries_in_a_metadata_field_datasource Delete entries in a metadata field datasource API reference
|
433
|
+
#
|
434
|
+
# @param [String] field_external_id The id of the field to update
|
435
|
+
# @param [Array] entries_external_id The ids of all the entries to delete from the datasource
|
436
|
+
# @param [Hash] options Additional options
|
437
|
+
# @return [Cloudinary::Api::Response] The remaining datasource entries
|
438
|
+
# @raise [Cloudinary::Api::Error]
|
439
|
+
def self.delete_datasource_entries(field_external_id, entries_external_id, options = {})
|
440
|
+
uri = [field_external_id, "datasource"]
|
441
|
+
params = {:external_ids => entries_external_id }
|
442
|
+
|
443
|
+
call_metadata_api(:delete, uri, params, options)
|
444
|
+
end
|
445
|
+
|
446
|
+
# Updates a metadata field datasource.
|
447
|
+
#
|
448
|
+
# Updates the datasource of a supported field type (currently only enum and set), passed as JSON data. The
|
449
|
+
# update is partial: datasource entries with an existing external_id will be updated and entries with new
|
450
|
+
# external_id’s (or without external_id’s) will be appended.
|
451
|
+
#
|
452
|
+
# @see https://cloudinary.com/documentation/admin_api#update_a_metadata_field_datasource Update a metadata field datasource API reference
|
453
|
+
#
|
454
|
+
# @param [String] field_external_id The external id of the field to update
|
455
|
+
# @param [Array] entries_external_id
|
456
|
+
# @param [Hash] options Additional options
|
457
|
+
# @return [Cloudinary::Api::Response]
|
458
|
+
# @raise [Cloudinary::Api::Error]
|
459
|
+
def self.update_metadata_field_datasource(field_external_id, entries_external_id, options = {})
|
460
|
+
uri = [field_external_id, "datasource"]
|
461
|
+
|
462
|
+
params = entries_external_id.each_with_object({:values => [] }) do |item, hash|
|
463
|
+
item = only(item, :external_id, :value)
|
464
|
+
hash[:values ] << item if item.present?
|
465
|
+
end
|
466
|
+
|
467
|
+
call_metadata_api(:put, uri, params, options)
|
468
|
+
end
|
469
|
+
|
470
|
+
# Restores entries in a metadata field datasource.
|
471
|
+
#
|
472
|
+
# Restores (unblocks) any previously deleted datasource entries for a specified metadata field definition.
|
473
|
+
# Sets the state of the entries to active.
|
474
|
+
#
|
475
|
+
# @see https://cloudinary.com/documentation/admin_api#restore_entries_in_a_metadata_field_datasource Restore entries in a metadata field datasource API reference
|
476
|
+
#
|
477
|
+
# @param [String] field_external_id The ID of the metadata field
|
478
|
+
# @param [Array] entries_external_ids An array of IDs of datasource entries to restore (unblock)
|
479
|
+
# @param [Hash] options Additional options
|
480
|
+
# @return [Cloudinary::Api::Response]
|
481
|
+
# @raise [Cloudinary::Api::Error]
|
482
|
+
def self.restore_metadata_field_datasource(field_external_id, entries_external_ids, options = {})
|
483
|
+
uri = [field_external_id, "datasource_restore"]
|
484
|
+
params = {:external_ids => entries_external_ids }
|
485
|
+
|
486
|
+
call_metadata_api(:post, uri, params, options)
|
487
|
+
end
|
488
|
+
|
338
489
|
protected
|
339
490
|
|
340
491
|
def self.call_api(method, uri, params, options)
|
@@ -343,6 +494,7 @@ class Cloudinary::Api
|
|
343
494
|
api_key = options[:api_key] || Cloudinary.config.api_key || raise("Must supply api_key")
|
344
495
|
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise("Must supply api_secret")
|
345
496
|
timeout = options[:timeout] || Cloudinary.config.timeout || 60
|
497
|
+
uri = Cloudinary::Utils.smart_escape(uri)
|
346
498
|
api_url = [cloudinary, "v1_1", cloud_name, uri].join("/")
|
347
499
|
# Add authentication
|
348
500
|
api_url.sub!(%r(^(https?://)), "\\1#{api_key}:#{api_secret}@")
|
@@ -382,6 +534,22 @@ class Cloudinary::Api
|
|
382
534
|
raise GeneralError.new("Error parsing server response (#{response.code}) - #{response.body}. Got - #{e}")
|
383
535
|
end
|
384
536
|
|
537
|
+
# Protected function that assists with performing an API call to the metadata_fields part of the Admin API.
|
538
|
+
#
|
539
|
+
# @protected
|
540
|
+
# @param [Symbol] method The HTTP method. Valid methods: get, post, put, delete
|
541
|
+
# @param [Array] uri REST endpoint of the API (without 'metadata_fields')
|
542
|
+
# @param [Hash] params Query/body parameters passed to the method
|
543
|
+
# @param [Hash] options Additional options. Can be an override of the configuration, headers, etc.
|
544
|
+
# @return [Cloudinary::Api::Response]
|
545
|
+
# @raise [Cloudinary::Api::Error]
|
546
|
+
def self.call_metadata_api(method, uri, params, options)
|
547
|
+
options[:content_type] = :json
|
548
|
+
uri = ["metadata_fields", uri].reject(&:empty?).join("/")
|
549
|
+
|
550
|
+
call_api(method, uri, params, options)
|
551
|
+
end
|
552
|
+
|
385
553
|
def self.only(hash, *keys)
|
386
554
|
result = {}
|
387
555
|
keys.each do |key|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
if RUBY_VERSION > "2"
|
3
5
|
require "ostruct"
|
@@ -10,6 +12,7 @@ module Cloudinary
|
|
10
12
|
module AuthToken
|
11
13
|
SEPARATOR = '~'
|
12
14
|
UNSAFE = /[ "#%&\'\/:;<=>?@\[\\\]^`{\|}~]/
|
15
|
+
EMPTY_TOKEN = {}.freeze
|
13
16
|
|
14
17
|
def self.generate(options = {})
|
15
18
|
key = options[:key]
|
@@ -42,12 +45,11 @@ module Cloudinary
|
|
42
45
|
"#{name}=#{token.join(SEPARATOR)}"
|
43
46
|
end
|
44
47
|
|
45
|
-
|
46
48
|
# Merge token2 to token1 returning a new
|
47
49
|
# Requires to support Ruby 1.9
|
48
50
|
def self.merge_auth_token(token1, token2)
|
49
|
-
token1 = token1 ||
|
50
|
-
token2 = token2 ||
|
51
|
+
token1 = token1 || EMPTY_TOKEN
|
52
|
+
token2 = token2 || EMPTY_TOKEN
|
51
53
|
token1 = token1.respond_to?( :to_h) ? token1.to_h : token1
|
52
54
|
token2 = token2.respond_to?( :to_h) ? token2.to_h : token2
|
53
55
|
token1.merge(token2)
|
@@ -69,4 +71,4 @@ module Cloudinary
|
|
69
71
|
OpenSSL::HMAC.hexdigest(digest, bin_key, message)
|
70
72
|
end
|
71
73
|
end
|
72
|
-
end
|
74
|
+
end
|
@@ -9,8 +9,10 @@ module Cloudinary::CarrierWave
|
|
9
9
|
|
10
10
|
def self.included(base)
|
11
11
|
base.storage Cloudinary::CarrierWave::Storage
|
12
|
+
base.cache_storage = :file if base.cache_storage.blank?
|
12
13
|
base.extend ClassMethods
|
13
|
-
base.class_attribute :
|
14
|
+
base.class_attribute :metadata
|
15
|
+
base.class_attribute :storage_type, instance_reader: false
|
14
16
|
override_in_versions(base, :blank?, :full_public_id, :my_public_id, :all_versions_processors, :stored_version)
|
15
17
|
end
|
16
18
|
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Cloudinary::CarrierWave
|
2
2
|
def download!(uri, *args)
|
3
|
-
return super
|
3
|
+
return super unless self.cloudinary_should_handle_remote?
|
4
4
|
if respond_to?(:process_uri)
|
5
5
|
uri = process_uri(uri)
|
6
6
|
else # Backward compatibility with old CarrierWave
|
7
|
-
|
7
|
+
remote_url_unsafe_chars = /([^a-zA-Z0-9_.\-\/:?&=]+)/ # In addition allow query string characters: "?","&" and "="
|
8
|
+
uri = URI.parse(Cloudinary::Utils.smart_escape(Cloudinary::Utils.smart_unescape(uri), remote_url_unsafe_chars))
|
8
9
|
end
|
9
10
|
return if uri.to_s.blank?
|
10
11
|
self.original_filename = @cache_id = @filename = File.basename(uri.path).gsub(/[^a-zA-Z0-9\.\-\+_]/, '')
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
|
2
2
|
|
3
3
|
def store!(file)
|
4
|
-
return
|
4
|
+
return unless uploader.enable_processing
|
5
|
+
|
5
6
|
if uploader.is_main_uploader?
|
6
7
|
case file
|
7
8
|
when Cloudinary::CarrierWave::PreloadedCloudinaryFile
|
@@ -1,13 +1,11 @@
|
|
1
1
|
module Cloudinary::CloudinaryController
|
2
2
|
protected
|
3
|
-
|
3
|
+
|
4
4
|
def valid_cloudinary_response?
|
5
5
|
received_signature = request.query_parameters[:signature]
|
6
6
|
calculated_signature = Cloudinary::Utils.api_sign_request(
|
7
7
|
request.query_parameters.select{|key, value| [:public_id, :version].include?(key.to_sym)},
|
8
8
|
Cloudinary.config.api_secret)
|
9
9
|
return received_signature == calculated_signature
|
10
|
-
end
|
10
|
+
end
|
11
11
|
end
|
12
|
-
|
13
|
-
ActionController::Base.send :include, Cloudinary::CloudinaryController
|
data/lib/cloudinary/helper.rb
CHANGED
@@ -286,7 +286,7 @@ 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.
|
289
|
+
# Helper method that uses the deprecated ZIP download API.
|
290
290
|
# Replaced by cl_download_zip_url that uses the more advanced and robust archive generation and download API
|
291
291
|
# @deprecated
|
292
292
|
def cl_zip_download_url(tag, options = {})
|
@@ -296,7 +296,7 @@ module CloudinaryHelper
|
|
296
296
|
# @see {Cloudinary::Utils.download_archive_url}
|
297
297
|
def cl_download_archive_url(options = {})
|
298
298
|
Cloudinary::Utils.download_archive_url(options)
|
299
|
-
end
|
299
|
+
end
|
300
300
|
|
301
301
|
# @see {Cloudinary::Utils.download_zip_url}
|
302
302
|
def cl_download_zip_url(options = {})
|
@@ -318,7 +318,7 @@ module CloudinaryHelper
|
|
318
318
|
if Cloudinary.config.enhance_image_tag
|
319
319
|
alias_method :image_tag, :image_tag_with_cloudinary
|
320
320
|
alias_method :image_path, :image_path_with_cloudinary
|
321
|
-
end
|
321
|
+
end
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
@@ -419,3 +419,30 @@ rescue LoadError
|
|
419
419
|
# no sass support. Ignore.
|
420
420
|
end
|
421
421
|
|
422
|
+
begin
|
423
|
+
require 'sassc'
|
424
|
+
require 'sassc/script/functions'
|
425
|
+
module SassC::Script::Functions
|
426
|
+
# Helper method for generating cloudinary_url in scss files.
|
427
|
+
#
|
428
|
+
# As opposed to sass(deprecated), optional named arguments are not supported, use hash map instead.
|
429
|
+
#
|
430
|
+
# Example:
|
431
|
+
# Sass: cloudinary-url("sample", $quality: "auto", $fetch_format: "auto");
|
432
|
+
# becomes
|
433
|
+
# SassC: cloudinary-url("sample", ("quality": "auto", "fetch_format": "auto"));
|
434
|
+
#
|
435
|
+
# @param [::SassC::Script::Value::String] public_id The public ID of the resource
|
436
|
+
# @param [::SassC::Script::Value::Map] sass_options Additional options
|
437
|
+
#
|
438
|
+
# @return [::SassC::Script::Value::String]
|
439
|
+
def cloudinary_url(public_id, sass_options = {})
|
440
|
+
options = {}
|
441
|
+
sass_options.to_h.each { |k, v| options[k.value.to_sym] = v.value }
|
442
|
+
url = Cloudinary::Utils.cloudinary_url(public_id.value, {:type => :asset}.merge(options))
|
443
|
+
::SassC::Script::Value::String.new("url(#{url})")
|
444
|
+
end
|
445
|
+
end
|
446
|
+
rescue LoadError
|
447
|
+
# no sassc support. Ignore.
|
448
|
+
end
|