cloudinary 1.4.0 → 1.5.2
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 +13 -5
- data/CHANGELOG.md +31 -0
- data/cloudinary.gemspec +6 -3
- data/lib/cloudinary.rb +67 -39
- data/lib/cloudinary/api.rb +46 -0
- data/lib/cloudinary/auth_token.rb +68 -0
- data/lib/cloudinary/carrier_wave/remote.rb +3 -3
- data/lib/cloudinary/ostruct2.rb +284 -0
- data/lib/cloudinary/uploader.rb +1 -0
- data/lib/cloudinary/utils.rb +35 -15
- data/lib/cloudinary/version.rb +1 -1
- data/spec/api_spec.rb +63 -21
- data/spec/archive_spec.rb +1 -1
- data/spec/auth_token_spec.rb +82 -0
- data/spec/cloudinary_helper_spec.rb +16 -0
- data/spec/cloudinary_spec.rb +15 -0
- data/spec/utils_methods_spec.rb +0 -33
- metadata +65 -34
- data/lib/cloudinary/akamai.rb +0 -50
data/lib/cloudinary/uploader.rb
CHANGED
@@ -16,6 +16,7 @@ class Cloudinary::Uploader
|
|
16
16
|
options.keys.each { |key| options[key.to_sym] = options.delete(key) if key.is_a?(String) }
|
17
17
|
|
18
18
|
params = {
|
19
|
+
:access_mode => options[:access_mode],
|
19
20
|
:allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
|
20
21
|
:auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f,
|
21
22
|
:background_removal => options[:background_removal],
|
data/lib/cloudinary/utils.rb
CHANGED
@@ -5,10 +5,9 @@ require 'uri'
|
|
5
5
|
require 'aws_cf_signer'
|
6
6
|
require 'json'
|
7
7
|
require 'cgi'
|
8
|
-
require 'cloudinary/
|
8
|
+
require 'cloudinary/auth_token'
|
9
9
|
|
10
10
|
class Cloudinary::Utils
|
11
|
-
include Cloudinary::Akamai
|
12
11
|
# @deprecated Use Cloudinary::SHARED_CDN
|
13
12
|
SHARED_CDN = Cloudinary::SHARED_CDN
|
14
13
|
DEFAULT_RESPONSIVE_WIDTH_TRANSFORMATION = {:width => :auto, :crop => :limit}
|
@@ -41,7 +40,7 @@ class Cloudinary::Utils
|
|
41
40
|
|
42
41
|
symbolize_keys!(options)
|
43
42
|
|
44
|
-
responsive_width = config_option_consume(options, :responsive_width)
|
43
|
+
responsive_width = config_option_consume(options, :responsive_width)
|
45
44
|
size = options.delete(:size)
|
46
45
|
options[:width], options[:height] = size.split("x") if size
|
47
46
|
width = options[:width]
|
@@ -282,7 +281,7 @@ class Cloudinary::Utils
|
|
282
281
|
transformation = breakpoint_settings.delete(:transformation) || breakpoint_settings.delete("transformation")
|
283
282
|
if transformation
|
284
283
|
breakpoint_settings[:transformation] = Cloudinary::Utils.generate_transformation_string(transformation.clone, true)
|
285
|
-
end
|
284
|
+
end
|
286
285
|
end
|
287
286
|
breakpoint_settings
|
288
287
|
|
@@ -317,6 +316,10 @@ class Cloudinary::Utils
|
|
317
316
|
sign_version = config_option_consume(options, :sign_version) # Deprecated behavior
|
318
317
|
url_suffix = options.delete(:url_suffix)
|
319
318
|
use_root_path = config_option_consume(options, :use_root_path)
|
319
|
+
auth_token = config_option_consume(options, :auth_token)
|
320
|
+
unless auth_token == false
|
321
|
+
auth_token = Cloudinary::AuthToken.merge_auth_token(Cloudinary.config.auth_token, auth_token)
|
322
|
+
end
|
320
323
|
|
321
324
|
original_source = source
|
322
325
|
return original_source if source.blank?
|
@@ -354,7 +357,7 @@ class Cloudinary::Utils
|
|
354
357
|
version &&= "v#{version}"
|
355
358
|
|
356
359
|
transformation = transformation.gsub(%r(([^:])//), '\1/')
|
357
|
-
if sign_url
|
360
|
+
if sign_url && ( !auth_token || auth_token.empty?)
|
358
361
|
to_sign = [transformation, sign_version && version, source_to_sign].reject(&:blank?).join("/")
|
359
362
|
i = 0
|
360
363
|
while to_sign != CGI.unescape(to_sign) && i <10
|
@@ -366,6 +369,13 @@ class Cloudinary::Utils
|
|
366
369
|
|
367
370
|
prefix = unsigned_download_url_prefix(source, cloud_name, private_cdn, cdn_subdomain, secure_cdn_subdomain, cname, secure, secure_distribution)
|
368
371
|
source = [prefix, resource_type, type, signature, transformation, version, source].reject(&:blank?).join("/")
|
372
|
+
if sign_url && auth_token && !auth_token.empty?
|
373
|
+
auth_token[:url] = URI.parse(source).path
|
374
|
+
token = Cloudinary::AuthToken.generate auth_token
|
375
|
+
source += "?#{token}"
|
376
|
+
end
|
377
|
+
|
378
|
+
source
|
369
379
|
end
|
370
380
|
|
371
381
|
def self.finalize_source(source, format, url_suffix)
|
@@ -496,7 +506,7 @@ class Cloudinary::Utils
|
|
496
506
|
return Cloudinary::Utils.cloudinary_api_url("download", options) + "?" + hash_query_params(cloudinary_params)
|
497
507
|
end
|
498
508
|
|
499
|
-
# Utility method that uses the deprecated ZIP download API.
|
509
|
+
# Utility method that uses the deprecated ZIP download API.
|
500
510
|
# @deprecated Replaced by {download_zip_url} that uses the more advanced and robust archive generation and download API
|
501
511
|
def self.zip_download_url(tag, options = {})
|
502
512
|
warn "zip_download_url is deprecated. Please use download_zip_url instead."
|
@@ -543,14 +553,19 @@ class Cloudinary::Utils
|
|
543
553
|
end
|
544
554
|
|
545
555
|
def self.signed_download_url(public_id, options = {})
|
546
|
-
aws_private_key_path = options[:aws_private_key_path] || Cloudinary.config.aws_private_key_path
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
556
|
+
aws_private_key_path = options[:aws_private_key_path] || Cloudinary.config.aws_private_key_path
|
557
|
+
if aws_private_key_path
|
558
|
+
aws_key_pair_id = options[:aws_key_pair_id] || Cloudinary.config.aws_key_pair_id || raise(CloudinaryException, "Must supply aws_key_pair_id")
|
559
|
+
authenticated_distribution = options[:authenticated_distribution] || Cloudinary.config.authenticated_distribution || raise(CloudinaryException, "Must supply authenticated_distribution")
|
560
|
+
@signers ||= Hash.new{|h,k| path, id = k; h[k] = AwsCfSigner.new(path, id)}
|
561
|
+
signer = @signers[[aws_private_key_path, aws_key_pair_id]]
|
562
|
+
url = Cloudinary::Utils.unsigned_download_url(public_id, {:type=>:authenticated}.merge(options).merge(:secure=>true, :secure_distribution=>authenticated_distribution, :private_cdn=>true))
|
563
|
+
expires_at = options[:expires_at] || (Time.now+3600)
|
564
|
+
return signer.sign(url, :ending => expires_at)
|
565
|
+
else
|
566
|
+
return Cloudinary::Utils.unsigned_download_url( public_id, options)
|
567
|
+
end
|
568
|
+
|
554
569
|
end
|
555
570
|
|
556
571
|
def self.cloudinary_url(public_id, options = {})
|
@@ -753,7 +768,7 @@ class Cloudinary::Utils
|
|
753
768
|
|
754
769
|
#
|
755
770
|
# @private
|
756
|
-
# @param [String|Hash|Array] an
|
771
|
+
# @param [String|Hash|Array] eager an transformation as a string or hash, with or without a format. The parameter also accepts an array of eager transformations.
|
757
772
|
def self.build_eager(eager)
|
758
773
|
return nil if eager.nil?
|
759
774
|
Cloudinary::Utils.build_array(eager).map do
|
@@ -769,6 +784,11 @@ class Cloudinary::Utils
|
|
769
784
|
end.join("|")
|
770
785
|
end
|
771
786
|
|
787
|
+
def self.generate_auth_token(options)
|
788
|
+
options = Cloudinary::AuthToken.merge_auth_token Cloudinary.config.auth_token, options
|
789
|
+
Cloudinary::AuthToken.generate options
|
790
|
+
|
791
|
+
end
|
772
792
|
private
|
773
793
|
|
774
794
|
def self.hash_query_params(hash)
|
data/lib/cloudinary/version.rb
CHANGED
data/spec/api_spec.rb
CHANGED
@@ -4,7 +4,8 @@ require 'cloudinary'
|
|
4
4
|
describe Cloudinary::Api do
|
5
5
|
break puts("Please setup environment for api test to run") if Cloudinary.config.api_secret.blank?
|
6
6
|
include_context "cleanup", TIMESTAMP_TAG
|
7
|
-
|
7
|
+
TEST_WIDTH = rand(1000)
|
8
|
+
TEST_TRANSFOMATION = "c_scale,w_#{TEST_WIDTH}"
|
8
9
|
prefix = "api_test_#{Time.now.to_i}"
|
9
10
|
test_id_1 = "#{prefix}_1"
|
10
11
|
test_id_2 = "#{prefix}_2"
|
@@ -12,11 +13,11 @@ describe Cloudinary::Api do
|
|
12
13
|
before(:all) do
|
13
14
|
|
14
15
|
@api = Cloudinary::Api
|
15
|
-
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_1, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>
|
16
|
-
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_2, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>
|
17
|
-
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_3, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>
|
18
|
-
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_1, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "test-key=test", :eager =>[:width =>
|
19
|
-
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_3, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "test-key=tasty", :eager =>[:width =>
|
16
|
+
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_1, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
|
17
|
+
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_2, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
|
18
|
+
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_3, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "key=value", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
|
19
|
+
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_1, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "test-key=test", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
|
20
|
+
Cloudinary::Uploader.upload(TEST_IMG, :public_id => test_id_3, :tags => [TEST_TAG, TIMESTAMP_TAG], :context => "test-key=tasty", :eager =>[:width =>TEST_WIDTH, :crop =>:scale])
|
20
21
|
end
|
21
22
|
|
22
23
|
after(:all) do
|
@@ -198,37 +199,37 @@ describe Cloudinary::Api do
|
|
198
199
|
|
199
200
|
describe 'transformations' do
|
200
201
|
it "should allow listing transformations" do
|
201
|
-
transformation = @api.transformations()["transformations"].find { |transformation| transformation["name"] ==
|
202
|
+
transformation = @api.transformations(max_results: 500)["transformations"].find { |transformation| transformation["name"] == TEST_TRANSFOMATION }
|
202
203
|
expect(transformation).not_to be_blank
|
203
204
|
expect(transformation["used"]).to eq(true)
|
204
205
|
end
|
205
206
|
|
206
207
|
it "should allow getting transformation metadata" do
|
207
|
-
transformation = @api.transformation(
|
208
|
+
transformation = @api.transformation(TEST_TRANSFOMATION)
|
208
209
|
expect(transformation).not_to be_blank
|
209
|
-
expect(transformation["info"]).to eq(["crop" => "scale", "width" =>
|
210
|
-
transformation = @api.transformation("crop" => "scale", "width" =>
|
210
|
+
expect(transformation["info"]).to eq(["crop" => "scale", "width" => TEST_WIDTH])
|
211
|
+
transformation = @api.transformation("crop" => "scale", "width" => TEST_WIDTH)
|
211
212
|
expect(transformation).not_to be_blank
|
212
|
-
expect(transformation["info"]).to eq(["crop" => "scale", "width" =>
|
213
|
+
expect(transformation["info"]).to eq(["crop" => "scale", "width" => TEST_WIDTH])
|
213
214
|
end
|
214
215
|
|
215
216
|
it "should allow updating transformation allowed_for_strict" do
|
216
|
-
@api.update_transformation(
|
217
|
-
transformation = @api.transformation(
|
217
|
+
@api.update_transformation(TEST_TRANSFOMATION, :allowed_for_strict => true)
|
218
|
+
transformation = @api.transformation(TEST_TRANSFOMATION)
|
218
219
|
expect(transformation).not_to be_blank
|
219
220
|
expect(transformation["allowed_for_strict"]).to eq(true)
|
220
|
-
@api.update_transformation(
|
221
|
-
transformation = @api.transformation(
|
221
|
+
@api.update_transformation(TEST_TRANSFOMATION, :allowed_for_strict => false)
|
222
|
+
transformation = @api.transformation(TEST_TRANSFOMATION)
|
222
223
|
expect(transformation).not_to be_blank
|
223
224
|
expect(transformation["allowed_for_strict"]).to eq(false)
|
224
225
|
end
|
225
226
|
|
226
227
|
it "should fetch two different derived images using next_cursor" do
|
227
|
-
result = @api.transformation(
|
228
|
+
result = @api.transformation(TEST_TRANSFOMATION, :max_results=>1)
|
228
229
|
expect(result["derived"]).not_to be_blank
|
229
230
|
expect(result["derived"].length).to eq(1)
|
230
231
|
expect(result["next_cursor"]).not_to be_blank
|
231
|
-
result2 = @api.transformation(
|
232
|
+
result2 = @api.transformation(TEST_TRANSFOMATION, :max_results=>1, :next_cursor=>result["next_cursor"])
|
232
233
|
expect(result2["derived"]).not_to be_blank
|
233
234
|
expect(result2["derived"].length).to eq(1)
|
234
235
|
expect(result2["derived"][0]["id"]).not_to eq(result["derived"][0]["id"] )
|
@@ -263,9 +264,9 @@ describe Cloudinary::Api do
|
|
263
264
|
|
264
265
|
end
|
265
266
|
it "should allow deleting implicit transformation" do
|
266
|
-
@api.transformation(
|
267
|
-
@api.delete_transformation(
|
268
|
-
expect { @api.transformation(
|
267
|
+
@api.transformation(TEST_TRANSFOMATION)
|
268
|
+
@api.delete_transformation(TEST_TRANSFOMATION)
|
269
|
+
expect { @api.transformation(TEST_TRANSFOMATION) }.to raise_error(Cloudinary::Api::NotFound)
|
269
270
|
end
|
270
271
|
end
|
271
272
|
|
@@ -374,7 +375,7 @@ describe Cloudinary::Api do
|
|
374
375
|
end
|
375
376
|
|
376
377
|
it "should throw if folder is missing" do
|
377
|
-
Cloudinary::Api.subfolders("I_do_not_exist")
|
378
|
+
expect{Cloudinary::Api.subfolders("I_do_not_exist")}.to raise_error(Cloudinary::Api::NotFound)
|
378
379
|
end
|
379
380
|
|
380
381
|
describe '.restore' do
|
@@ -395,4 +396,45 @@ describe Cloudinary::Api do
|
|
395
396
|
|
396
397
|
|
397
398
|
end
|
399
|
+
describe "access_mode" do
|
400
|
+
i = 0
|
401
|
+
|
402
|
+
publicId = ""
|
403
|
+
access_mode_tag = ''
|
404
|
+
before(:each) do
|
405
|
+
i += 1
|
406
|
+
access_mode_tag = TEST_TAG + "access_mode" + i.to_s
|
407
|
+
result = Cloudinary::Uploader.upload TEST_IMG, access_mode: "authenticated", tags: [TEST_TAG, TIMESTAMP_TAG, access_mode_tag]
|
408
|
+
publicId = result["public_id"]
|
409
|
+
expect(result["access_mode"]).to eq("authenticated")
|
410
|
+
end
|
411
|
+
|
412
|
+
it "should update access mode by ids" do
|
413
|
+
result = Cloudinary::Api.update_resources_access_mode_by_ids "public", [publicId]
|
414
|
+
|
415
|
+
expect(result["updated"]).to be_an_instance_of(Array)
|
416
|
+
expect(result["updated"].length).to eq(1)
|
417
|
+
resource = result["updated"][0]
|
418
|
+
expect(resource["public_id"]).to eq(publicId)
|
419
|
+
expect(resource["access_mode"]).to eq('public')
|
420
|
+
end
|
421
|
+
it "should update access mode by prefix" do
|
422
|
+
result = Cloudinary::Api.update_resources_access_mode_by_prefix "public", publicId[0..-3]
|
423
|
+
|
424
|
+
expect(result["updated"]).to be_an_instance_of(Array)
|
425
|
+
expect(result["updated"].length).to eq(1)
|
426
|
+
resource = result["updated"][0]
|
427
|
+
expect(resource["public_id"]).to eq(publicId)
|
428
|
+
expect(resource["access_mode"]).to eq('public')
|
429
|
+
end
|
430
|
+
it "should update access mode by tag" do
|
431
|
+
result = Cloudinary::Api.update_resources_access_mode_by_tag "public", access_mode_tag
|
432
|
+
|
433
|
+
expect(result["updated"]).to be_an_instance_of(Array)
|
434
|
+
expect(result["updated"].length).to eq(1)
|
435
|
+
resource = result["updated"][0]
|
436
|
+
expect(resource["public_id"]).to eq(publicId)
|
437
|
+
expect(resource["access_mode"]).to eq('public')
|
438
|
+
end
|
439
|
+
end
|
398
440
|
end
|
data/spec/archive_spec.rb
CHANGED
@@ -92,7 +92,7 @@ describe Cloudinary::Uploader do
|
|
92
92
|
file_count
|
93
93
|
)
|
94
94
|
it "should include keys: #{expected_keys.join(', ')}" do
|
95
|
-
expect(archive_result.keys).to
|
95
|
+
expect(archive_result.keys).to include(*expected_keys)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
describe '.create_zip' do
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'cloudinary'
|
4
|
+
|
5
|
+
KEY = "00112233FF99"
|
6
|
+
ALT_KEY = "CCBB2233FF00"
|
7
|
+
|
8
|
+
describe 'auth_token' do
|
9
|
+
before :all do
|
10
|
+
@url_backup = ENV["CLOUDINARY_URL"]
|
11
|
+
end
|
12
|
+
before do
|
13
|
+
Cloudinary.config_from_url "cloudinary://a:b@test123"
|
14
|
+
Cloudinary.config.auth_token = { :key => KEY, :duration => 300, :start_time => 11111111 }
|
15
|
+
end
|
16
|
+
after do
|
17
|
+
ENV["CLOUDINARY_URL"] = @url_backup
|
18
|
+
Cloudinary::config_from_url @url_backup
|
19
|
+
end
|
20
|
+
it "should generate with start and duration" do
|
21
|
+
token = Cloudinary::Utils.generate_auth_token :start_time => 1111111111, :acl => "/image/*", :duration => 300
|
22
|
+
expect(token).to eq '__cld_token__=st=1111111111~exp=1111111411~acl=%2fimage%2f%2a~hmac=0d5b0c9c1485ee162c459879fe62e06caa23bc26fec92d58bd100f2e1592eac6'
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "authenticated url" do
|
26
|
+
before do
|
27
|
+
Cloudinary.config :private_cdn => true
|
28
|
+
|
29
|
+
end
|
30
|
+
it "should add token if authToken is globally set and signed = true" do
|
31
|
+
url = Cloudinary::Utils.cloudinary_url "sample.jpg", :sign_url => true, :resource_type => "image", :type => "authenticated", :version => "1486020273"
|
32
|
+
expect(url).to eq("http://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=8db0d753ee7bbb9e2eaf8698ca3797436ba4c20e31f44527e43b6a6e995cfdb3")
|
33
|
+
|
34
|
+
end
|
35
|
+
it "should add token for 'public' resource" do
|
36
|
+
url = Cloudinary::Utils.cloudinary_url "sample.jpg", :sign_url => true, :resource_type => "image", :type => "public", :version => "1486020273"
|
37
|
+
expect(url).to eq("http://test123-res.cloudinary.com/image/public/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=c2b77d9f81be6d89b5d0ebc67b671557e88a40bcf03dd4a6997ff4b994ceb80e")
|
38
|
+
|
39
|
+
end
|
40
|
+
it "should not add token if signed is false" do
|
41
|
+
url = Cloudinary::Utils.cloudinary_url "sample.jpg", :type => "authenticated", :version => "1486020273"
|
42
|
+
expect(url).to eq("http://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg")
|
43
|
+
|
44
|
+
end
|
45
|
+
it "should not add token if authToken is globally set but null auth token is explicitly set and signed = true" do
|
46
|
+
url = Cloudinary::Utils.cloudinary_url "sample.jpg", :auth_token => false, :sign_url => true, :type => "authenticated", :version => "1486020273"
|
47
|
+
expect(url).to eq("http://test123-res.cloudinary.com/image/authenticated/s--v2fTPYTu--/v1486020273/sample.jpg")
|
48
|
+
|
49
|
+
end
|
50
|
+
it "explicit authToken should override global setting" do
|
51
|
+
url = Cloudinary::Utils.cloudinary_url "sample.jpg", :sign_url => true, :auth_token => { :key => ALT_KEY, :start_time => 222222222, :duration => 100 }, :type => "authenticated", :transformation => { :crop => "scale", :width => 300 }
|
52
|
+
expect(url).to eq("http://test123-res.cloudinary.com/image/authenticated/c_scale,w_300/sample.jpg?__cld_token__=st=222222222~exp=222222322~hmac=7d276841d70c4ecbd0708275cd6a82e1f08e47838fbb0bceb2538e06ddfa3029")
|
53
|
+
|
54
|
+
end
|
55
|
+
it "should compute expiration as start time + duration" do
|
56
|
+
token = { :key => KEY, :start_time => 11111111, :duration => 300 }
|
57
|
+
url = Cloudinary::Utils.cloudinary_url "sample.jpg", :sign_url => true, :auth_token => token, :resource_type => "image", :type => "authenticated", :version => "1486020273"
|
58
|
+
expect(url).to eq("http://test123-res.cloudinary.com/image/authenticated/v1486020273/sample.jpg?__cld_token__=st=11111111~exp=11111411~hmac=8db0d753ee7bbb9e2eaf8698ca3797436ba4c20e31f44527e43b6a6e995cfdb3")
|
59
|
+
|
60
|
+
end
|
61
|
+
it "should raise if key is not provided" do
|
62
|
+
Cloudinary.config.auth_token[:key] = nil
|
63
|
+
token = { :expiration => 111111, :duration => 0 }
|
64
|
+
expect{Cloudinary::Utils.generate_auth_token(token)}.to raise_error
|
65
|
+
end
|
66
|
+
it "should raise if expiration and duration are not provided" do
|
67
|
+
token = { :key => KEY, :expiration => 0, :duration => 0 }
|
68
|
+
expect{Cloudinary::Utils.generate_auth_token(token)}.to raise_error
|
69
|
+
end
|
70
|
+
end
|
71
|
+
describe "authentication token" do
|
72
|
+
it "should generate token string" do
|
73
|
+
user = "foobar" # we can't rely on the default "now" value in tests
|
74
|
+
tokenOptions = { :key => KEY, :duration => 300, :acl => "/*/t_#{user}" }
|
75
|
+
tokenOptions[:start_time] = 222222222 # we can't rely on the default "now" value in tests
|
76
|
+
cookieToken = Cloudinary::Utils.generate_auth_token tokenOptions
|
77
|
+
expect(cookieToken).to eq("__cld_token__=st=222222222~exp=222222522~acl=%2f%2a%2ft_foobar~hmac=1284376353c1c43d6f6a98f2813c5596f4ff6f34d837cd853fd8c3c9e7f8428c")
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
@@ -4,6 +4,8 @@ require 'cloudinary'
|
|
4
4
|
require 'action_view'
|
5
5
|
require 'cloudinary/helper'
|
6
6
|
|
7
|
+
KEY = "00112233FF99"
|
8
|
+
|
7
9
|
helper_class = Class.new do
|
8
10
|
include CloudinaryHelper
|
9
11
|
end
|
@@ -127,4 +129,18 @@ RSpec.describe CloudinaryHelper do
|
|
127
129
|
expect(tag['http-equiv']).to eq('Accept-CH')
|
128
130
|
end
|
129
131
|
end
|
132
|
+
|
133
|
+
context "auth_token" do
|
134
|
+
it "should add token to an image tag url" do
|
135
|
+
tag = helper.cl_image_tag "sample.jpg",
|
136
|
+
:cloud_name => 'test123',
|
137
|
+
:sign_url => true,
|
138
|
+
:type => "authenticated",
|
139
|
+
:version => "1486020273",
|
140
|
+
:auth_token => {key: KEY, start_time: 11111111, duration: 300}
|
141
|
+
expect(tag).to match /<img.*src="http:\/\/res.cloudinary.com\/test123\/image\/authenticated\/v1486020273\/sample.jpg\?__cld_token__=st=11111111~exp=11111411~hmac=9bd6f41e2a5893da8343dc8eb648de8bf73771993a6d1457d49851250caf3b80.*>/
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
130
146
|
end
|
data/spec/cloudinary_spec.rb
CHANGED
@@ -14,4 +14,19 @@ describe Cloudinary do
|
|
14
14
|
expect(Cloudinary.USER_AGENT).to match( %r"Spec\/1.0 \(Test\) CloudinaryRuby/[\d.]+")
|
15
15
|
|
16
16
|
end
|
17
|
+
|
18
|
+
describe 'config' do
|
19
|
+
before do
|
20
|
+
@url_backup = ENV["CLOUDINARY_URL"]
|
21
|
+
end
|
22
|
+
after do
|
23
|
+
ENV["CLOUDINARY_URL"] = @url_backup
|
24
|
+
Cloudinary::config_from_url @url_backup
|
25
|
+
end
|
26
|
+
it "should allow nested values in CLOUDINARY_URL" do
|
27
|
+
ENV["CLOUDINARY_URL"] = "cloudinary://key:secret@test123?foo[bar]=value"
|
28
|
+
Cloudinary::config_from_url ENV["CLOUDINARY_URL"]
|
29
|
+
expect(Cloudinary::config.foo.bar).to eq 'value'
|
30
|
+
end
|
31
|
+
end
|
17
32
|
end
|
data/spec/utils_methods_spec.rb
CHANGED
@@ -15,38 +15,5 @@ describe Utils do
|
|
15
15
|
it "should parse a percent range value" do
|
16
16
|
expect(Utils.instance_eval { norm_range_value("20p") }).to eq("20p")
|
17
17
|
end
|
18
|
-
describe 'Utils.generate_token' do
|
19
|
-
config_backup = Cloudinary.config.clone
|
20
|
-
before do
|
21
|
-
Cloudinary.config.akamai_key = '00112233FF99'
|
22
|
-
end
|
23
|
-
after do
|
24
|
-
Cloudinary.config.each_pair { |k, _| Cloudinary.config.delete_field(k) }
|
25
|
-
Cloudinary.config(config_backup.to_h)
|
26
|
-
end
|
27
|
-
it "should generate an Akamai token with start_time and window" do
|
28
|
-
token = Utils.generate_token start_time: 1111111111, acl: '/image/*', window: 300
|
29
|
-
expect(token).to eq('__cld_token__=st=1111111111~exp=1111111411~acl=/image/*~hmac=0854e8b6b6a46471a80b2dc28c69bd352d977a67d031755cc6f3486c121b43af')
|
30
|
-
end
|
31
|
-
it "should generate an Akamai token with window" do
|
32
|
-
first_exp = Time.new.getgm.to_i + 300
|
33
|
-
# expiration is calculated automatically as now + window
|
34
|
-
token = Utils.generate_token acl: '*', window: 300
|
35
|
-
second_exp = Time.new.getgm.to_i + 300
|
36
|
-
match = /exp=(\d+)/.match(token)
|
37
|
-
expect(match[1]).to be_truthy
|
38
|
-
expiration = match[1].to_i
|
39
|
-
expect(expiration).to be_between(first_exp, second_exp)
|
40
|
-
expect(Utils.generate_token acl: '*', end_time: expiration).to eq(token)
|
41
|
-
end
|
42
18
|
|
43
|
-
it "should accept a key" do
|
44
|
-
expect(Utils.generate_token acl: '*', end_time: 10000000, key: '00aabbff')
|
45
|
-
.to eq('__cld_token__=exp=10000000~acl=*~hmac=030eafb6b19e499659d699b3d43e7595e35e3c0060e8a71904b3b8c8759f4890')
|
46
|
-
end
|
47
|
-
it "should throw if no end_time or window is provided" do
|
48
|
-
expect { Utils.generate_token acl: '*' }.to raise_error
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
52
19
|
end
|