workos 0.9.2 → 0.10.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 (27) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/Gemfile.lock +2 -2
  4. data/README.md +15 -15
  5. data/docs/WorkOS/SSO.html +235 -235
  6. data/docs/file.README.html +20 -20
  7. data/lib/workos/client.rb +22 -1
  8. data/lib/workos/passwordless.rb +0 -2
  9. data/lib/workos/portal.rb +0 -6
  10. data/lib/workos/profile.rb +2 -2
  11. data/lib/workos/sso.rb +119 -13
  12. data/lib/workos/version.rb +1 -1
  13. data/spec/lib/workos/sso_spec.rb +198 -7
  14. data/spec/support/fixtures/vcr_cassettes/audit_trail/get_events.yml +2 -2
  15. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories.yml +1 -1
  16. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories_with_domain_param.yml +1 -1
  17. data/spec/support/fixtures/vcr_cassettes/sso/delete_connection_with_invalid_id.yml +72 -0
  18. data/spec/support/fixtures/vcr_cassettes/sso/delete_connection_with_valid_id.yml +70 -0
  19. data/spec/support/fixtures/vcr_cassettes/sso/get_connection_with_invalid_id.yml +72 -0
  20. data/spec/support/fixtures/vcr_cassettes/sso/get_connection_with_valid_id.yml +74 -0
  21. data/spec/support/fixtures/vcr_cassettes/sso/list_connections.yml +72 -0
  22. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_after_param.yml +72 -0
  23. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_before_param.yml +73 -0
  24. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_connection_type_param.yml +72 -0
  25. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_domain_param.yml +72 -0
  26. data/spec/support/fixtures/vcr_cassettes/sso/list_connections_with_limit_param.yml +72 -0
  27. metadata +23 -3
@@ -2,5 +2,5 @@
2
2
  # typed: strong
3
3
 
4
4
  module WorkOS
5
- VERSION = '0.9.2'
5
+ VERSION = '0.10.0'
6
6
  end
@@ -9,7 +9,7 @@ describe WorkOS::SSO do
9
9
  let(:args) do
10
10
  {
11
11
  domain: 'foo.com',
12
- project_id: 'workos-proj-123',
12
+ client_id: 'workos-proj-123',
13
13
  redirect_uri: 'foo.com/auth/callback',
14
14
  state: {
15
15
  next_page: '/dashboard/edit',
@@ -43,7 +43,7 @@ describe WorkOS::SSO do
43
43
  let(:args) do
44
44
  {
45
45
  provider: 'GoogleOAuth',
46
- project_id: 'workos-proj-123',
46
+ client_id: 'workos-proj-123',
47
47
  redirect_uri: 'foo.com/auth/callback',
48
48
  state: {
49
49
  next_page: '/dashboard/edit',
@@ -76,7 +76,7 @@ describe WorkOS::SSO do
76
76
  context 'with neither domain or provider' do
77
77
  let(:args) do
78
78
  {
79
- project_id: 'workos-proj-123',
79
+ client_id: 'workos-proj-123',
80
80
  redirect_uri: 'foo.com/auth/callback',
81
81
  state: {
82
82
  next_page: '/dashboard/edit',
@@ -97,7 +97,7 @@ describe WorkOS::SSO do
97
97
  let(:args) do
98
98
  {
99
99
  provider: 'Okta',
100
- project_id: 'workos-proj-123',
100
+ client_id: 'workos-proj-123',
101
101
  redirect_uri: 'foo.com/auth/callback',
102
102
  state: {
103
103
  next_page: '/dashboard/edit',
@@ -113,6 +113,49 @@ describe WorkOS::SSO do
113
113
  )
114
114
  end
115
115
  end
116
+
117
+ context 'passing the project_id' do
118
+ let(:args) do
119
+ {
120
+ domain: 'foo.com',
121
+ project_id: 'workos-proj-123',
122
+ redirect_uri: 'foo.com/auth/callback',
123
+ state: {
124
+ next_page: '/dashboard/edit',
125
+ }.to_s,
126
+ }
127
+ end
128
+ it 'raises a deprecation warning' do
129
+ expect do
130
+ described_class.authorization_url(**args)
131
+ end.to output(
132
+ "[DEPRECATION] `project_id` is deprecated.
133
+ Please use `client_id` instead.\n",
134
+ ).to_stderr
135
+ end
136
+
137
+ it 'returns a valid URL' do
138
+ authorization_url = described_class.authorization_url(**args)
139
+
140
+ expect(URI.parse(authorization_url)).to be_a URI
141
+ end
142
+
143
+ it 'returns the expected hostname' do
144
+ authorization_url = described_class.authorization_url(**args)
145
+
146
+ expect(URI.parse(authorization_url).host).to eq(WorkOS::API_HOSTNAME)
147
+ end
148
+
149
+ it 'returns the expected query string' do
150
+ authorization_url = described_class.authorization_url(**args)
151
+
152
+ expect(URI.parse(authorization_url).query).to eq(
153
+ 'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
154
+ '&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
155
+ 'edit%22%7D&domain=foo.com',
156
+ )
157
+ end
158
+ end
116
159
  end
117
160
 
118
161
  describe '.profile' do
@@ -123,13 +166,13 @@ describe WorkOS::SSO do
123
166
  let(:args) do
124
167
  {
125
168
  code: SecureRandom.hex(10),
126
- project_id: 'workos-proj-123',
169
+ client_id: 'workos-proj-123',
127
170
  }
128
171
  end
129
172
 
130
173
  let(:request_body) do
131
174
  {
132
- client_id: args[:project_id],
175
+ client_id: args[:client_id],
133
176
  client_secret: WorkOS.key,
134
177
  code: args[:code],
135
178
  grant_type: 'authorization_code',
@@ -278,7 +321,7 @@ describe WorkOS::SSO do
278
321
  end
279
322
 
280
323
  let(:token) { 'draft_conn_id' }
281
- let(:project_id) { 'proj_0239u590h' }
324
+ let(:client_id) { 'proj_0239u590h' }
282
325
 
283
326
  context 'with a valid request' do
284
327
  before do
@@ -312,4 +355,152 @@ describe WorkOS::SSO do
312
355
  end
313
356
  end
314
357
  end
358
+
359
+ describe '.list_connections' do
360
+ before(:all) do
361
+ WorkOS.key = 'key'
362
+ end
363
+
364
+ after(:all) do
365
+ WorkOS.key = nil
366
+ end
367
+
368
+ context 'with no options' do
369
+ it 'returns connections' do
370
+ VCR.use_cassette('sso/list_connections') do
371
+ connections = WorkOS::SSO.list_connections
372
+ expect(connections.size).to eq(1)
373
+ end
374
+ end
375
+ end
376
+
377
+ context 'with connection_type option' do
378
+ it 'returns connections' do
379
+ VCR.use_cassette('sso/list_connections_with_connection_type_param') do
380
+ connections = WorkOS::SSO.list_connections(
381
+ connection_type: 'OktaSAML',
382
+ )
383
+ expect(connections.first['connection_type']).to eq('OktaSAML')
384
+ end
385
+ end
386
+ end
387
+
388
+ context 'with domain option' do
389
+ it 'returns connections' do
390
+ VCR.use_cassette('sso/list_connections_with_domain_param') do
391
+ connections = WorkOS::SSO.list_connections(
392
+ domain: 'foo-corp.com',
393
+ )
394
+ domains = connections.first['domains']
395
+ expect(domains.first['domain']).to eq('foo-corp.com')
396
+ end
397
+ end
398
+ end
399
+
400
+ context 'with limit option' do
401
+ it 'returns connections' do
402
+ VCR.use_cassette('sso/list_connections_with_limit_param') do
403
+ connections = WorkOS::SSO.list_connections(
404
+ limit: 1,
405
+ )
406
+ expect(connections.size).to eq(1)
407
+ end
408
+ end
409
+ end
410
+
411
+ context 'with before option' do
412
+ it 'returns connections' do
413
+ VCR.use_cassette('sso/list_connections_with_before_param') do
414
+ connections = WorkOS::SSO.list_connections(
415
+ before: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
416
+ )
417
+ expect(connections.size).to eq(1)
418
+ end
419
+ end
420
+ end
421
+
422
+ context 'with after option' do
423
+ it 'returns connections' do
424
+ VCR.use_cassette('sso/list_connections_with_after_param') do
425
+ connections = WorkOS::SSO.list_connections(
426
+ after: 'conn_01EQKPMQAPV02H270HKVNS4CTA',
427
+ )
428
+ expect(connections.size).to eq(1)
429
+ end
430
+ end
431
+ end
432
+ end
433
+
434
+ describe '.get_connection' do
435
+ before(:all) do
436
+ WorkOS.key = 'key'
437
+ end
438
+
439
+ after(:all) do
440
+ WorkOS.key = nil
441
+ end
442
+
443
+ context 'with a valid id' do
444
+ it 'gets the connection details' do
445
+ VCR.use_cassette('sso/get_connection_with_valid_id') do
446
+ connection = WorkOS::SSO.get_connection(
447
+ id: 'conn_01EX00NB050H354WKGC7990AR2',
448
+ )
449
+
450
+ expect(connection.id).to eq('conn_01EX00NB050H354WKGC7990AR2')
451
+ expect(connection.connection_type).to eq('OktaSAML')
452
+ expect(connection.name).to eq('Foo Corp')
453
+ expect(connection.domains.first[:domain]).to eq('foo-corp.com')
454
+ end
455
+ end
456
+ end
457
+
458
+ context 'with an invalid id' do
459
+ it 'raises an error' do
460
+ VCR.use_cassette('sso/get_connection_with_invalid_id') do
461
+ expect do
462
+ WorkOS::SSO.get_connection(id: 'invalid')
463
+ end.to raise_error(
464
+ WorkOS::APIError,
465
+ 'Status 404, Not Found - request ID: ',
466
+ )
467
+ end
468
+ end
469
+ end
470
+ end
471
+
472
+ describe '.delete_connection' do
473
+ before(:all) do
474
+ WorkOS.key = 'key'
475
+ end
476
+
477
+ after(:all) do
478
+ WorkOS.key = nil
479
+ end
480
+
481
+ context 'with a valid id' do
482
+ it 'returns true' do
483
+ VCR.use_cassette('sso/delete_connection_with_valid_id') do
484
+ response = WorkOS::SSO.delete_connection(
485
+ id: 'conn_01EX55FRVN1V2PCA9YWTMZQMMQ',
486
+ )
487
+
488
+ expect(response).to be(true)
489
+ end
490
+ end
491
+ end
492
+
493
+ context 'with an invalid id' do
494
+ it 'returns false' do
495
+ VCR.use_cassette('sso/delete_connection_with_invalid_id') do
496
+ expect do
497
+ WorkOS::SSO.delete_connection(id: 'invalid')
498
+ end.to raise_error(
499
+ WorkOS::APIError,
500
+ 'Status 404, Not Found - request ID: ',
501
+ )
502
+ end
503
+ end
504
+ end
505
+ end
315
506
  end
@@ -54,8 +54,8 @@ http_interactions:
54
54
  encoding: ASCII-8BIT
55
55
  string:
56
56
  '{"data":[{"object":"event","id":"evt_01EEJM9Q9SMC3W2SZDKA5VJ8XQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPHAYX46BBZKGK3BGQXJ","metadata":{"description":"User
57
- viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.384Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","project_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}},{"object":"event","id":"evt_01EEJM9Q7GMR1VGT6VXN2N2JJQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPGM8KFT9VBQHJMV8YZB","metadata":{"description":"User
58
- viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.360Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","project_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}}],"listMetadata":{"before":"evt_01EEJKZDAR6G4JHFQT4R3KSZDQ","after":null}}'
57
+ viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.384Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","client_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}},{"object":"event","id":"evt_01EEJM9Q7GMR1VGT6VXN2N2JJQ","group":"workos.com","location":"::1","latitude":null,"longitude":null,"type":"r","actor_name":"foo@example.com","actor_id":"user_01EEG9P7A1DA9VY9CX7GT47RPF","target_name":"api_key_query","target_id":"key_01EEG9MPGM8KFT9VBQHJMV8YZB","metadata":{"description":"User
58
+ viewed API key.","x_request_id":""},"occurred_at":"2020-07-31T14:27:00.360Z","action":{"object":"event_action","id":"evt_action_01EEGQXWAHB065P5JD0QDAAGDC","name":"user.viewed_api_key","client_id":"project_01DZB0E7HQMA6G85PQNHQJMZD0"}}],"listMetadata":{"before":"evt_01EEJKZDAR6G4JHFQT4R3KSZDQ","after":null}}'
59
59
  http_version:
60
60
  recorded_at: Fri, 31 Jul 2020 14:41:12 GMT
61
61
  recorded_with: VCR 5.0.0
@@ -56,7 +56,7 @@ http_interactions:
56
56
  - 1.1 vegur
57
57
  body:
58
58
  encoding: ASCII-8BIT
59
- string: '{"object":"list","listMetadata":{"before":"directory_edp_01E44H95QPBGZ6A4D89VYZ0WX1","after":null},"data":[{"object":"directory","id":"directory_edp_01E64QQVQTCB0DECJ9CFNXEWDW","external_key":"lA3gS1kCZMCkk82E","state":"linked","type":"gsuite directory","name":"Foo Corp","bearer_token":null,"project_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
59
+ string: '{"object":"list","listMetadata":{"before":"directory_edp_01E44H95QPBGZ6A4D89VYZ0WX1","after":null},"data":[{"object":"directory","id":"directory_edp_01E64QQVQTCB0DECJ9CFNXEWDW","external_key":"lA3gS1kCZMCkk82E","state":"linked","type":"gsuite directory","name":"Foo Corp","bearer_token":null,"client_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
60
60
  http_version:
61
61
  recorded_at: Thu, 30 Apr 2020 03:11:45 GMT
62
62
  recorded_with: VCR 5.0.0
@@ -57,7 +57,7 @@ http_interactions:
57
57
  body:
58
58
  encoding: UTF-8
59
59
  string: '{"object":"list","listMetadata":{"before":null,"after":null},"data":[{"object":"directory","id":"directory_edp_01E64QQVQTCB0DECJ9CFNXEWDW","external_key":"lA3gS1kCZMCkk82E","state":"linked","type":"gsuite
60
- directory","name":"Foo Corp","bearer_token":null,"project_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
60
+ directory","name":"Foo Corp","bearer_token":null,"client_id":"project_01DFYCG8RCB1DB6DKFTGXF4Q9F","domain":"foo-corp.com"}]}'
61
61
  http_version:
62
62
  recorded_at: Thu, 30 Apr 2020 03:42:20 GMT
63
63
  recorded_with: VCR 5.0.0
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: https://api.workos.com/connections/invalid
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ User-Agent:
17
+ - WorkOS; ruby/2.7.1; x86_64-darwin19; v0.10.0
18
+ Authorization:
19
+ - Bearer <API_KEY>
20
+ response:
21
+ status:
22
+ code: 404
23
+ message: Not Found
24
+ headers:
25
+ Server:
26
+ - Cowboy
27
+ Connection:
28
+ - keep-alive
29
+ Vary:
30
+ - Origin, Accept-Encoding
31
+ Access-Control-Allow-Credentials:
32
+ - 'true'
33
+ Content-Security-Policy:
34
+ - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self''
35
+ https: data:;frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src
36
+ ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests'
37
+ X-Dns-Prefetch-Control:
38
+ - 'off'
39
+ Expect-Ct:
40
+ - max-age=0
41
+ X-Frame-Options:
42
+ - SAMEORIGIN
43
+ Strict-Transport-Security:
44
+ - max-age=15552000; includeSubDomains
45
+ X-Download-Options:
46
+ - noopen
47
+ X-Content-Type-Options:
48
+ - nosniff
49
+ X-Permitted-Cross-Domain-Policies:
50
+ - none
51
+ Referrer-Policy:
52
+ - no-referrer
53
+ X-Xss-Protection:
54
+ - '0'
55
+ X-Request-Id:
56
+ -
57
+ Content-Type:
58
+ - application/json; charset=utf-8
59
+ Content-Length:
60
+ - '23'
61
+ Etag:
62
+ - W/"17-SuRA/yvUWUo8rK6x7dKURLeBo+0"
63
+ Date:
64
+ - Thu, 04 Feb 2021 17:20:08 GMT
65
+ Via:
66
+ - 1.1 vegur
67
+ body:
68
+ encoding: UTF-8
69
+ string: '{"message":"Not Found"}'
70
+ http_version:
71
+ recorded_at: Thu, 04 Feb 2021 17:20:08 GMT
72
+ recorded_with: VCR 5.0.0
@@ -0,0 +1,70 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: delete
5
+ uri: https://api.workos.com/connections/conn_01EX55FRVN1V2PCA9YWTMZQMMQ
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ User-Agent:
17
+ - WorkOS; ruby/2.7.1; x86_64-darwin19; v0.10.0
18
+ Authorization:
19
+ - Bearer <API_KEY>
20
+ response:
21
+ status:
22
+ code: 204
23
+ message: No Content
24
+ headers:
25
+ Server:
26
+ - Cowboy
27
+ Content-Length:
28
+ - '0'
29
+ Connection:
30
+ - keep-alive
31
+ Vary:
32
+ - Origin
33
+ Access-Control-Allow-Credentials:
34
+ - 'true'
35
+ Content-Security-Policy:
36
+ - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self''
37
+ https: data:;frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src
38
+ ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests'
39
+ X-Dns-Prefetch-Control:
40
+ - 'off'
41
+ Expect-Ct:
42
+ - max-age=0
43
+ X-Frame-Options:
44
+ - SAMEORIGIN
45
+ Strict-Transport-Security:
46
+ - max-age=15552000; includeSubDomains
47
+ X-Download-Options:
48
+ - noopen
49
+ X-Content-Type-Options:
50
+ - nosniff
51
+ X-Permitted-Cross-Domain-Policies:
52
+ - none
53
+ Referrer-Policy:
54
+ - no-referrer
55
+ X-Xss-Protection:
56
+ - '0'
57
+ X-Request-Id:
58
+ -
59
+ Etag:
60
+ - W/"a-bAsFyilMr4Ra1hIU5PyoyFRunpI"
61
+ Date:
62
+ - Thu, 04 Feb 2021 17:20:08 GMT
63
+ Via:
64
+ - 1.1 vegur
65
+ body:
66
+ encoding: UTF-8
67
+ string: ''
68
+ http_version:
69
+ recorded_at: Thu, 04 Feb 2021 17:20:08 GMT
70
+ recorded_with: VCR 5.0.0
@@ -0,0 +1,72 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.workos.com/connections/invalid
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ Accept:
15
+ - "*/*"
16
+ User-Agent:
17
+ - WorkOS; ruby/2.7.1; x86_64-darwin19; v0.10.0
18
+ Authorization:
19
+ - Bearer <API_KEY>
20
+ response:
21
+ status:
22
+ code: 404
23
+ message: Not Found
24
+ headers:
25
+ Server:
26
+ - Cowboy
27
+ Connection:
28
+ - keep-alive
29
+ Vary:
30
+ - Origin, Accept-Encoding
31
+ Access-Control-Allow-Credentials:
32
+ - 'true'
33
+ Content-Security-Policy:
34
+ - 'default-src ''self'';base-uri ''self'';block-all-mixed-content;font-src ''self''
35
+ https: data:;frame-ancestors ''self'';img-src ''self'' data:;object-src ''none'';script-src
36
+ ''self'';script-src-attr ''none'';style-src ''self'' https: ''unsafe-inline'';upgrade-insecure-requests'
37
+ X-Dns-Prefetch-Control:
38
+ - 'off'
39
+ Expect-Ct:
40
+ - max-age=0
41
+ X-Frame-Options:
42
+ - SAMEORIGIN
43
+ Strict-Transport-Security:
44
+ - max-age=15552000; includeSubDomains
45
+ X-Download-Options:
46
+ - noopen
47
+ X-Content-Type-Options:
48
+ - nosniff
49
+ X-Permitted-Cross-Domain-Policies:
50
+ - none
51
+ Referrer-Policy:
52
+ - no-referrer
53
+ X-Xss-Protection:
54
+ - '0'
55
+ X-Request-Id:
56
+ -
57
+ Content-Type:
58
+ - application/json; charset=utf-8
59
+ Content-Length:
60
+ - '23'
61
+ Etag:
62
+ - W/"17-SuRA/yvUWUo8rK6x7dKURLeBo+0"
63
+ Date:
64
+ - Fri, 29 Jan 2021 15:36:23 GMT
65
+ Via:
66
+ - 1.1 vegur
67
+ body:
68
+ encoding: UTF-8
69
+ string: '{"message":"Not Found"}'
70
+ http_version:
71
+ recorded_at: Fri, 29 Jan 2021 15:36:23 GMT
72
+ recorded_with: VCR 5.0.0