auth0 5.1.2 → 5.5.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.
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