gocardless 1.11.1 → 1.11.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/gocardless/client.rb +1 -1
- data/lib/gocardless/utils.rb +20 -1
- data/lib/gocardless/version.rb +1 -1
- data/spec/client_spec.rb +21 -13
- data/spec/page_spec.rb +2 -2
- data/spec/resource_spec.rb +10 -10
- data/spec/spec_helper.rb +2 -2
- data/spec/utils_spec.rb +10 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 417cec8542edd246281e1e82b45294ad06d09a5e
|
4
|
+
data.tar.gz: 2dae626c784514a1b722dbb348bd782e954f7c46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d47705fcf702d7fb7ed80a1e847b7953c4b235f6bb78d16961978c97166eaa9c9b1d790dde027e3a2cac7109170e5b2063e1fac1a4588a576aeb143314a68795
|
7
|
+
data.tar.gz: b8c4cc2cc8ad7aebf8586a8f9b901e160116b03039c1c820b5c3bdab1848bddd233e061c07ded755d63f67f5df2ae096dad29169f2c1ad9ffc221ab8932eccf2
|
data/CHANGELOG.md
CHANGED
data/lib/gocardless/client.rb
CHANGED
@@ -418,7 +418,7 @@ module GoCardless
|
|
418
418
|
def signature_valid?(params)
|
419
419
|
params = params.clone
|
420
420
|
signature = params.delete(:signature)
|
421
|
-
sign_params(params)[:signature]
|
421
|
+
Utils.secure_compare(sign_params(params)[:signature], signature)
|
422
422
|
end
|
423
423
|
|
424
424
|
# Generate a random base64-encoded string
|
data/lib/gocardless/utils.rb
CHANGED
@@ -82,7 +82,7 @@ module GoCardless
|
|
82
82
|
end * '&'
|
83
83
|
end
|
84
84
|
|
85
|
-
# Given a Hash of parameters, normalize
|
85
|
+
# Given a Hash of parameters, normalize them (flatten and convert to a
|
86
86
|
# string), then generate the HMAC-SHA-256 signature using the provided key.
|
87
87
|
#
|
88
88
|
# @param [Hash] params the parameters to sign
|
@@ -94,6 +94,25 @@ module GoCardless
|
|
94
94
|
OpenSSL::HMAC.hexdigest(digest, key, msg)
|
95
95
|
end
|
96
96
|
|
97
|
+
# Given two strings, compare them in constant time (for the length of the
|
98
|
+
# string). This can avoid timing attacks when used to compare signed
|
99
|
+
# parameters.
|
100
|
+
# Borrowed from ActiveSupport::MessageVerifier.
|
101
|
+
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/message_verifier.rb
|
102
|
+
#
|
103
|
+
# @param [String] the first string to compare
|
104
|
+
# @param [String] this second string to compare
|
105
|
+
# @return [Boolean] the result of the comparison
|
106
|
+
def secure_compare(a, b)
|
107
|
+
return false unless a.bytesize == b.bytesize
|
108
|
+
|
109
|
+
l = a.unpack("C#{a.bytesize}")
|
110
|
+
|
111
|
+
res = 0
|
112
|
+
b.each_byte { |byte| res |= byte ^ l.shift }
|
113
|
+
res == 0
|
114
|
+
end
|
115
|
+
|
97
116
|
# Format a Time object according to ISO 8601, and convert to UTC.
|
98
117
|
#
|
99
118
|
# @param [Time] time the time object to format
|
data/lib/gocardless/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -235,7 +235,9 @@ describe GoCardless::Client do
|
|
235
235
|
token = @client.instance_variable_get(:@access_token)
|
236
236
|
r = double
|
237
237
|
r.stub(:parsed)
|
238
|
-
token.should_receive(:get)
|
238
|
+
token.should_receive(:get) do |p, o|
|
239
|
+
expect(p).to satisfy { |v| v =~ %r|/api/v1/test| }
|
240
|
+
end.and_return(r)
|
239
241
|
@client.api_get('/test')
|
240
242
|
end
|
241
243
|
|
@@ -250,7 +252,9 @@ describe GoCardless::Client do
|
|
250
252
|
token = @client.instance_variable_get(:@access_token)
|
251
253
|
r = double
|
252
254
|
r.stub(:parsed)
|
253
|
-
token.should_receive(:post)
|
255
|
+
token.should_receive(:post) do |p,opts|
|
256
|
+
expect(opts[:body]).to eq('{"a":1}')
|
257
|
+
end.and_return(r)
|
254
258
|
@client.api_post('/test', {:a => 1})
|
255
259
|
end
|
256
260
|
|
@@ -265,7 +269,9 @@ describe GoCardless::Client do
|
|
265
269
|
token = @client.instance_variable_get(:@access_token)
|
266
270
|
r = double
|
267
271
|
r.stub(:parsed)
|
268
|
-
token.should_receive(:delete)
|
272
|
+
token.should_receive(:delete) do |p,opts|
|
273
|
+
expect(opts[:body]).to eq('{"a":1}')
|
274
|
+
end.and_return(r)
|
269
275
|
@client.api_delete('/test', {:a => 1})
|
270
276
|
end
|
271
277
|
|
@@ -283,7 +289,9 @@ describe GoCardless::Client do
|
|
283
289
|
|
284
290
|
token = @client.instance_variable_get(:@access_token)
|
285
291
|
merchant_url = '/api/v1/merchants/123'
|
286
|
-
token.should_receive(:get)
|
292
|
+
token.should_receive(:get) do |p,o|
|
293
|
+
expect(p).to eq(merchant_url)
|
294
|
+
end.and_return response
|
287
295
|
|
288
296
|
GoCardless::Merchant.stub(:new_with_client)
|
289
297
|
|
@@ -331,12 +339,12 @@ describe GoCardless::Client do
|
|
331
339
|
|
332
340
|
it "succeeds with a valid signature" do
|
333
341
|
params = @client.send(:sign_params, @params)
|
334
|
-
@client.send(:signature_valid?, params).should
|
342
|
+
@client.send(:signature_valid?, params).should be_truthy
|
335
343
|
end
|
336
344
|
|
337
345
|
it "fails with an invalid signature" do
|
338
346
|
params = {:signature => 'invalid'}.merge(@params)
|
339
|
-
@client.send(:signature_valid?, params).should
|
347
|
+
@client.send(:signature_valid?, params).should be_falsey
|
340
348
|
end
|
341
349
|
end
|
342
350
|
|
@@ -380,11 +388,11 @@ describe GoCardless::Client do
|
|
380
388
|
it "includes valid http basic credentials" do
|
381
389
|
GoCardless::Subscription.stub(:find_with_client)
|
382
390
|
auth = 'Basic YWJjOnh5eg=='
|
383
|
-
@client.should_receive(:request)
|
391
|
+
@client.should_receive(:request) do |type, path, opts|
|
384
392
|
opts.should include :headers
|
385
393
|
opts[:headers].should include 'Authorization'
|
386
394
|
opts[:headers]['Authorization'].should == auth
|
387
|
-
end
|
395
|
+
end.once
|
388
396
|
@client.confirm_resource(@client.send(:sign_params, @params))
|
389
397
|
end
|
390
398
|
|
@@ -438,12 +446,12 @@ describe GoCardless::Client do
|
|
438
446
|
|
439
447
|
it "and_return false when the signature is invalid" do
|
440
448
|
params = {:signature => 'xxx'}.merge(@params)
|
441
|
-
@client.response_params_valid?(params).should
|
449
|
+
@client.response_params_valid?(params).should be_falsey
|
442
450
|
end
|
443
451
|
|
444
452
|
it "and_return true when the signature is valid" do
|
445
453
|
params = @client.send(:sign_params, @params)
|
446
|
-
@client.response_params_valid?(params).should
|
454
|
+
@client.response_params_valid?(params).should be_truthy
|
447
455
|
end
|
448
456
|
end
|
449
457
|
|
@@ -501,7 +509,7 @@ describe GoCardless::Client do
|
|
501
509
|
|
502
510
|
it "should include a valid signature" do
|
503
511
|
params = get_params(@client.send(:new_limit_url, :subscription, :x => 1))
|
504
|
-
params.key?('signature').should
|
512
|
+
params.key?('signature').should be_truthy
|
505
513
|
sig = params.delete('signature')
|
506
514
|
sig.should == @client.send(:sign_params, params.clone)[:signature]
|
507
515
|
end
|
@@ -542,13 +550,13 @@ describe GoCardless::Client do
|
|
542
550
|
describe "#webhook_valid?" do
|
543
551
|
it "and_return false when the webhook signature is invalid" do
|
544
552
|
@client.webhook_valid?({:some => 'stuff', :signature => 'invalid'}).
|
545
|
-
should
|
553
|
+
should be_falsey
|
546
554
|
end
|
547
555
|
|
548
556
|
it "and_return true when the webhook signature is valid" do
|
549
557
|
valid_signature = '175e814f0f64e5e86d41fb8fe06a857cedda715a96d3dc3d885e6d97dbeb7e49'
|
550
558
|
@client.webhook_valid?({:some => 'stuff', :signature => valid_signature}).
|
551
|
-
should
|
559
|
+
should be_truthy
|
552
560
|
end
|
553
561
|
end
|
554
562
|
|
data/spec/page_spec.rb
CHANGED
@@ -14,12 +14,12 @@ describe GoCardless::Page do
|
|
14
14
|
|
15
15
|
context "when there is next page available" do
|
16
16
|
let(:links) {{ "next" => 2, "last" => 2 }}
|
17
|
-
it { should
|
17
|
+
it { should be_truthy }
|
18
18
|
end
|
19
19
|
|
20
20
|
context "when there is no next page" do
|
21
21
|
let(:links) {{ "previous" => 1, "first" => 1 }}
|
22
|
-
it { should
|
22
|
+
it { should be_falsey }
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
data/spec/resource_spec.rb
CHANGED
@@ -170,8 +170,8 @@ describe GoCardless::Resource do
|
|
170
170
|
end
|
171
171
|
|
172
172
|
it "#persisted? works" do
|
173
|
-
GoCardless::Resource.new.persisted?.should
|
174
|
-
GoCardless::Resource.new(:id => 1).persisted?.should
|
173
|
+
GoCardless::Resource.new.persisted?.should be_falsey
|
174
|
+
GoCardless::Resource.new(:id => 1).persisted?.should be_truthy
|
175
175
|
end
|
176
176
|
|
177
177
|
describe "#save" do
|
@@ -288,8 +288,8 @@ describe GoCardless::Resource do
|
|
288
288
|
|
289
289
|
describe "resource permissions" do
|
290
290
|
it "are not given by default" do
|
291
|
-
GoCardless::Resource.creatable?.should
|
292
|
-
GoCardless::Resource.updatable?.should
|
291
|
+
GoCardless::Resource.creatable?.should be_falsey
|
292
|
+
GoCardless::Resource.updatable?.should be_falsey
|
293
293
|
end
|
294
294
|
|
295
295
|
it "are present when specified" do
|
@@ -301,14 +301,14 @@ describe GoCardless::Resource do
|
|
301
301
|
updatable
|
302
302
|
end
|
303
303
|
|
304
|
-
CreatableResource.creatable?.should
|
305
|
-
CreatableResource.updatable?.should
|
304
|
+
CreatableResource.creatable?.should be_truthy
|
305
|
+
CreatableResource.updatable?.should be_falsey
|
306
306
|
|
307
|
-
UpdatableResource.creatable?.should
|
308
|
-
UpdatableResource.updatable?.should
|
307
|
+
UpdatableResource.creatable?.should be_falsey
|
308
|
+
UpdatableResource.updatable?.should be_truthy
|
309
309
|
|
310
|
-
GoCardless::Resource.creatable?.should
|
311
|
-
GoCardless::Resource.updatable?.should
|
310
|
+
GoCardless::Resource.creatable?.should be_falsey
|
311
|
+
GoCardless::Resource.updatable?.should be_falsey
|
312
312
|
end
|
313
313
|
end
|
314
314
|
|
data/spec/spec_helper.rb
CHANGED
@@ -17,12 +17,12 @@ shared_examples_for "it has a query method for" do |status|
|
|
17
17
|
describe "##{status}?" do
|
18
18
|
context "when #{status}" do
|
19
19
|
let(:object) { described_class.new(:status => status) }
|
20
|
-
specify { object.send("#{status}?").should
|
20
|
+
specify { object.send("#{status}?").should be_truthy }
|
21
21
|
end
|
22
22
|
|
23
23
|
context "when not #{status}" do
|
24
24
|
let(:object) { described_class.new }
|
25
|
-
specify { object.send("#{status}?").should
|
25
|
+
specify { object.send("#{status}?").should be_falsey }
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/spec/utils_spec.rb
CHANGED
@@ -26,6 +26,16 @@ describe GoCardless::Utils do
|
|
26
26
|
GoCardless::Utils.singularize("cacti").should == "cactus"
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
describe '.secure_compare' do
|
31
|
+
it 'is true for the same strings' do
|
32
|
+
GoCardless::Utils.secure_compare('hello', 'hello').should be_truthy
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'is false for different strings' do
|
36
|
+
GoCardless::Utils.secure_compare('hello', 'banjo').should be_falsey
|
37
|
+
end
|
38
|
+
end
|
29
39
|
end
|
30
40
|
|
31
41
|
describe "hash helpers" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gocardless
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.11.
|
4
|
+
version: 1.11.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harry Marr
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-10-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oauth2
|
@@ -157,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
157
|
version: '0'
|
158
158
|
requirements: []
|
159
159
|
rubyforge_project:
|
160
|
-
rubygems_version: 2.
|
160
|
+
rubygems_version: 2.4.2
|
161
161
|
signing_key:
|
162
162
|
specification_version: 4
|
163
163
|
summary: Ruby wrapper for the GoCardless API
|