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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d6f32cb53d97a60e6d0ec304b1dbee2a80e7d1610c9007a9a0331bf80c3f882
|
4
|
+
data.tar.gz: 29863f2c682c9800cef486624985a8d4f8959b7da19ce0f53b4377bdc0312eaf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b7ac1b9edaeb3d8faad6dc1d75442f41cadef751400840c27ff176d370ca0739f68eda398c05efe56b7bfaa04376a0154f17840e15ac670fd4cc9d673527cb0
|
7
|
+
data.tar.gz: c3ba9122af7accec3abf2b9388b62be44e1e483a6f229e13ba40d1d283e9eef75c7179235b2674011e7d49d1fc12284c83b59f0dcfb0eed38e73195815123294
|
data/.travis.yml
CHANGED
@@ -1,22 +1,16 @@
|
|
1
|
-
dist:
|
1
|
+
dist: jammy
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
-
|
5
|
-
- 2.
|
6
|
-
- 3.0
|
4
|
+
- 3.1.4
|
5
|
+
- 3.2.2
|
6
|
+
- 3.3.0
|
7
7
|
|
8
8
|
matrix:
|
9
9
|
include:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
- gem install bundler -v 1.17.3
|
15
|
-
- name: "Ruby 2.5.9"
|
16
|
-
dist: xenial
|
17
|
-
rvm: ruby-2.5.9
|
18
|
-
before_install:
|
19
|
-
- gem install bundler -v 2.3.26
|
10
|
+
# There is an OpenSSL issue on Jammy with Ruby 3.0
|
11
|
+
- name: "Ruby: 3.0.6"
|
12
|
+
dist: focal
|
13
|
+
rvm: 3.0.6
|
20
14
|
|
21
15
|
before_script: >
|
22
16
|
export CLOUDINARY_URL=$(bash tools/get_test_cloud.sh);
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,54 @@
|
|
1
|
+
2.0.0 / 2024-04-08
|
2
|
+
==================
|
3
|
+
|
4
|
+
Breaking Changes
|
5
|
+
----------------
|
6
|
+
|
7
|
+
* Set minimal Ruby version to `3.0`
|
8
|
+
* For older Rubies use version `1.x` of this library
|
9
|
+
* Replace `rest-client` with `faraday`
|
10
|
+
* Set config `secure` to `true` by default
|
11
|
+
* All delivery URLs are set to be `https://` by default
|
12
|
+
* To disable - set `secure` to `false` in config/options
|
13
|
+
* Add support for URL Analytics
|
14
|
+
* Adds analytics signature query parameter to the delivery URLs
|
15
|
+
* To disable - set `analytics` to `false` in config/options
|
16
|
+
* Remove deprecated methods
|
17
|
+
* `Cloudinary::Utils.unsigned_download_url`
|
18
|
+
* use `Cloudinary::Utils.cloudinary_url` instead
|
19
|
+
* `Cloudinary::Utils.signed_download_url`
|
20
|
+
* use `Cloudinary::Utils.cloudinary_url` instead
|
21
|
+
* `Cloudinary::Utils.zip_download_url`
|
22
|
+
* use `Cloudinary::Utils.download_zip_url` instead
|
23
|
+
* `cl_zip_download_url`
|
24
|
+
* use `cl_download_zip_url` instead
|
25
|
+
* Remove deprecated constants
|
26
|
+
|
27
|
+
New functionality and features
|
28
|
+
------------------------------
|
29
|
+
|
30
|
+
* Add support for `analyze` API
|
31
|
+
* Support chunked uploads with CarrierWave
|
32
|
+
* Filter users by last login in `users` Provisioning API
|
33
|
+
|
34
|
+
1.29.0 / 2024-02-26
|
35
|
+
==================
|
36
|
+
|
37
|
+
New functionality and features
|
38
|
+
------------------------------
|
39
|
+
|
40
|
+
* Add support for `context` parameter in `url_for_direct_upload`
|
41
|
+
* Add support for `use_fetch_format` parameter in `cl_video_tag`
|
42
|
+
* Add support for `fields` parameter in Search and Admin APIs
|
43
|
+
* Add support for access keys management in Account Provisioning API
|
44
|
+
|
45
|
+
Other Changes
|
46
|
+
-------------
|
47
|
+
|
48
|
+
* Avoid early loading of `ActionView::Base`
|
49
|
+
* Fix `sqlite3` dependency version
|
50
|
+
* Add Rails 7.x to supported versions on `README.md`
|
51
|
+
|
1
52
|
1.28.0 / 2023-11-06
|
2
53
|
==================
|
3
54
|
|
data/README.md
CHANGED
@@ -40,11 +40,13 @@ the [Ruby on Rails SDK Guide](https://cloudinary.com/documentation/rails_integra
|
|
40
40
|
|
41
41
|
| SDK Version | Ruby 1.9.3 | Ruby 2.x | Ruby 3.x |
|
42
42
|
|-------------|------------|----------|----------|
|
43
|
-
| 1.x |
|
43
|
+
| 1.x | ✔ | ✔ | ✔ |
|
44
|
+
| 2.x | ✘ | ✘ | ✔ |
|
44
45
|
|
45
|
-
| SDK Version | Rails 5.x | Rails 6.x |
|
46
|
-
|
47
|
-
| 1.x |
|
46
|
+
| SDK Version | Rails 5.x | Rails 6.x | Rails 7.x |
|
47
|
+
|-------------|-----------|-----------|-----------|
|
48
|
+
| 1.x | ✔ | ✔ | ✔ |
|
49
|
+
| 2.x | ✘ | ✔ | ✔ |
|
48
50
|
|
49
51
|
## Installation
|
50
52
|
|
@@ -64,7 +66,7 @@ require 'cloudinary'
|
|
64
66
|
- [See full documentation](https://cloudinary.com/documentation/rails_image_manipulation).
|
65
67
|
|
66
68
|
```ruby
|
67
|
-
cl_image_tag("sample.jpg", :
|
69
|
+
cl_image_tag("sample.jpg", width: 100, height: 150, crop: "fill")
|
68
70
|
```
|
69
71
|
|
70
72
|
### Upload
|
data/cloudinary.gemspec
CHANGED
@@ -7,63 +7,33 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = Cloudinary::VERSION
|
8
8
|
s.authors = ["Nadav Soferman","Itai Lahan","Tal Lev-Ami"]
|
9
9
|
s.email = ["nadav.soferman@cloudinary.com","itai.lahan@cloudinary.com","tal.levami@cloudinary.com"]
|
10
|
-
s.homepage = "
|
10
|
+
s.homepage = "https://cloudinary.com"
|
11
11
|
s.license = "MIT"
|
12
12
|
|
13
13
|
s.summary = %q{Client library for easily using the Cloudinary service}
|
14
14
|
s.description = %q{Client library for easily using the Cloudinary service}
|
15
15
|
|
16
|
-
s.
|
17
|
-
|
18
|
-
s.files = `git ls-files`.split("\n").select { |f| !f.start_with?("test", "spec", "features", "samples") } + Dir.glob("vendor/assets/javascripts/*/*") + Dir.glob("vendor/assets/html/*")
|
16
|
+
s.files = `git ls-files`.split("\n").select { |f| !f.start_with?("test", "spec", "features", "samples") } +
|
17
|
+
Dir.glob("vendor/assets/javascripts/*/*") + Dir.glob("vendor/assets/html/*")
|
19
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
19
|
s.require_paths = ["lib"]
|
21
20
|
|
22
|
-
s.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
s.add_development_dependency "
|
35
|
-
s.add_development_dependency "
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
s.add_development_dependency "rake", "<= 12.2.1"
|
41
|
-
end
|
42
|
-
if RUBY_VERSION >= "2.7.0"
|
43
|
-
s.add_development_dependency "sqlite3"
|
44
|
-
else
|
45
|
-
s.add_development_dependency "sqlite3", "< 1.6.0"
|
46
|
-
end
|
47
|
-
|
48
|
-
s.add_development_dependency "rspec", '>=3.5'
|
49
|
-
s.add_development_dependency "rspec-retry"
|
50
|
-
|
51
|
-
if RUBY_VERSION >= "3.0.0"
|
52
|
-
s.add_development_dependency "rails", "~> 6.0.3"
|
53
|
-
elsif RUBY_VERSION >= "2.2.2"
|
54
|
-
s.add_development_dependency "rails", "~> 5.2"
|
55
|
-
end
|
56
|
-
|
57
|
-
s.add_development_dependency "railties", "<= 4.2.7" if RUBY_VERSION <= "1.9.3"
|
58
|
-
s.add_development_dependency "rspec-rails"
|
59
|
-
|
60
|
-
s.add_development_dependency "rubyzip"
|
61
|
-
|
62
|
-
if RUBY_VERSION <= "2.4.0"
|
63
|
-
s.add_development_dependency "simplecov", "<= 0.17.1" # support testing Ruby 1.9
|
64
|
-
s.add_development_dependency 'loofah', '~>2.19.1'
|
65
|
-
s.add_development_dependency "rails-html-sanitizer", "<1.5.0"
|
66
|
-
else
|
67
|
-
s.add_development_dependency "simplecov", "> 0.18.0"
|
68
|
-
end
|
21
|
+
s.required_ruby_version = '~> 3'
|
22
|
+
|
23
|
+
s.add_dependency "faraday", ">= 2.0.1", "< 3.0.0"
|
24
|
+
s.add_dependency "faraday-multipart", "~> 1.0", ">= 1.0.4"
|
25
|
+
|
26
|
+
s.add_development_dependency 'faraday-follow_redirects', '~> 0.3.0'
|
27
|
+
s.add_development_dependency "rails", ">= 6.1.7", "< 8.0.0"
|
28
|
+
s.add_development_dependency "rexml", ">= 3.2.5", "< 4.0.0"
|
29
|
+
s.add_development_dependency "actionpack", ">= 6.1.7", "< 8.0.0"
|
30
|
+
s.add_development_dependency "nokogiri", ">= 1.12.5", "< 2.0.0"
|
31
|
+
s.add_development_dependency "rake", ">= 13.0.6", "< 14.0.0"
|
32
|
+
s.add_development_dependency "sqlite3", ">= 1.4.2", "< 2.0.0"
|
33
|
+
s.add_development_dependency "rspec", ">= 3.11.2", "< 4.0.0"
|
34
|
+
s.add_development_dependency "rspec-retry", ">= 0.6.2", "< 1.0.0"
|
35
|
+
s.add_development_dependency "railties", ">= 6.0.4", "< 8.0.0"
|
36
|
+
s.add_development_dependency "rspec-rails", ">= 6.0.4", "< 7.0.0"
|
37
|
+
s.add_development_dependency "rubyzip", ">= 2.3.0", "< 3.0.0"
|
38
|
+
s.add_development_dependency "simplecov", ">= 0.21.2", "< 1.0.0"
|
69
39
|
end
|
@@ -39,10 +39,12 @@ module ActiveStorage
|
|
39
39
|
begin
|
40
40
|
extra_headers = checksum.nil? ? {} : {Headers::CONTENT_MD5 => checksum}
|
41
41
|
options = @options.merge(options)
|
42
|
+
resource_type = resource_type(io, key)
|
43
|
+
options[:format] = ext_for_file(key) if resource_type == "raw"
|
42
44
|
Cloudinary::Uploader.upload_large(
|
43
45
|
io,
|
44
46
|
public_id: public_id_internal(key),
|
45
|
-
resource_type: resource_type
|
47
|
+
resource_type: resource_type,
|
46
48
|
context: {active_storage_key: key, checksum: checksum},
|
47
49
|
extra_headers: extra_headers,
|
48
50
|
**options
|
@@ -81,7 +83,9 @@ module ActiveStorage
|
|
81
83
|
# through direct upload (client side js), filename is missing, and that leads to inconsistent/broken URLs.
|
82
84
|
# To avoid that, we explicitly pass file format in options.
|
83
85
|
options[:format] = ext_for_file(key) if options[:resource_type] == "raw"
|
86
|
+
context = options.delete(:context)
|
84
87
|
options[:context] = {active_storage_key: key}
|
88
|
+
options[:context].reverse_merge!(context) if context.respond_to?(:merge)
|
85
89
|
options.delete(:file)
|
86
90
|
payload[:url] = api_uri("upload", options)
|
87
91
|
end
|
@@ -147,7 +151,7 @@ module ActiveStorage
|
|
147
151
|
|
148
152
|
# Return the partial content in the byte +range+ of the file at the +key+.
|
149
153
|
def download_chunk(key, range)
|
150
|
-
url = Cloudinary::Utils.
|
154
|
+
url = Cloudinary::Utils.cloudinary_url(public_id(key), resource_type: resource_type(nil, key))
|
151
155
|
uri = URI(url)
|
152
156
|
instrument :download, key: key do
|
153
157
|
req = Net::HTTP::Get.new(uri)
|
@@ -13,10 +13,10 @@ class Cloudinary::AccountApi
|
|
13
13
|
# @param [Object] options additional options
|
14
14
|
def self.create_sub_account(name, cloud_name = nil, custom_attributes = {}, enabled = nil, base_account = nil, options = {})
|
15
15
|
params = {
|
16
|
-
name:
|
17
|
-
cloud_name:
|
18
|
-
custom_attributes:
|
19
|
-
enabled:
|
16
|
+
name: name,
|
17
|
+
cloud_name: cloud_name,
|
18
|
+
custom_attributes: custom_attributes,
|
19
|
+
enabled: enabled,
|
20
20
|
base_sub_account_id: base_account
|
21
21
|
}
|
22
22
|
|
@@ -35,10 +35,10 @@ class Cloudinary::AccountApi
|
|
35
35
|
# @param [Object] options additional options
|
36
36
|
def self.update_sub_account(sub_account_id, name = nil, cloud_name = nil, custom_attributes = nil, enabled = nil, options = {})
|
37
37
|
params = {
|
38
|
-
name:
|
39
|
-
cloud_name:
|
38
|
+
name: name,
|
39
|
+
cloud_name: cloud_name,
|
40
40
|
custom_attributes: custom_attributes,
|
41
|
-
enabled:
|
41
|
+
enabled: enabled
|
42
42
|
}
|
43
43
|
|
44
44
|
call_account_api(:put, ['sub_accounts', sub_account_id], params, options.merge(content_type: :json))
|
@@ -53,8 +53,8 @@ class Cloudinary::AccountApi
|
|
53
53
|
def self.sub_accounts(enabled = nil, ids = [], prefix = nil, options = {})
|
54
54
|
params = {
|
55
55
|
enabled: enabled,
|
56
|
-
ids:
|
57
|
-
prefix:
|
56
|
+
ids: ids,
|
57
|
+
prefix: prefix
|
58
58
|
}
|
59
59
|
|
60
60
|
call_account_api(:get, 'sub_accounts', params, options.merge(content_type: :json))
|
@@ -84,9 +84,9 @@ class Cloudinary::AccountApi
|
|
84
84
|
# @param [Object] options additional options
|
85
85
|
def self.create_user(name, email, role, sub_account_ids = [], options = {})
|
86
86
|
params = {
|
87
|
-
name:
|
88
|
-
email:
|
89
|
-
role:
|
87
|
+
name: name,
|
88
|
+
email: email,
|
89
|
+
role: role,
|
90
90
|
sub_account_ids: sub_account_ids
|
91
91
|
}
|
92
92
|
|
@@ -111,9 +111,9 @@ class Cloudinary::AccountApi
|
|
111
111
|
# @param [Object] options additional options
|
112
112
|
def self.update_user(user_id, name = nil, email = nil, role = nil, sub_account_ids = nil, options = {})
|
113
113
|
params = {
|
114
|
-
name:
|
115
|
-
email:
|
116
|
-
role:
|
114
|
+
name: name,
|
115
|
+
email: email,
|
116
|
+
role: role,
|
117
117
|
sub_account_ids: sub_account_ids
|
118
118
|
}
|
119
119
|
|
@@ -127,18 +127,30 @@ class Cloudinary::AccountApi
|
|
127
127
|
call_account_api(:get, ['users', user_id], {}, options.merge(content_type: :json))
|
128
128
|
end
|
129
129
|
|
130
|
-
#
|
131
|
-
#
|
132
|
-
# @param [
|
133
|
-
# @param [String]
|
134
|
-
# @param [String]
|
135
|
-
# @param [
|
130
|
+
# Get a list of the users according to filters.
|
131
|
+
#
|
132
|
+
# @param [Boolean] pending Optional. Limit results to pending users (true), users that are not pending (false), or all users (null)
|
133
|
+
# @param [Array<String>] user_ids Optional. List of user IDs. Up to 100
|
134
|
+
# @param [String] prefix Optional. Search by prefix of the user's name or email. Case-insensitive
|
135
|
+
# @param [String] sub_account_id Optional. Return only users who have access to the given sub-account
|
136
|
+
# @param [Object] options Generic advanced options map, see online documentation.
|
137
|
+
# @option options [Boolean] :last_login Optional. Return only users that last logged in in the specified range of dates (true),
|
138
|
+
# users that didn't last logged in in that range (false), or all users (null).
|
139
|
+
# @option options [Date] :from Optional. Last login start date.
|
140
|
+
# @option options [Date] :to Optional. Last login end date.
|
141
|
+
#
|
142
|
+
# @return [Cloudinary::Api::Response] the users' details.
|
143
|
+
#
|
144
|
+
# @raise [Cloudinary::Api::Error] If the request fails.
|
136
145
|
def self.users(pending = nil, user_ids = [], prefix = nil, sub_account_id = nil, options = {})
|
137
146
|
params = {
|
138
|
-
ids:
|
139
|
-
prefix:
|
147
|
+
ids: user_ids,
|
148
|
+
prefix: prefix,
|
140
149
|
sub_account_id: sub_account_id,
|
141
|
-
pending:
|
150
|
+
pending: pending,
|
151
|
+
last_login: options[:last_login].to_s,
|
152
|
+
from: Cloudinary::Utils.to_usage_api_date_format(options[:from]),
|
153
|
+
to: Cloudinary::Utils.to_usage_api_date_format(options[:to])
|
142
154
|
}
|
143
155
|
|
144
156
|
call_account_api(:get, 'users', params, options.merge(content_type: :json))
|
@@ -210,16 +222,55 @@ class Cloudinary::AccountApi
|
|
210
222
|
call_account_api(:get, ['user_groups', group_id, 'users'], {}, options.merge(content_type: :json))
|
211
223
|
end
|
212
224
|
|
225
|
+
# Lists access keys.
|
226
|
+
#
|
227
|
+
# @param [String] sub_account_id The ID of the sub-account.
|
228
|
+
# @param [Object] options Additional options.
|
229
|
+
def self.access_keys(sub_account_id, options = {})
|
230
|
+
params = Cloudinary::Api.only(options, :page_size, :page, :sort_by, :sort_order)
|
231
|
+
call_account_api(:get, ['sub_accounts', sub_account_id, 'access_keys'], params, options)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Generates access key.
|
235
|
+
#
|
236
|
+
# @param [String] sub_account_id The ID of the sub-account.
|
237
|
+
# @param [String] name The display name as shown in the management console.
|
238
|
+
# @param [Boolean] enabled Whether to create the access key as enabled (default is enabled).
|
239
|
+
# @param [Object] options Additional options.
|
240
|
+
def self.generate_access_key(sub_account_id, name = nil, enabled = nil, options = {})
|
241
|
+
params = {
|
242
|
+
name: name,
|
243
|
+
enabled: enabled,
|
244
|
+
}
|
245
|
+
call_account_api(:post, ['sub_accounts', sub_account_id, 'access_keys'], params, options.merge(content_type: :json))
|
246
|
+
end
|
247
|
+
|
248
|
+
# Updates access key.
|
249
|
+
#
|
250
|
+
# @param [String] sub_account_id The ID of the sub-account.
|
251
|
+
# @param [String] api_key The API key.
|
252
|
+
# @param [String] name The display name as shown in the management console.
|
253
|
+
# @param [Boolean] enabled Enable or disable the access key.
|
254
|
+
# @param [Object] options Additional options.
|
255
|
+
def self.update_access_key(sub_account_id, api_key, name = nil, enabled = nil, options = {})
|
256
|
+
params = {
|
257
|
+
name: name,
|
258
|
+
enabled: enabled,
|
259
|
+
}
|
260
|
+
call_account_api(:put, ['sub_accounts', sub_account_id, 'access_keys', api_key], params, options.merge(content_type: :json))
|
261
|
+
end
|
262
|
+
|
213
263
|
def self.call_account_api(method, uri, params, options)
|
214
264
|
account_id = options[:account_id] || Cloudinary.account_config.account_id || raise('Must supply account_id')
|
215
265
|
api_key = options[:provisioning_api_key] || Cloudinary.account_config.provisioning_api_key || raise('Must supply provisioning api_key')
|
216
266
|
api_secret = options[:provisioning_api_secret] || Cloudinary.account_config.provisioning_api_secret || raise('Must supply provisioning api_secret')
|
267
|
+
api_version = options[:api_version] || Cloudinary.config.api_version || 'v1_1'
|
217
268
|
|
218
269
|
params.reject! { |_, v| v.nil? }
|
219
270
|
auth = { :key => api_key, :secret => api_secret }
|
220
271
|
|
221
272
|
call_cloudinary_api(method, uri, auth, params, options) do |cloudinary, inner_uri|
|
222
|
-
[cloudinary,
|
273
|
+
[cloudinary, api_version, 'provisioning', 'accounts', account_id, inner_uri]
|
223
274
|
end
|
224
275
|
end
|
225
276
|
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cloudinary
|
4
|
+
module Analytics
|
5
|
+
extend self
|
6
|
+
|
7
|
+
QUERY_KEY = '_a'
|
8
|
+
ALGO_VERSION = 'B' # The version of the algorithm
|
9
|
+
SDK_CODE = 'C' # Cloudinary Ruby SDK
|
10
|
+
|
11
|
+
@product = 'A' # Official SDK. Set to 'B' for integrations.
|
12
|
+
@sdk_code = SDK_CODE
|
13
|
+
@sdk_version = Cloudinary::VERSION
|
14
|
+
@tech_version = "#{RUBY_VERSION[/\d+\.\d+/]}"
|
15
|
+
|
16
|
+
CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
17
|
+
BINARY_PAD_SIZE = 6
|
18
|
+
|
19
|
+
@char_codes = nil
|
20
|
+
@signature = nil
|
21
|
+
|
22
|
+
# Gets the SDK analytics signature query parameter.
|
23
|
+
#
|
24
|
+
# @return [String] The SDK signature query parameter.
|
25
|
+
def sdk_analytics_query_param
|
26
|
+
"#{QUERY_KEY}=#{self.sdk_analytics_signature}"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Gets the SDK signature by encoding the SDK version and tech version.
|
30
|
+
#
|
31
|
+
# @return [String] The SDK signature.
|
32
|
+
def sdk_analytics_signature
|
33
|
+
return @signature unless @signature.nil?
|
34
|
+
|
35
|
+
begin
|
36
|
+
@signature = ALGO_VERSION + @product + @sdk_code + encode_version(@sdk_version) + encode_version(@tech_version)
|
37
|
+
rescue RangeError
|
38
|
+
@signature = 'E'
|
39
|
+
end
|
40
|
+
|
41
|
+
@signature
|
42
|
+
end
|
43
|
+
|
44
|
+
# Sets the product code.
|
45
|
+
#
|
46
|
+
# Used for integrations.
|
47
|
+
#
|
48
|
+
# @param [String] product The product code to set. 'A' is for the official SDK. 'B' for integrations.
|
49
|
+
#
|
50
|
+
# @return [void]
|
51
|
+
#
|
52
|
+
# @internal
|
53
|
+
def product(product)
|
54
|
+
@product = product
|
55
|
+
end
|
56
|
+
|
57
|
+
# Sets the SDK code.
|
58
|
+
#
|
59
|
+
# Used for integrations.
|
60
|
+
#
|
61
|
+
# @param [String] sdk_code The SDK code to set.
|
62
|
+
#
|
63
|
+
# @return [void]
|
64
|
+
#
|
65
|
+
# @internal
|
66
|
+
def sdk_code(sdk_code)
|
67
|
+
@sdk_code = sdk_code
|
68
|
+
end
|
69
|
+
|
70
|
+
# Sets the SDK version.
|
71
|
+
#
|
72
|
+
# Used for integrations.
|
73
|
+
#
|
74
|
+
# @param [String] sdk_version The SDK version to set (MAJOR.MINOR.PATCH), for example: "1.0.0".
|
75
|
+
#
|
76
|
+
# @return [void]
|
77
|
+
#
|
78
|
+
# @internal
|
79
|
+
def sdk_version(sdk_version)
|
80
|
+
@sdk_version = sdk_version
|
81
|
+
end
|
82
|
+
|
83
|
+
# Sets the tech version.
|
84
|
+
#
|
85
|
+
# Used for integrations.
|
86
|
+
#
|
87
|
+
# @param [String] tech_version The tech version to set (MAJOR.MINOR), for example: "1.0".
|
88
|
+
#
|
89
|
+
# @return [void]
|
90
|
+
#
|
91
|
+
# @internal
|
92
|
+
def tech_version(tech_version)
|
93
|
+
@tech_version = tech_version.split('.').first(2).join('.')
|
94
|
+
end
|
95
|
+
|
96
|
+
# Encodes a semVer-like version string.
|
97
|
+
#
|
98
|
+
# Example:
|
99
|
+
# input: '1.24.0'
|
100
|
+
# explode: ['1','24','0']
|
101
|
+
# pad: ['01','24','00']
|
102
|
+
# reverse: ['00', '24', '01']
|
103
|
+
# implode: '002401'
|
104
|
+
# int: 2401
|
105
|
+
# binary: '100101100001'
|
106
|
+
# padded: '000000100101100001'
|
107
|
+
# str_split: ['000000', '100101', '100001']
|
108
|
+
# getKey: ['A', 'l', 'h']
|
109
|
+
# implode: 'Alh'
|
110
|
+
#
|
111
|
+
# @param [String] version Can be either x.y.z or x.y
|
112
|
+
#
|
113
|
+
# @return [String] A string built from 3 characters of the base64 table
|
114
|
+
#
|
115
|
+
# @raise [RangeError] when version is larger than 43.21.26
|
116
|
+
def encode_version(version)
|
117
|
+
parts = version.split('.')
|
118
|
+
|
119
|
+
padded_parts = parts.map { |part| part.rjust(2, '0') }
|
120
|
+
number = padded_parts.reverse.join.to_i
|
121
|
+
padded_binary = int_to_padded_bin(number, parts.length * BINARY_PAD_SIZE)
|
122
|
+
|
123
|
+
raise RangeError, 'Version must be smaller than 43.21.26' if padded_binary.length % BINARY_PAD_SIZE != 0
|
124
|
+
|
125
|
+
encoded_chars = padded_binary.chars.each_slice(BINARY_PAD_SIZE).map { |slice| get_key(slice.join) }
|
126
|
+
|
127
|
+
encoded_chars.join
|
128
|
+
end
|
129
|
+
|
130
|
+
# Gets the key for binary value.
|
131
|
+
#
|
132
|
+
# @param [String] binary_value The value.
|
133
|
+
#
|
134
|
+
# @return [Array, Object] The key for the binary value.
|
135
|
+
def get_key(binary_value)
|
136
|
+
@char_codes ||= initialize_char_codes
|
137
|
+
|
138
|
+
@char_codes[binary_value] || ''
|
139
|
+
end
|
140
|
+
|
141
|
+
def initialize_char_codes
|
142
|
+
char_codes = {}
|
143
|
+
CHARS.chars.each_with_index { |char, idx| char_codes[int_to_padded_bin(idx, BINARY_PAD_SIZE)] = char }
|
144
|
+
char_codes
|
145
|
+
end
|
146
|
+
|
147
|
+
# Converts integer to left padded binary string.
|
148
|
+
#
|
149
|
+
# @param [Integer] integer The input.
|
150
|
+
# @param [Integer] pad_num The num of padding chars.
|
151
|
+
#
|
152
|
+
# @return [String] The padded binary string.
|
153
|
+
def int_to_padded_bin(integer, pad_num)
|
154
|
+
integer.to_s(2).rjust(pad_num, '0')
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|