cloudinary 1.11.1 → 1.12.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/.gitignore +6 -1
- data/.travis.yml +12 -6
- data/CHANGELOG.md +30 -0
- data/cloudinary.gemspec +2 -0
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +181 -0
- data/lib/cloudinary.rb +9 -4
- data/lib/cloudinary/api.rb +17 -4
- data/lib/cloudinary/auth_token.rb +6 -4
- data/lib/cloudinary/uploader.rb +4 -4
- data/lib/cloudinary/utils.rb +62 -29
- data/lib/cloudinary/version.rb +1 -1
- data/spec/active_storage/Gemfile +12 -0
- data/spec/active_storage/application_system_test_case.rb +5 -0
- data/spec/active_storage/database/create_users_migration.rb +9 -0
- data/spec/active_storage/database/setup.rb +7 -0
- data/spec/active_storage/dummy/Rakefile +5 -0
- data/spec/active_storage/dummy/app/assets/config/manifest.js +3 -0
- data/spec/active_storage/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/active_storage/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/active_storage/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/active_storage/dummy/app/helpers/application_helper.rb +4 -0
- data/spec/active_storage/dummy/app/jobs/application_job.rb +4 -0
- data/spec/active_storage/dummy/app/models/application_record.rb +5 -0
- data/spec/active_storage/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/active_storage/dummy/bin/bundle +5 -0
- data/spec/active_storage/dummy/bin/rails +6 -0
- data/spec/active_storage/dummy/bin/rake +6 -0
- data/spec/active_storage/dummy/bin/yarn +11 -0
- data/spec/active_storage/dummy/config.ru +7 -0
- data/spec/active_storage/dummy/config/application.rb +22 -0
- data/spec/active_storage/dummy/config/boot.rb +7 -0
- data/spec/active_storage/dummy/config/database.yml +25 -0
- data/spec/active_storage/dummy/config/environment.rb +7 -0
- data/spec/active_storage/dummy/config/environments/development.rb +52 -0
- data/spec/active_storage/dummy/config/environments/production.rb +83 -0
- data/spec/active_storage/dummy/config/environments/test.rb +38 -0
- data/spec/active_storage/dummy/config/initializers/application_controller_renderer.rb +7 -0
- data/spec/active_storage/dummy/config/initializers/assets.rb +16 -0
- data/spec/active_storage/dummy/config/initializers/backtrace_silencers.rb +8 -0
- data/spec/active_storage/dummy/config/initializers/cookies_serializer.rb +7 -0
- data/spec/active_storage/dummy/config/initializers/filter_parameter_logging.rb +6 -0
- data/spec/active_storage/dummy/config/initializers/inflections.rb +17 -0
- data/spec/active_storage/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/active_storage/dummy/config/initializers/wrap_parameters.rb +16 -0
- data/spec/active_storage/dummy/config/routes.rb +4 -0
- data/spec/active_storage/dummy/config/secrets.yml +32 -0
- data/spec/active_storage/dummy/config/spring.rb +8 -0
- data/spec/active_storage/dummy/config/storage.yml +3 -0
- data/spec/active_storage/dummy/config/webpacker.yml +72 -0
- data/spec/active_storage/dummy/package.json +5 -0
- data/spec/active_storage/dummy/public/404.html +67 -0
- data/spec/active_storage/dummy/public/422.html +67 -0
- data/spec/active_storage/dummy/public/500.html +66 -0
- data/spec/active_storage/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/active_storage/dummy/public/apple-touch-icon.png +0 -0
- data/spec/active_storage/dummy/public/favicon.ico +0 -0
- data/spec/active_storage/fixtures/files/colors.bmp +0 -0
- data/spec/active_storage/fixtures/files/empty_file.txt +0 -0
- data/spec/active_storage/fixtures/files/favicon.ico +0 -0
- data/spec/active_storage/fixtures/files/icon.psd +0 -0
- data/spec/active_storage/fixtures/files/icon.svg +13 -0
- data/spec/active_storage/fixtures/files/image.gif +0 -0
- data/spec/active_storage/fixtures/files/racecar.jpg +0 -0
- data/spec/active_storage/fixtures/files/racecar.tif +0 -0
- data/spec/active_storage/fixtures/files/racecar_rotated.jpg +0 -0
- data/spec/active_storage/fixtures/files/report.pdf +0 -0
- data/spec/active_storage/fixtures/files/rotated_video.mp4 +0 -0
- data/spec/active_storage/fixtures/files/video.mp4 +0 -0
- data/spec/active_storage/fixtures/files/video_with_rectangular_samples.mp4 +0 -0
- data/spec/active_storage/fixtures/files/video_with_undefined_display_aspect_ratio.mp4 +0 -0
- data/spec/active_storage/fixtures/files/video_without_video_stream.mp4 +0 -0
- data/spec/active_storage/service/cloudinary_service_spec.rb +92 -0
- data/spec/active_storage/service/configurations.yml +4 -0
- data/spec/active_storage/test_helper.rb +43 -0
- data/spec/api_spec.rb +68 -12
- data/spec/archive_spec.rb +17 -1
- data/spec/cloudinary_helper_spec.rb +2 -0
- data/spec/cloudinary_spec.rb +30 -6
- data/spec/movie.mp4 +0 -0
- data/spec/spec_helper.rb +9 -2
- data/spec/uploader_spec.rb +20 -3
- data/spec/utils_methods_spec.rb +29 -2
- data/spec/utils_spec.rb +93 -11
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +31 -1
- 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 +161 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f3837b9826e6f31a35e478b9d8bbf81027cee43ece65f7df161b748fd5c21dd9
|
|
4
|
+
data.tar.gz: 3b47da18531bbfe2252f6cfe4a071bc5972c286c2f5777758d1b1a7e1a30b07e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 34d0a6214325094a27683345da51e605b7ba6f6ba5761d4c64478dea618dbf3d4ce14a255bf69d513704d72dca6ef5a27ee4bc6e5e81d66e5548341f9e7c2e8c
|
|
7
|
+
data.tar.gz: 383bbafb8b06b9bda3fdedbde2f6b7248bcee0bacd5576e98b8e9b79d9ff45cd7d1025056fe1edde412fbf4a04855ba4ea3af197c260374827026f7a0b883f55
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
matrix:
|
|
4
|
+
include:
|
|
5
|
+
- name: "Ruby 1.9"
|
|
6
|
+
dist: precise
|
|
7
|
+
rvm: 1.9.3
|
|
8
|
+
before_install:
|
|
9
|
+
- gem install bundler -v 1.17.3
|
|
10
|
+
- name: "Ruby 2.5.3"
|
|
11
|
+
dist: xenial
|
|
12
|
+
rvm: ruby-2.5.3
|
|
13
|
+
before_install:
|
|
14
|
+
- gem install bundler
|
|
9
15
|
script: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
1.12.0 / 2019-10-02
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
New functionality and features
|
|
5
|
+
------------------------------
|
|
6
|
+
|
|
7
|
+
* Add Cloudinary service for ActiveStorage
|
|
8
|
+
* Add `create_folder` Admin API method
|
|
9
|
+
* Add `delete_folder` Admin API method
|
|
10
|
+
* Add `cinemagraph_analysis` to `upload`, `explicit` and `resource` API methods
|
|
11
|
+
* Add `font_antialiasing` and `font_hinting` text style parameters
|
|
12
|
+
* Add `derived_next_cursor` parameter to `resource` Admin API
|
|
13
|
+
* Add `next_cursor` and `max_results` for `root_folders` and `subfolders` Admin API functions
|
|
14
|
+
* Add `jpeg` to `IMAGE_FORMATS`
|
|
15
|
+
* Add `pow` transformation operator
|
|
16
|
+
* Add `force_version` to `cloudinary_url`
|
|
17
|
+
* Support per corner values for the `radius` transformation parameter
|
|
18
|
+
* Support using multiple resource types when generating archives
|
|
19
|
+
* Support Google Storage fetch URL
|
|
20
|
+
|
|
21
|
+
Other Changes
|
|
22
|
+
-------------
|
|
23
|
+
* Ensure `CLOUDINARY_URL` starts with `cloudinary://`
|
|
24
|
+
* Reduce memory usage in `Cloudinary::Utils.cloudinary_url`
|
|
25
|
+
* Encode URL in Admin API methods
|
|
26
|
+
* Fix base64 data validation
|
|
27
|
+
* Return `video` as the `resource_type` for audio files
|
|
28
|
+
* Add language and platform version for ruby/rails user agent
|
|
29
|
+
* Fix TravisCI configuration for ruby 1.9
|
|
30
|
+
|
|
1
31
|
|
|
2
32
|
1.11.1 / 2018-12-22
|
|
3
33
|
===================
|
data/cloudinary.gemspec
CHANGED
|
@@ -26,7 +26,9 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
s.add_development_dependency "actionpack"
|
|
27
27
|
s.add_development_dependency "nokogiri"
|
|
28
28
|
s.add_development_dependency "rake"
|
|
29
|
+
s.add_development_dependency "sqlite3"
|
|
29
30
|
s.add_development_dependency "rspec", '>=3.5'
|
|
31
|
+
s.add_development_dependency "rails", "~>5.2" if RUBY_VERSION >= "2.2.2"
|
|
30
32
|
s.add_development_dependency "rspec-rails"
|
|
31
33
|
s.add_development_dependency "rubyzip", "<=1.2.0" # support testing Ruby 1.9
|
|
32
34
|
s.add_development_dependency "simplecov"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Allow Blob attributes to be passed down to the service
|
|
2
|
+
# attributes includes
|
|
3
|
+
# - key - the string the BlobKey represents
|
|
4
|
+
# - content_type
|
|
5
|
+
# - filename
|
|
6
|
+
module ActiveStorage
|
|
7
|
+
class BlobKey < String
|
|
8
|
+
attr_reader :attributes
|
|
9
|
+
def initialize(attributes)
|
|
10
|
+
if attributes.is_a? Hash
|
|
11
|
+
attributes.symbolize_keys!
|
|
12
|
+
super(attributes[:key])
|
|
13
|
+
@attributes = attributes
|
|
14
|
+
else
|
|
15
|
+
super(attributes)
|
|
16
|
+
@attributes = {key: attributes} if attributes
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
require 'active_storage/blob_key'
|
|
2
|
+
require 'cloudinary/helper'
|
|
3
|
+
|
|
4
|
+
unless ActiveStorage::Blob.method_defined? :original_key
|
|
5
|
+
class ActiveStorage::Blob
|
|
6
|
+
alias_method :original_key, :key
|
|
7
|
+
|
|
8
|
+
def key
|
|
9
|
+
original_key
|
|
10
|
+
ActiveStorage::BlobKey.new(@attributes.as_json)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module ActiveStorage
|
|
16
|
+
class Service::CloudinaryService < Service
|
|
17
|
+
module Headers
|
|
18
|
+
CONTENT_TYPE = "Content-Type".freeze
|
|
19
|
+
CONTENT_MD5 = "Content-MD5".freeze
|
|
20
|
+
end
|
|
21
|
+
attr_reader :upload_options
|
|
22
|
+
|
|
23
|
+
def initialize(**options)
|
|
24
|
+
@options = options
|
|
25
|
+
@helper = ActionView::Base.new
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def upload(key, io, filename: nil, checksum: nil, **options)
|
|
29
|
+
instrument :upload, key: key, checksum: checksum do
|
|
30
|
+
begin
|
|
31
|
+
extra_headers = checksum.nil? ? {} : {Headers::CONTENT_MD5 => checksum}
|
|
32
|
+
options = @options.merge(options)
|
|
33
|
+
Cloudinary::Uploader.upload(
|
|
34
|
+
io,
|
|
35
|
+
public_id: public_id(key),
|
|
36
|
+
resource_type: resource_type(io, key),
|
|
37
|
+
context: {active_storage_key: key, checksum: checksum},
|
|
38
|
+
extra_headers: extra_headers,
|
|
39
|
+
**options
|
|
40
|
+
)
|
|
41
|
+
rescue CloudinaryException => e
|
|
42
|
+
raise ActiveStorage::IntegrityError, e.message, e.backtrace
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def url(key, filename: nil, content_type: '', **options)
|
|
48
|
+
instrument :url, key: key do |payload|
|
|
49
|
+
url = Cloudinary::Utils.cloudinary_url(
|
|
50
|
+
public_id(key),
|
|
51
|
+
resource_type: resource_type(nil, key),
|
|
52
|
+
format: ext_for_content_type(content_type),
|
|
53
|
+
**@options.merge(options.symbolize_keys)
|
|
54
|
+
)
|
|
55
|
+
payload[:url] = url
|
|
56
|
+
|
|
57
|
+
url
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def url_for_direct_upload(key, **options)
|
|
62
|
+
instrument :url, key: key do |payload|
|
|
63
|
+
options = {:resource_type => resource_type(nil, key)}.merge(@options.merge(options.symbolize_keys))
|
|
64
|
+
options[:public_id] = public_id(key)
|
|
65
|
+
options[:context] = {active_storage_key: key}
|
|
66
|
+
options.delete(:file)
|
|
67
|
+
payload[:url] = api_uri("upload", options)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def headers_for_direct_upload(key, content_type:, checksum:, **)
|
|
72
|
+
{
|
|
73
|
+
Headers::CONTENT_TYPE => content_type,
|
|
74
|
+
Headers::CONTENT_MD5 => checksum,
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def delete(key)
|
|
79
|
+
instrument :delete, key: key do
|
|
80
|
+
Cloudinary::Uploader.destroy public_id(key), resource_type: resource_type(nil, key)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def delete_prefixed(prefix)
|
|
85
|
+
# This method is used by ActiveStorage to delete derived resources after the main resource was deleted.
|
|
86
|
+
# In Cloudinary, the derived resources are deleted automatically when the main resource is deleted.
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def exist?(key)
|
|
90
|
+
instrument :exist, key: key do |payload|
|
|
91
|
+
begin
|
|
92
|
+
Cloudinary::Api.resource public_id(key), resource_type: resource_type(nil, key)
|
|
93
|
+
true
|
|
94
|
+
rescue Cloudinary::Api::NotFound => e
|
|
95
|
+
false
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def download(key, &block)
|
|
101
|
+
url = Cloudinary::Utils.unsigned_download_url(public_id(key), resource_type: resource_type(nil, key))
|
|
102
|
+
uri = URI(url)
|
|
103
|
+
if block_given?
|
|
104
|
+
instrument :streaming_download, key: key do
|
|
105
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
|
106
|
+
request = Net::HTTP::Get.new uri
|
|
107
|
+
http.request request do |response|
|
|
108
|
+
response.read_body &block
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
else
|
|
114
|
+
instrument :download, key: key do
|
|
115
|
+
res = Net::HTTP::get_response(uri)
|
|
116
|
+
res.body
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Return the partial content in the byte +range+ of the file at the +key+.
|
|
122
|
+
def download_chunk(key, range)
|
|
123
|
+
url = Cloudinary::Utils.unsigned_download_url(public_id(key), resource_type: resource_type(nil, key))
|
|
124
|
+
uri = URI(url)
|
|
125
|
+
instrument :download, key: key do
|
|
126
|
+
req = Net::HTTP::Get.new(uri)
|
|
127
|
+
range_end = case
|
|
128
|
+
when range.end.nil? then ''
|
|
129
|
+
when range.exclude_end? then range.end - 1
|
|
130
|
+
else range.end
|
|
131
|
+
end
|
|
132
|
+
req['range'] = "bytes=#{[range.begin, range_end].join('-')}"
|
|
133
|
+
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
|
|
134
|
+
http.request(req)
|
|
135
|
+
end
|
|
136
|
+
res.body.force_encoding(Encoding::BINARY)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
def api_uri(action, options)
|
|
144
|
+
base_url = Cloudinary::Utils.cloudinary_api_url(action, options)
|
|
145
|
+
upload_params = Cloudinary::Uploader.build_upload_params(options)
|
|
146
|
+
|
|
147
|
+
upload_params.reject! {|k, v| Cloudinary::Utils.safe_blank?(v)}
|
|
148
|
+
unless options[:unsigned]
|
|
149
|
+
upload_params = Cloudinary::Utils.sign_request(upload_params, options)
|
|
150
|
+
end
|
|
151
|
+
"#{base_url}?#{upload_params.to_query}"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def ext_for_content_type(content_type)
|
|
155
|
+
@formats ||= Hash.new do |h, key|
|
|
156
|
+
ext = Rack::Mime::MIME_TYPES.invert[key]
|
|
157
|
+
h[key] = ext.slice(1..-1) unless ext.nil?
|
|
158
|
+
end
|
|
159
|
+
@formats[content_type]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def public_id(key)
|
|
163
|
+
# TODO: Allow custom manipulation of key to obscure how we store in Cloudinary
|
|
164
|
+
key
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def resource_type(io, key = "")
|
|
168
|
+
return 'image' unless key.respond_to? :attributes
|
|
169
|
+
options = key.attributes
|
|
170
|
+
content_type = options[:content_type] || (io.nil? ? '' : Marcel::MimeType.for(io))
|
|
171
|
+
case content_type.split('/')[0]
|
|
172
|
+
when 'video'
|
|
173
|
+
'video'
|
|
174
|
+
when 'text'
|
|
175
|
+
'raw'
|
|
176
|
+
else
|
|
177
|
+
'image'
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
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
|
|
@@ -86,7 +86,12 @@ module Cloudinary
|
|
|
86
86
|
|
|
87
87
|
def self.config_from_url(url)
|
|
88
88
|
@@config ||= OpenStruct.new
|
|
89
|
-
|
|
89
|
+
return unless url && !url.empty?
|
|
90
|
+
uri = URI.parse(url)
|
|
91
|
+
if !uri.scheme || "cloudinary" != uri.scheme.downcase
|
|
92
|
+
raise(CloudinaryException,
|
|
93
|
+
"Invalid CLOUDINARY_URL scheme. Expecting to start with 'cloudinary://'")
|
|
94
|
+
end
|
|
90
95
|
set_config(
|
|
91
96
|
"cloud_name" => uri.host,
|
|
92
97
|
"api_key" => uri.user,
|
data/lib/cloudinary/api.rb
CHANGED
|
@@ -79,7 +79,8 @@ class Cloudinary::Api
|
|
|
79
79
|
type = options[:type] || "upload"
|
|
80
80
|
uri = "resources/#{resource_type}/#{type}/#{public_id}"
|
|
81
81
|
call_api(:get, uri,
|
|
82
|
-
only(options,
|
|
82
|
+
only(options,
|
|
83
|
+
:cinemagraph_analysis,
|
|
83
84
|
:colors,
|
|
84
85
|
:coordinates,
|
|
85
86
|
:exif,
|
|
@@ -88,7 +89,8 @@ class Cloudinary::Api
|
|
|
88
89
|
:max_results,
|
|
89
90
|
:pages,
|
|
90
91
|
:phash,
|
|
91
|
-
:quality_analysis
|
|
92
|
+
:quality_analysis,
|
|
93
|
+
:derived_next_cursor
|
|
92
94
|
), options)
|
|
93
95
|
end
|
|
94
96
|
|
|
@@ -226,11 +228,21 @@ class Cloudinary::Api
|
|
|
226
228
|
end
|
|
227
229
|
|
|
228
230
|
def self.root_folders(options={})
|
|
229
|
-
|
|
231
|
+
params = only(options, :max_results, :next_cursor)
|
|
232
|
+
call_api(:get, "folders", params, options)
|
|
230
233
|
end
|
|
231
234
|
|
|
232
235
|
def self.subfolders(of_folder_path, options={})
|
|
233
|
-
|
|
236
|
+
params = only(options, :max_results, :next_cursor)
|
|
237
|
+
call_api(:get, "folders/#{of_folder_path}", params, options)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def self.delete_folder(path, options={})
|
|
241
|
+
call_api(:delete, "folders/#{path}", {}, options)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def self.create_folder(folder_name, options={})
|
|
245
|
+
call_api(:post, "folders/#{folder_name}", {}, options)
|
|
234
246
|
end
|
|
235
247
|
|
|
236
248
|
def self.upload_mappings(options={})
|
|
@@ -343,6 +355,7 @@ class Cloudinary::Api
|
|
|
343
355
|
api_key = options[:api_key] || Cloudinary.config.api_key || raise("Must supply api_key")
|
|
344
356
|
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise("Must supply api_secret")
|
|
345
357
|
timeout = options[:timeout] || Cloudinary.config.timeout || 60
|
|
358
|
+
uri = Cloudinary::Utils.smart_escape(uri)
|
|
346
359
|
api_url = [cloudinary, "v1_1", cloud_name, uri].join("/")
|
|
347
360
|
# Add authentication
|
|
348
361
|
api_url.sub!(%r(^(https?://)), "\\1#{api_key}:#{api_secret}@")
|
|
@@ -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
|
data/lib/cloudinary/uploader.rb
CHANGED
|
@@ -5,8 +5,7 @@ require 'cloudinary/cache'
|
|
|
5
5
|
|
|
6
6
|
class Cloudinary::Uploader
|
|
7
7
|
|
|
8
|
-
REMOTE_URL_REGEX =
|
|
9
|
-
|
|
8
|
+
REMOTE_URL_REGEX = Cloudinary::Utils::REMOTE_URL_REGEX
|
|
10
9
|
# @deprecated use {Cloudinary::Utils.build_eager} instead
|
|
11
10
|
def self.build_eager(eager)
|
|
12
11
|
Cloudinary::Utils.build_eager(eager)
|
|
@@ -28,6 +27,7 @@ class Cloudinary::Uploader
|
|
|
28
27
|
:backup => Cloudinary::Utils.as_safe_bool(options[:backup]),
|
|
29
28
|
:callback => options[:callback],
|
|
30
29
|
:categorization => options[:categorization],
|
|
30
|
+
:cinemagraph_analysis => Cloudinary::Utils.as_safe_bool(options[:cinemagraph_analysis]),
|
|
31
31
|
:colors => Cloudinary::Utils.as_safe_bool(options[:colors]),
|
|
32
32
|
:context => Cloudinary::Utils.encode_context(options[:context]),
|
|
33
33
|
:custom_coordinates => Cloudinary::Utils.encode_double_array(options[:custom_coordinates]),
|
|
@@ -77,7 +77,7 @@ class Cloudinary::Uploader
|
|
|
77
77
|
params = build_upload_params(options)
|
|
78
78
|
if file.is_a?(Pathname)
|
|
79
79
|
params[:file] = File.open(file, "rb")
|
|
80
|
-
elsif file.respond_to?(:read) ||
|
|
80
|
+
elsif file.respond_to?(:read) || Cloudinary::Utils.is_remote?(file)
|
|
81
81
|
params[:file] = file
|
|
82
82
|
else
|
|
83
83
|
params[:file] = File.open(file, "rb")
|
|
@@ -95,7 +95,7 @@ class Cloudinary::Uploader
|
|
|
95
95
|
public_id = public_id_or_options
|
|
96
96
|
options = old_options
|
|
97
97
|
end
|
|
98
|
-
if
|
|
98
|
+
if Cloudinary::Utils.is_remote?(file)
|
|
99
99
|
return upload(file, options.merge(:public_id => public_id))
|
|
100
100
|
elsif file.is_a?(Pathname) || !file.respond_to?(:read)
|
|
101
101
|
filename = file
|