auth0 5.1.2 → 5.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/CHANGELOG.md +44 -0
  4. data/README.md +1 -0
  5. data/auth0.gemspec +7 -6
  6. data/lib/auth0/api/v2/branding.rb +0 -1
  7. data/lib/auth0/api/v2/connections.rb +5 -2
  8. data/lib/auth0/api/v2/device_credentials.rb +3 -3
  9. data/lib/auth0/api/v2/logs.rb +2 -2
  10. data/lib/auth0/api/v2/organizations.rb +19 -3
  11. data/lib/auth0/api/v2/roles.rb +7 -3
  12. data/lib/auth0/mixins/httpproxy.rb +71 -33
  13. data/lib/auth0/mixins/initializer.rb +1 -0
  14. data/lib/auth0/version.rb +1 -1
  15. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connection/_filters/should_exclude_the_fields_indicated.yml +38 -26
  16. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connection/_filters/should_include_the_fields_indicated.yml +38 -24
  17. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connection/should_find_the_correct_connection.yml +38 -26
  18. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connections/_filters/should_include_previously-created_connection_when_filtered.yml +41 -21
  19. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connections/_filters/should_should_exclude_the_fields_indicated_from_filtered_results.yml +41 -21
  20. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connections/_filters/should_should_include_the_fields_indicated_from_filtered_results.yml +41 -21
  21. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connections/should_include_the_previously_created_connection.yml +41 -21
  22. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_connections/should_not_be_empty.yml +41 -21
  23. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_delete_connection/should_delete_the_connection.yml +45 -24
  24. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_delete_connection_user/should_delete_the_user_created.yml +75 -39
  25. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_update_connection/should_update_the_connection.yml +39 -28
  26. data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/create_test_connection.yml +37 -25
  27. data/spec/lib/auth0/api/v2/connections_spec.rb +1 -1
  28. data/spec/lib/auth0/api/v2/device_credentials_spec.rb +2 -2
  29. data/spec/lib/auth0/api/v2/organizations_spec.rb +31 -6
  30. data/spec/lib/auth0/api/v2/roles_spec.rb +5 -1
  31. data/spec/lib/auth0/mixins/httpproxy_spec.rb +216 -25
  32. data/spec/lib/auth0/mixins/initializer_spec.rb +7 -0
  33. data/spec/support/dummy_class_for_proxy.rb +1 -2
  34. metadata +32 -23
  35. data/.yardoc/checksums +0 -22
  36. data/.yardoc/complete +0 -0
  37. data/.yardoc/object_types +0 -0
  38. data/.yardoc/objects/root.dat +0 -0
  39. data/.yardoc/proxy_types +0 -0
@@ -12,54 +12,66 @@ http_interactions:
12
12
  Accept-Encoding:
13
13
  - gzip, deflate
14
14
  User-Agent:
15
- - Ruby/2.3.1
15
+ - rest-client/2.0.2 (darwin20.2.0 x86_64) ruby/2.7.2p137
16
16
  Content-Type:
17
17
  - application/json
18
18
  Auth0-Client:
19
- - eyJuYW1lIjoicnVieS1hdXRoMCIsInZlcnNpb24iOiI0LjUuMCJ9
19
+ - eyJuYW1lIjoicnVieS1hdXRoMCIsInZlcnNpb24iOiI1LjEuMiIsImVudiI6eyJydWJ5IjoiMi43LjIifX0=
20
20
  Authorization:
21
21
  - Bearer API_TOKEN
22
22
  Content-Length:
23
23
  - '53'
24
- Host:
25
- - auth0-sdk-tests.auth0.com
26
24
  response:
27
25
  status:
28
26
  code: 201
29
27
  message: Created
30
28
  headers:
31
29
  Date:
32
- - Fri, 05 Oct 2018 20:16:25 GMT
30
+ - Tue, 20 Jul 2021 02:06:03 GMT
33
31
  Content-Type:
34
32
  - application/json; charset=utf-8
35
33
  Transfer-Encoding:
36
34
  - chunked
37
35
  Connection:
38
36
  - keep-alive
39
- X-Ratelimit-Limit:
40
- - '10'
41
- X-Ratelimit-Remaining:
42
- - '9'
43
- X-Ratelimit-Reset:
44
- - '1538770587'
45
- Vary:
46
- - origin,accept-encoding
37
+ Cf-Ray:
38
+ - 6718a0c42c0a323a-LAX
47
39
  Cache-Control:
48
- - private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
40
+ - no-cache
49
41
  Content-Encoding:
50
42
  - gzip
51
43
  Strict-Transport-Security:
52
- - max-age=15724800
53
- X-Robots-Tag:
54
- - noindex, nofollow, nosnippet, noarchive
44
+ - max-age=31536000
45
+ Vary:
46
+ - origin,accept-encoding
47
+ Cf-Cache-Status:
48
+ - DYNAMIC
49
+ Expect-Ct:
50
+ - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
51
+ Ot-Baggage-Auth0-Request-Id:
52
+ - 6718a0c42c0a323a
53
+ Ot-Tracer-Sampled:
54
+ - 'true'
55
+ Ot-Tracer-Spanid:
56
+ - 672b1d28532dec55
57
+ Ot-Tracer-Traceid:
58
+ - 1552b04c1ec626a6
59
+ X-Content-Type-Options:
60
+ - nosniff
61
+ X-Ratelimit-Limit:
62
+ - '50'
63
+ X-Ratelimit-Remaining:
64
+ - '49'
65
+ X-Ratelimit-Reset:
66
+ - '1626746764'
67
+ Server:
68
+ - cloudflare
69
+ Alt-Svc:
70
+ - h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443";
71
+ ma=86400
55
72
  body:
56
73
  encoding: ASCII-8BIT
57
74
  string: !binary |-
58
- H4sIAAAAAAAAA3WPQUvEQAyF/0vOFRYRlB4V9iQii+hhWYbpNK0DM0lJMl3K
59
- 0v/u1EU9eUp4L3zv5QKxhxYCk3v+uJ8fH3Z7fc+H/d3wAg3wZJFJob1AHvw2
60
- fLA4I7QmBRsQtCLkkIRTcopmkUa9umsDk1c9s/SvnGJYaszI3FdsJ8XQDSwB
61
- 3SRsGLaYH6iaeMNxcTOKfuu3659aKb7Y565iyOfaBN5Q7YmJrpQbKd1iVaoH
62
- UV3P2Udy4deHdvBJawyS7xL2LqSIZLX08bQ95FPe9n+pp/ULPGRgtDMBAAA=
63
- http_version:
64
- recorded_at: Fri, 05 Oct 2018 20:16:25 GMT
65
- recorded_with: VCR 4.0.0
75
+ H4sIAAAAAAAAA3WPQUvEQAyF/0vOFUpPMke9LSgelAVlGaYzaR2YJiVJd7cs+9+duurNU0Je8r2XC+QEDiKTp/unXdudu3dtdw9v+2dogGfLTAruAtMQthKi5SOCM1mwAUFbhDyScCle0SzTqDf12sAcVE8s6YVLjmu1GZlTxapJMBxXf0TRagCua6CXxdAPLBH9LGwY7Vv6Yf3eVEpY7LOtGApTTQKvqPbIRLeDO1n61eqoLmT1iaeQycc/HdwQitbsSKEvmHwsGclq6I/D9lAo09b/Sz1cvwBFiD9BMwEAAA==
76
+ recorded_at: Tue, 20 Jul 2021 02:06:02 GMT
77
+ recorded_with: VCR 6.0.0
@@ -113,7 +113,7 @@ describe Auth0::Api::V2::Connections do
113
113
  context '.delete_connection_user' do
114
114
  it { expect(@instance).to respond_to(:delete_connection_user) }
115
115
  it 'is expected to call delete to /api/v2/connections/connectionId/users' do
116
- expect(@instance).to receive(:delete).with('/api/v2/connections/connectionId/users?email=email@test.com')
116
+ expect(@instance).to receive(:delete).with('/api/v2/connections/connectionId/users', email: 'email@test.com')
117
117
  @instance.delete_connection_user('connectionId', 'email@test.com')
118
118
  end
119
119
 
@@ -22,9 +22,9 @@ describe Auth0::Api::V2::DeviceCredentials do
22
22
  )
23
23
  expect { @instance.device_credentials(client_id) }.not_to raise_error
24
24
  end
25
- it 'is expect to raise an error when type is not one of \'public_key\', \'refresh_token\'' do
25
+ it 'is expect to raise an error when type is not one of \'public_key\', \'refresh_token\', \'rotating_refresh_token\'' do
26
26
  expect { @instance.device_credentials(client_id, type: 'invalid_type') }.to raise_error(
27
- 'Type must be one of \'public_key\', \'refresh_token\''
27
+ 'Type must be one of \'public_key\', \'refresh_token\', \'rotating_refresh_token\''
28
28
  )
29
29
  end
30
30
  end
@@ -20,6 +20,8 @@ describe Auth0::Api::V2::Organizations do
20
20
  '/api/v2/organizations',
21
21
  per_page: nil,
22
22
  page: nil,
23
+ from: nil,
24
+ take: nil,
23
25
  include_totals: nil
24
26
  )
25
27
  expect { @instance.organizations }.not_to raise_error
@@ -30,12 +32,16 @@ describe Auth0::Api::V2::Organizations do
30
32
  '/api/v2/organizations',
31
33
  per_page: 10,
32
34
  page: 1,
35
+ from: 'org_id',
36
+ take: 50,
33
37
  include_totals: true
34
38
  )
35
39
  expect do
36
40
  @instance.organizations(
37
41
  per_page: 10,
38
42
  page: 1,
43
+ from: 'org_id',
44
+ take: 50,
39
45
  include_totals: true
40
46
  )
41
47
  end.not_to raise_error
@@ -438,19 +444,38 @@ describe Auth0::Api::V2::Organizations do
438
444
  expect { @instance.get_organizations_members(nil) }.to raise_exception(Auth0::MissingOrganizationId)
439
445
  end
440
446
 
441
- it 'is expected to get invitations for an org' do
447
+ it 'is expected to get members for an org' do
442
448
  expect(@instance).to receive(:get).with(
443
- '/api/v2/organizations/org_id/members'
449
+ '/api/v2/organizations/org_id/members',
450
+ per_page: nil,
451
+ page: nil,
452
+ from: nil,
453
+ take: nil,
454
+ include_totals: nil
444
455
  )
445
- expect { @instance.get_organizations_members('org_id') }.not_to raise_error
456
+ expect do
457
+ @instance.get_organizations_members('org_id')
458
+ end.not_to raise_error
446
459
  end
447
460
 
448
- it 'is expected to get members for an org' do
461
+ it 'is expected to get /api/v2/organizations with custom parameters' do
449
462
  expect(@instance).to receive(:get).with(
450
- '/api/v2/organizations/org_id/members'
463
+ '/api/v2/organizations/org_id/members',
464
+ per_page: 10,
465
+ page: 1,
466
+ from: 'org_id',
467
+ take: 50,
468
+ include_totals: true
451
469
  )
452
470
  expect do
453
- @instance.get_organizations_members('org_id')
471
+ @instance.get_organizations_members(
472
+ 'org_id',
473
+ per_page: 10,
474
+ page: 1,
475
+ from: 'org_id',
476
+ take: 50,
477
+ include_totals: true
478
+ )
454
479
  end.not_to raise_error
455
480
  end
456
481
  end
@@ -152,6 +152,8 @@ describe Auth0::Api::V2::Roles do
152
152
  '/api/v2/roles/ROLE_ID/users',
153
153
  per_page: nil,
154
154
  page: nil,
155
+ from: nil,
156
+ take: nil,
155
157
  include_totals: nil
156
158
  )
157
159
  expect { @instance.get_role_users('ROLE_ID') }.not_to raise_error
@@ -162,10 +164,12 @@ describe Auth0::Api::V2::Roles do
162
164
  '/api/v2/roles/ROLE_ID/users',
163
165
  per_page: 30,
164
166
  page: 4,
167
+ from: 'org_id',
168
+ take: 50,
165
169
  include_totals: true
166
170
  )
167
171
  expect do
168
- @instance.get_role_users('ROLE_ID', per_page: 30, page: 4, include_totals: true)
172
+ @instance.get_role_users('ROLE_ID', per_page: 30, page: 4, from: 'org_id', take: 50, include_totals: true)
169
173
  end.not_to raise_error
170
174
  end
171
175
  end
@@ -5,6 +5,9 @@ describe Auth0::Mixins::HTTPProxy do
5
5
  before :each do
6
6
  dummy_instance = DummyClassForProxy.new
7
7
  dummy_instance.extend(Auth0::Mixins::HTTPProxy)
8
+ dummy_instance.base_uri = "https://auth0.com"
9
+ dummy_instance.retry_count = 0
10
+
8
11
  @instance = dummy_instance
9
12
  @exception = DummyClassForRestClient.new
10
13
  end
@@ -14,7 +17,7 @@ describe Auth0::Mixins::HTTPProxy do
14
17
  it { expect(@instance).to respond_to(http_method.to_sym) }
15
18
  it "should call send http #{http_method} method to path defined through HTTP" do
16
19
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
17
- url: '/test',
20
+ url: 'https://auth0.com/test',
18
21
  timeout: nil,
19
22
  headers: { params: {} },
20
23
  payload: nil)
@@ -24,7 +27,7 @@ describe Auth0::Mixins::HTTPProxy do
24
27
 
25
28
  it 'should not raise exception if data returned not in json format (should be fixed in v2)' do
26
29
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
27
- url: '/test',
30
+ url: 'https://auth0.com/test',
28
31
  timeout: nil,
29
32
  headers: { params: {} },
30
33
  payload: nil)
@@ -36,7 +39,7 @@ describe Auth0::Mixins::HTTPProxy do
36
39
  it "should raise Auth0::Unauthorized on send http #{http_method}
37
40
  method to path defined through HTTP when 401 status received" do
38
41
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
39
- url: '/test',
42
+ url: 'https://auth0.com/test',
40
43
  timeout: nil,
41
44
  headers: { params: {} },
42
45
  payload: nil)
@@ -47,7 +50,7 @@ describe Auth0::Mixins::HTTPProxy do
47
50
  it "should raise Auth0::NotFound on send http #{http_method} method
48
51
  to path defined through HTTP when 404 status received" do
49
52
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
50
- url: '/test',
53
+ url: 'https://auth0.com/test',
51
54
  timeout: nil,
52
55
  headers: { params: {} },
53
56
  payload: nil)
@@ -58,7 +61,7 @@ describe Auth0::Mixins::HTTPProxy do
58
61
  it "should raise Auth0::Unsupported on send http #{http_method} method
59
62
  to path defined through HTTP when 418 or other unknown status received" do
60
63
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
61
- url: '/test',
64
+ url: 'https://auth0.com/test',
62
65
  timeout: nil,
63
66
  headers: { params: {} },
64
67
  payload: nil)
@@ -69,7 +72,7 @@ describe Auth0::Mixins::HTTPProxy do
69
72
  it "should raise Auth0::RequestTimeout on send http #{http_method} method
70
73
  to path defined through HTTP when RestClient::RequestTimeout received" do
71
74
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
72
- url: '/test',
75
+ url: 'https://auth0.com/test',
73
76
  timeout: nil,
74
77
  headers: { params: {} },
75
78
  payload: nil)
@@ -81,7 +84,7 @@ describe Auth0::Mixins::HTTPProxy do
81
84
  to path defined through HTTP when 400 status received" do
82
85
  @exception.response = StubResponse.new({}, false, 400)
83
86
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
84
- url: '/test',
87
+ url: 'https://auth0.com/test',
85
88
  timeout: nil,
86
89
  headers: { params: {} },
87
90
  payload: nil)
@@ -93,7 +96,7 @@ describe Auth0::Mixins::HTTPProxy do
93
96
  to path defined through HTTP when 403" do
94
97
  @exception.response = StubResponse.new({}, false, 403)
95
98
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
96
- url: '/test',
99
+ url: 'https://auth0.com/test',
97
100
  timeout: nil,
98
101
  headers: { params: {} },
99
102
  payload: nil)
@@ -110,7 +113,7 @@ describe Auth0::Mixins::HTTPProxy do
110
113
  }
111
114
  @exception.response = StubResponse.new({}, false, 429, headers)
112
115
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
113
- url: '/test',
116
+ url: 'https://auth0.com/test',
114
117
  timeout: nil,
115
118
  headers: { params: {} },
116
119
  payload: nil)
@@ -133,7 +136,7 @@ describe Auth0::Mixins::HTTPProxy do
133
136
  to path defined through HTTP when 500 received" do
134
137
  @exception.response = StubResponse.new({}, false, 500)
135
138
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
136
- url: '/test',
139
+ url: 'https://auth0.com/test',
137
140
  timeout: nil,
138
141
  headers: { params: {} },
139
142
  payload: nil)
@@ -141,14 +144,108 @@ describe Auth0::Mixins::HTTPProxy do
141
144
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::ServerError)
142
145
  end
143
146
 
144
- it 'should escape path with Addressable::URI.escape' do
147
+ it 'should normalize path with Addressable::URI' do
145
148
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
146
- url: '/te%20st',
149
+ url: 'https://auth0.com/te%20st%23test',
147
150
  timeout: nil,
148
151
  headers: { params: {} },
149
152
  payload: nil)
150
153
  .and_return(StubResponse.new({}, true, 200))
151
- expect { @instance.send(http_method, '/te st') }.not_to raise_error
154
+ expect { @instance.send(http_method, '/te st#test') }.not_to raise_error
155
+ end
156
+
157
+ context "when status 429 is recieved on send http #{http_method} method" do
158
+ it "should retry 3 times when retry_count is not set" do
159
+ retry_instance = DummyClassForProxy.new
160
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
161
+ retry_instance.base_uri = "https://auth0.com"
162
+
163
+ @exception.response = StubResponse.new({}, false, 429)
164
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
165
+ url: 'https://auth0.com/test',
166
+ timeout: nil,
167
+ headers: { params: {} },
168
+ payload: nil)
169
+ .and_raise(@exception)
170
+ expect(RestClient::Request).to receive(:execute).exactly(4).times
171
+
172
+ expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
173
+ expect(error).to be_a(Auth0::RateLimitEncountered)
174
+ }
175
+ end
176
+
177
+ it "should retry 2 times when retry_count is set to 2" do
178
+ retry_instance = DummyClassForProxy.new
179
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
180
+ retry_instance.base_uri = "https://auth0.com"
181
+ retry_instance.retry_count = 2
182
+
183
+ @exception.response = StubResponse.new({}, false, 429)
184
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
185
+ url: 'https://auth0.com/test',
186
+ timeout: nil,
187
+ headers: { params: {} },
188
+ payload: nil)
189
+ .and_raise(@exception)
190
+ expect(RestClient::Request).to receive(:execute).exactly(3).times
191
+
192
+ expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
193
+ expect(error).to be_a(Auth0::RateLimitEncountered)
194
+ }
195
+ end
196
+
197
+ it "should not retry when retry_count is set to 0" do
198
+ retry_instance = DummyClassForProxy.new
199
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
200
+ retry_instance.base_uri = "https://auth0.com"
201
+ retry_instance.retry_count = 0
202
+
203
+ @exception.response = StubResponse.new({}, false, 429)
204
+
205
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
206
+ url: 'https://auth0.com/test',
207
+ timeout: nil,
208
+ headers: { params: {} },
209
+ payload: nil)
210
+ .and_raise(@exception)
211
+
212
+ expect(RestClient::Request).to receive(:execute).exactly(1).times
213
+ expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
214
+ expect(error).to be_a(Auth0::RateLimitEncountered)
215
+ }
216
+ end
217
+
218
+ it "should have have random retry times grow with jitter backoff" do
219
+ retry_instance = DummyClassForProxy.new
220
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
221
+ retry_instance.base_uri = "https://auth0.com"
222
+ retry_instance.retry_count = 2
223
+ time_entries = []
224
+ @time_start
225
+
226
+ @exception.response = StubResponse.new({}, false, 429)
227
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
228
+ url: 'https://auth0.com/test',
229
+ timeout: nil,
230
+ headers: { params: {} },
231
+ payload: nil) do
232
+
233
+ time_entries.push(Time.now.to_f - @time_start.to_f)
234
+ @time_start = Time.now.to_f # restart the clock
235
+ raise @exception
236
+ end
237
+
238
+ @time_start = Time.now.to_f #start the clock
239
+ retry_instance.send(http_method, '/test') rescue nil
240
+ time_entries_first_set = time_entries.shift(time_entries.length)
241
+
242
+ retry_instance.send(http_method, '/test') rescue nil
243
+ time_entries.each_with_index do |entry, index|
244
+ if index > 0 #skip the first request
245
+ expect(entry != time_entries_first_set[index])
246
+ end
247
+ end
248
+ end
152
249
  end
153
250
  end
154
251
  end
@@ -158,7 +255,7 @@ describe Auth0::Mixins::HTTPProxy do
158
255
  it { expect(@instance).to respond_to(http_method.to_sym) }
159
256
  it "should call send http #{http_method} method to path defined through HTTP" do
160
257
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
161
- url: '/test',
258
+ url: 'https://auth0.com/test',
162
259
  timeout: nil,
163
260
  headers: nil,
164
261
  payload: '{}')
@@ -168,7 +265,7 @@ describe Auth0::Mixins::HTTPProxy do
168
265
 
169
266
  it 'should not raise exception if data returned not in json format (should be fixed in v2)' do
170
267
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
171
- url: '/test',
268
+ url: 'https://auth0.com/test',
172
269
  timeout: nil,
173
270
  headers: nil,
174
271
  payload: '{}')
@@ -181,7 +278,7 @@ describe Auth0::Mixins::HTTPProxy do
181
278
  to path defined through HTTP when 401 status received" do
182
279
  @exception.response = StubResponse.new({}, false, 401)
183
280
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
184
- url: '/test',
281
+ url: 'https://auth0.com/test',
185
282
  timeout: nil,
186
283
  headers: nil,
187
284
  payload: '{}')
@@ -198,7 +295,7 @@ describe Auth0::Mixins::HTTPProxy do
198
295
  }
199
296
  @exception.response = StubResponse.new({}, false, 429,headers)
200
297
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
201
- url: '/test',
298
+ url: 'https://auth0.com/test',
202
299
  timeout: nil,
203
300
  headers: nil,
204
301
  payload: '{}')
@@ -221,7 +318,7 @@ describe Auth0::Mixins::HTTPProxy do
221
318
  to path defined through HTTP when 404 status received" do
222
319
  @exception.response = StubResponse.new({}, false, 404)
223
320
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
224
- url: '/test',
321
+ url: 'https://auth0.com/test',
225
322
  timeout: nil,
226
323
  headers: nil,
227
324
  payload: '{}')
@@ -233,7 +330,7 @@ describe Auth0::Mixins::HTTPProxy do
233
330
  to path defined through HTTP when 418 or other unknown status received" do
234
331
  @exception.response = StubResponse.new({}, false, 418)
235
332
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
236
- url: '/test',
333
+ url: 'https://auth0.com/test',
237
334
  timeout: nil,
238
335
  headers: nil,
239
336
  payload: '{}')
@@ -244,7 +341,7 @@ describe Auth0::Mixins::HTTPProxy do
244
341
  it "should raise Auth0::RequestTimeout on send http #{http_method} method
245
342
  to path defined through HTTP when RestClient::RequestTimeout received" do
246
343
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
247
- url: '/test',
344
+ url: 'https://auth0.com/test',
248
345
  timeout: nil,
249
346
  headers: nil,
250
347
  payload: '{}')
@@ -256,7 +353,7 @@ describe Auth0::Mixins::HTTPProxy do
256
353
  to path defined through HTTP when 400 status received" do
257
354
  @exception.response = StubResponse.new({}, false, 400)
258
355
  allow(RestClient::Request).to receive(:execute).with(method: http_method,
259
- url: '/test',
356
+ url: 'https://auth0.com/test',
260
357
  timeout: nil,
261
358
  headers: nil,
262
359
  payload: '{}')
@@ -267,7 +364,7 @@ describe Auth0::Mixins::HTTPProxy do
267
364
  it "should raise Auth0::ServerError on send http #{http_method} method
268
365
  to path defined through HTTP when 500 received" do
269
366
  @exception.response = StubResponse.new({}, false, 500)
270
- allow(RestClient::Request).to receive(:execute).with(method: http_method, url: '/test',
367
+ allow(RestClient::Request).to receive(:execute).with(method: http_method, url: 'https://auth0.com/test',
271
368
  timeout: nil,
272
369
  headers: nil,
273
370
  payload: '{}')
@@ -275,9 +372,9 @@ describe Auth0::Mixins::HTTPProxy do
275
372
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::ServerError)
276
373
  end
277
374
 
278
- it 'should escape path with Addressable::URI.escape' do
375
+ it 'should normalize path with Addressable::URI' do
279
376
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
280
- url: '/te%20st',
377
+ url: 'https://auth0.com/te%20st',
281
378
  timeout: nil,
282
379
  headers: nil,
283
380
  payload: '{}')
@@ -292,13 +389,107 @@ describe Auth0::Mixins::HTTPProxy do
292
389
  3241312' on property id (The user_id of the user to retrieve).",
293
390
  'errorCode' => 'invalid_uri')
294
391
  expect(RestClient::Request).to receive(:execute).with(method: http_method,
295
- url: '/test',
392
+ url: 'https://auth0.com/test',
296
393
  timeout: nil,
297
394
  headers: nil,
298
395
  payload: '{}')
299
396
  .and_return(StubResponse.new(res, true, 404))
300
397
  expect { @instance.send(http_method, '/test') }.to raise_error(Auth0::NotFound, res)
301
398
  end
399
+
400
+ context "when status 429 is recieved on send http #{http_method} method" do
401
+ it "should retry 3 times when retry_count is not set" do
402
+ retry_instance = DummyClassForProxy.new
403
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
404
+ retry_instance.base_uri = "https://auth0.com"
405
+
406
+ @exception.response = StubResponse.new({}, false, 429)
407
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
408
+ url: 'https://auth0.com/test',
409
+ timeout: nil,
410
+ headers: nil,
411
+ payload: '{}')
412
+ .and_raise(@exception)
413
+ expect(RestClient::Request).to receive(:execute).exactly(4).times
414
+
415
+ expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
416
+ expect(error).to be_a(Auth0::RateLimitEncountered)
417
+ }
418
+ end
419
+
420
+ it "should retry 2 times when retry_count is set to 2" do
421
+ retry_instance = DummyClassForProxy.new
422
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
423
+ retry_instance.base_uri = "https://auth0.com"
424
+ retry_instance.retry_count = 2
425
+
426
+ @exception.response = StubResponse.new({}, false, 429)
427
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
428
+ url: 'https://auth0.com/test',
429
+ timeout: nil,
430
+ headers: nil,
431
+ payload: '{}')
432
+ .and_raise(@exception)
433
+ expect(RestClient::Request).to receive(:execute).exactly(3).times
434
+
435
+ expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
436
+ expect(error).to be_a(Auth0::RateLimitEncountered)
437
+ }
438
+ end
439
+
440
+ it "should not retry when retry_count is set to 0" do
441
+ retry_instance = DummyClassForProxy.new
442
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
443
+ retry_instance.base_uri = "https://auth0.com"
444
+ retry_instance.retry_count = 0
445
+
446
+ @exception.response = StubResponse.new({}, false, 429)
447
+
448
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
449
+ url: 'https://auth0.com/test',
450
+ timeout: nil,
451
+ headers: nil,
452
+ payload: '{}')
453
+ .and_raise(@exception)
454
+
455
+ expect(RestClient::Request).to receive(:execute).exactly(1).times
456
+ expect { retry_instance.send(http_method, '/test') }.to raise_error { |error|
457
+ expect(error).to be_a(Auth0::RateLimitEncountered)
458
+ }
459
+ end
460
+
461
+ it "should have have random retry times grow with jitter backoff" do
462
+ retry_instance = DummyClassForProxy.new
463
+ retry_instance.extend(Auth0::Mixins::HTTPProxy)
464
+ retry_instance.base_uri = "https://auth0.com"
465
+ retry_instance.retry_count = 2
466
+ time_entries = []
467
+ @time_start
468
+
469
+ @exception.response = StubResponse.new({}, false, 429)
470
+ allow(RestClient::Request).to receive(:execute).with(method: http_method,
471
+ url: 'https://auth0.com/test',
472
+ timeout: nil,
473
+ headers: nil,
474
+ payload: '{}') do
475
+
476
+ time_entries.push(Time.now.to_f - @time_start.to_f)
477
+ @time_start = Time.now.to_f # restart the clock
478
+ raise @exception
479
+ end
480
+
481
+ @time_start = Time.now.to_f #start the clock
482
+ retry_instance.send(http_method, '/test') rescue nil
483
+ time_entries_first_set = time_entries.shift(time_entries.length)
484
+
485
+ retry_instance.send(http_method, '/test') rescue nil
486
+ time_entries.each_with_index do |entry, index|
487
+ if index > 0 #skip the first request
488
+ expect(entry != time_entries_first_set[index])
489
+ end
490
+ end
491
+ end
492
+ end
302
493
  end
303
494
  end
304
495
  end