onfido 1.0.0 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gem-push.yml +31 -0
  3. data/.github/workflows/ruby.yml +25 -0
  4. data/.rubocop.yml +5 -49
  5. data/.travis.yml +3 -10
  6. data/CHANGELOG.md +27 -0
  7. data/Gemfile +2 -0
  8. data/README.md +44 -156
  9. data/lib/onfido.rb +4 -3
  10. data/lib/onfido/api.rb +21 -11
  11. data/lib/onfido/errors/connection_error.rb +2 -0
  12. data/lib/onfido/errors/onfido_error.rb +2 -0
  13. data/lib/onfido/errors/request_error.rb +2 -0
  14. data/lib/onfido/errors/server_error.rb +2 -0
  15. data/lib/onfido/options.rb +38 -0
  16. data/lib/onfido/resource.rb +48 -58
  17. data/lib/onfido/resources/address.rb +3 -4
  18. data/lib/onfido/resources/applicant.rb +2 -0
  19. data/lib/onfido/resources/check.rb +6 -0
  20. data/lib/onfido/resources/document.rb +2 -0
  21. data/lib/onfido/resources/extraction.rb +11 -0
  22. data/lib/onfido/resources/live_photo.rb +2 -0
  23. data/lib/onfido/resources/live_video.rb +2 -0
  24. data/lib/onfido/resources/report.rb +2 -0
  25. data/lib/onfido/resources/sdk_token.rb +2 -0
  26. data/lib/onfido/resources/webhook.rb +8 -2
  27. data/lib/onfido/version.rb +3 -1
  28. data/onfido.gemspec +5 -7
  29. data/spec/integrations/address_spec.rb +4 -2
  30. data/spec/integrations/applicant_spec.rb +12 -7
  31. data/spec/integrations/check_spec.rb +17 -4
  32. data/spec/integrations/document_spec.rb +8 -4
  33. data/spec/integrations/extraction_spec.rb +23 -0
  34. data/spec/integrations/live_photo_spec.rb +8 -4
  35. data/spec/integrations/live_video_spec.rb +6 -1
  36. data/spec/integrations/report_spec.rb +6 -1
  37. data/spec/integrations/resource_spec.rb +106 -0
  38. data/spec/integrations/sdk_token_spec.rb +5 -1
  39. data/spec/integrations/webhook_spec.rb +35 -24
  40. data/spec/onfido/api_spec.rb +14 -25
  41. data/spec/onfido/connection_error_spec.rb +4 -2
  42. data/spec/onfido/options_spec.rb +39 -0
  43. data/spec/onfido/request_error_spec.rb +4 -2
  44. data/spec/spec_helper.rb +3 -5
  45. data/spec/support/fake_onfido_api.rb +69 -46
  46. data/spec/support/fixtures/applicant.json +1 -1
  47. data/spec/support/fixtures/check.json +1 -1
  48. data/spec/support/fixtures/checks.json +1 -1
  49. data/spec/support/fixtures/document.json +1 -1
  50. data/spec/support/fixtures/documents.json +2 -2
  51. data/spec/support/fixtures/extraction.json +23 -0
  52. data/spec/support/fixtures/live_photo.json +2 -2
  53. data/spec/support/fixtures/live_photos.json +4 -4
  54. data/spec/support/fixtures/live_video.json +2 -2
  55. data/spec/support/fixtures/live_videos.json +2 -2
  56. data/spec/support/fixtures/report.json +1 -1
  57. data/spec/support/fixtures/reports.json +2 -2
  58. data/spec/support/fixtures/webhook.json +1 -1
  59. data/spec/support/fixtures/webhooks.json +2 -2
  60. metadata +18 -43
  61. data/Rakefile +0 -1
  62. data/lib/onfido/configuration.rb +0 -46
  63. data/lib/onfido/null_logger.rb +0 -5
  64. data/spec/integrations/exceptions_spec.rb +0 -73
  65. data/spec/onfido/resource_spec.rb +0 -131
  66. data/spec/onfido_spec.rb +0 -76
@@ -1,33 +1,22 @@
1
- describe Onfido::API do
2
- subject(:api) { described_class.new }
3
-
4
- describe 'given a single-word resource' do
5
- specify { expect(api.address).to be_a(Onfido::Address) }
6
- end
1
+ # frozen_string_literal: true
7
2
 
8
- describe 'given a multi-word resource' do
9
- specify { expect(api.live_photo).to be_a(Onfido::LivePhoto) }
10
- end
11
-
12
- describe 'given an unknown resource' do
13
- specify { expect { api.blood_test }.to raise_error(NameError) }
3
+ describe Onfido::API do
4
+ before do
5
+ allow(Onfido::Options).to receive(:new).and_call_original
14
6
  end
15
7
 
16
- describe 'given no API key' do
17
- it 'uses nil for the resource API key' do
18
- expect(Onfido::Address).to receive(:new).with(nil)
19
- api.address
20
- end
8
+ let(:options) do
9
+ {
10
+ api_key: 'test',
11
+ region: :eu,
12
+ open_timeout: 1,
13
+ read_timeout: 2
14
+ }
21
15
  end
22
16
 
23
- describe 'given an API key' do
24
- let(:api_key) { 'some_key' }
25
-
26
- subject(:api) { described_class.new(api_key: api_key) }
17
+ it 'passes through options' do
18
+ described_class.new(**options)
27
19
 
28
- it 'uses that key to create the resource' do
29
- expect(Onfido::Address).to receive(:new).with(api_key)
30
- api.address
31
- end
20
+ expect(Onfido::Options).to have_received(:new).with(**options)
32
21
  end
33
22
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::ConnectionError do
2
4
  subject(:error) do
3
5
  described_class.new(
4
- "Invalid response object from API",
6
+ 'Invalid response object from API',
5
7
  response_code: response_code,
6
8
  response_body: response_body
7
9
  )
@@ -10,7 +12,7 @@ describe Onfido::ConnectionError do
10
12
  let(:response_code) { nil }
11
13
  let(:response_body) { nil }
12
14
 
13
- context "without a response_body" do
15
+ context 'without a response_body' do
14
16
  its(:json_body) { is_expected.to be_nil }
15
17
  its(:type) { is_expected.to be_nil }
16
18
  its(:fields) { is_expected.to be_nil }
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Onfido::Options do
4
+ subject(:options) do
5
+ described_class.new(
6
+ api_key: 'test',
7
+ region: :us,
8
+ open_timeout: 1,
9
+ read_timeout: 2
10
+ )
11
+ end
12
+
13
+ it 'checks region is valid' do
14
+ expect { described_class.new(api_key: 'test', region: :aa) }.to raise_error 'Unknown region aa'
15
+ end
16
+
17
+ context 'when creating rest client resource' do
18
+ let(:rest_client) { options.rest_client }
19
+
20
+ it 'configures with headers' do
21
+ expect(rest_client.options[:headers]).to eq(
22
+ 'Accept' => 'application/json',
23
+ 'Authorization' => 'Token token=test',
24
+ 'User-Agent' => "onfido-ruby/#{Onfido::VERSION}"
25
+ )
26
+ end
27
+
28
+ it 'configures with region' do
29
+ expect(rest_client.url).to eq 'https://api.us.onfido.com/v3.1/'
30
+ end
31
+
32
+ it 'configures with timeouts' do
33
+ expect(rest_client.options).to include(
34
+ open_timeout: 1,
35
+ read_timeout: 2
36
+ )
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::RequestError do
2
4
  subject(:error) do
3
5
  described_class.new(
@@ -20,8 +22,8 @@ describe Onfido::RequestError do
20
22
  end
21
23
 
22
24
  it 'returns the right message' do
23
- expect { raise error }.
24
- to raise_error('Authorization error: please re-check your credentials')
25
+ expect { raise error }
26
+ .to raise_error('Authorization error: please re-check your credentials')
25
27
  end
26
28
 
27
29
  its(:type) { is_expected.to eq('authorization_error') }
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
- Dir[File.dirname(__FILE__).concat("/support/**/*.rb")].each { |f| require f }
5
+ Dir[File.dirname(__FILE__).concat('/support/**/*.rb')].sort.each { |f| require f }
4
6
 
5
7
  require 'onfido'
6
8
  require 'webmock/rspec'
@@ -40,8 +42,4 @@ RSpec.configure do |config|
40
42
  # test failures related to randomization by passing the same `--seed` value
41
43
  # as the one that triggered the failure.
42
44
  Kernel.srand config.seed
43
-
44
- config.before(:each) do
45
- stub_request(:any, /onfido.com/).to_rack(FakeOnfidoAPI)
46
- end
47
45
  end
@@ -1,154 +1,177 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'sinatra/base'
2
4
 
3
- class FakeOnfidoAPI < Sinatra::Base
4
- get '/v3/addresses/pick' do
5
+ RSpec.shared_context 'fake onfido api' do
6
+ let(:onfido) { Onfido::API.new(api_key: 'test', region: :eu) }
7
+
8
+ before { stub_request(:any, /api.eu.onfido.com/).to_rack(FakeOnfidoAPI) }
9
+ end
10
+
11
+ class FakeOnfidoAPI < Sinatra::Base # rubocop:disable Metrics/ClassLength
12
+ get '/v3.1/addresses/pick' do
5
13
  json_response(200, 'addresses.json')
6
14
  end
7
15
 
8
- post '/v3/applicants' do
16
+ post '/v3.1/applicants' do
9
17
  json_response(201, 'applicant.json')
10
18
  end
11
19
 
12
- put '/v3/applicants/:id' do
20
+ put '/v3.1/applicants/:id' do
13
21
  json_response(200, 'applicant.json')
14
22
  end
15
23
 
16
- get '/v3/applicants/:id' do
24
+ get '/v3.1/applicants/:id' do
17
25
  json_response(200, 'applicant.json')
18
26
  end
19
27
 
20
- get '/v3/applicants' do
28
+ get '/v3.1/applicants' do
21
29
  response = json_response(200, 'applicants.json')
22
30
  { applicants: JSON.parse(response)['applicants'][pagination_range] }.to_json
23
31
  end
24
32
 
25
- delete '/v3/applicants/:id' do
33
+ delete '/v3.1/applicants/:id' do
26
34
  status 204
27
35
  end
28
36
 
29
- post '/v3/applicants/:id/restore' do
30
- if params["id"] == "a2fb9c62-ab10-4898-a8ec-342c4b552ad5"
37
+ post '/v3.1/applicants/:id/restore' do
38
+ if params['id'] == 'a2fb9c62-ab10-4898-a8ec-342c4b552ad5'
31
39
  json_response(422, 'not_scheduled_for_deletion_error.json')
32
40
  else
33
41
  status 204
34
42
  end
35
43
  end
36
44
 
37
- post '/v3/documents' do
45
+ post '/v3.1/documents' do
38
46
  json_response(201, 'document.json')
39
47
  end
40
48
 
41
- get '/v3/documents/:id' do
49
+ post '/v3.1/extractions' do
50
+ json_response(201, 'extraction.json')
51
+ end
52
+
53
+ get '/v3.1/documents/:id' do
42
54
  json_response(200, 'document.json')
43
55
  end
44
56
 
45
- get '/v3/documents' do
57
+ get '/v3.1/documents' do
46
58
  json_response(200, 'documents.json')
47
59
  end
48
60
 
49
- get '/v3/documents/:id/download' do
61
+ get '/v3.1/documents/:id/download' do
50
62
  status 200
51
63
  content_type 'application/octet-stream'
52
64
  "\x01\x02\x03" # acts as binary file data
53
65
  end
54
66
 
55
- post '/v3/live_photos' do
67
+ post '/v3.1/live_photos' do
56
68
  json_response(201, 'live_photo.json')
57
69
  end
58
70
 
59
- get '/v3/live_photos/:id' do
71
+ get '/v3.1/live_photos/:id' do
60
72
  json_response(200, 'live_photo.json')
61
73
  end
62
74
 
63
- get '/v3/live_photos' do
64
- if params["applicant_id"] != "1030303-123123-123123"
65
- status 404
66
- else
75
+ get '/v3.1/live_photos' do
76
+ if params['applicant_id'] == '1030303-123123-123123'
67
77
  json_response(200, 'live_photos.json')
78
+ else
79
+ status 404
68
80
  end
69
81
  end
70
82
 
71
- get '/v3/live_photos/:id/download' do
83
+ get '/v3.1/live_photos/:id/download' do
72
84
  status 200
73
85
  content_type 'image/jpeg'
74
86
  "\x01\x02\x03" # acts as binary file data
75
87
  end
76
88
 
77
- get '/v3/live_videos/:id' do
89
+ get '/v3.1/live_videos/:id' do
78
90
  json_response(200, 'live_video.json')
79
91
  end
80
92
 
81
- get '/v3/live_videos' do
82
- if params["applicant_id"] != "1030303-123123-123123"
83
- status 404
84
- else
93
+ get '/v3.1/live_videos' do
94
+ if params['applicant_id'] == '1030303-123123-123123'
85
95
  json_response(200, 'live_videos.json')
96
+ else
97
+ status 404
86
98
  end
87
99
  end
88
100
 
89
- get '/v3/live_videos/:id/download' do
101
+ get '/v3.1/live_videos/:id/download' do
90
102
  status 200
91
103
  content_type 'video/quicktime'
92
104
  "\x01\x02\x03" # acts as binary file data
93
105
  end
94
106
 
95
- post '/v3/checks' do
96
- params["applicant_id"].nil? ? status(422) : json_response(201, 'check.json')
107
+ post '/v3.1/checks' do
108
+ params['applicant_id'].nil? ? status(422) : json_response(201, 'check.json')
97
109
  end
98
110
 
99
- get '/v3/checks/:id' do
100
- json_response(200, "check.json")
111
+ get '/v3.1/checks/:id' do
112
+ json_response(200, 'check.json')
101
113
  end
102
114
 
103
- get '/v3/checks' do
104
- json_response(200, "checks.json")
115
+ get '/v3.1/checks' do
116
+ json_response(200, 'checks.json')
105
117
  end
106
118
 
107
- post '/v3/checks/:id/resume' do
119
+ post '/v3.1/checks/:id/resume' do
108
120
  status 204 # no_content
109
121
  end
110
122
 
111
- get '/v3/reports' do
123
+ get '/v3.1/checks/:id/download' do
124
+ status 200
125
+ content_type 'application/pdf'
126
+ "\x01\x02\x03" # acts as binary file data
127
+ end
128
+
129
+ get '/v3.1/reports' do
112
130
  json_response(200, 'reports.json')
113
131
  end
114
132
 
115
- get '/v3/reports/:id' do
133
+ get '/v3.1/reports/:id' do
116
134
  json_response(200, 'report.json')
117
135
  end
118
136
 
119
- post '/v3/reports/:id/resume' do
137
+ post '/v3.1/reports/:id/resume' do
120
138
  status 204
121
139
  end
122
140
 
123
- post '/v3/reports/:id/cancel' do
141
+ post '/v3.1/reports/:id/cancel' do
124
142
  status 204
125
143
  end
126
144
 
127
- post '/v3/sdk_token' do
145
+ post '/v3.1/sdk_token' do
128
146
  json_response(201, 'sdk_token.json')
129
147
  end
130
148
 
131
- post '/v3/webhooks' do
149
+ post '/v3.1/webhooks' do
132
150
  json_response(201, 'webhook.json')
133
151
  end
134
152
 
135
- get '/v3/webhooks/:id' do
153
+ get '/v3.1/webhooks/:id' do
136
154
  json_response(200, 'webhook.json')
137
155
  end
138
156
 
139
- get '/v3/webhooks' do
157
+ delete '/v3.1/webhooks/:id' do
158
+ content_type 'application/json; charset=utf-8'
159
+ status 204
160
+ end
161
+
162
+ get '/v3.1/webhooks' do
140
163
  json_response(200, 'webhooks.json')
141
164
  end
142
165
 
143
- get '/v3/4xx_response' do
166
+ get '/v3.1/4xx_response' do
144
167
  json_response(422, '4xx_response.json')
145
168
  end
146
169
 
147
- get '/v3/unexpected_error_format' do
170
+ get '/v3.1/unexpected_error_format' do
148
171
  json_response(400, 'unexpected_error_format.json')
149
172
  end
150
173
 
151
- get '/v3/unparseable_response' do
174
+ get '/v3.1/unparseable_response' do
152
175
  content_type :json
153
176
  status 504
154
177
  ''
@@ -157,9 +180,9 @@ class FakeOnfidoAPI < Sinatra::Base
157
180
  private
158
181
 
159
182
  def json_response(response_code, file_name)
160
- content_type "application/json; charset=utf-8"
183
+ content_type 'application/json; charset=utf-8'
161
184
  status response_code
162
- File.open(File.dirname(__FILE__) + '/fixtures/' + file_name, 'rb').read
185
+ File.open("#{File.dirname(__FILE__)}/fixtures/#{file_name}", 'rb').read
163
186
  end
164
187
 
165
188
  def pagination_range
@@ -7,7 +7,7 @@
7
7
  "last_name":"Bing",
8
8
  "email":"chandler_bing_6@friends.com",
9
9
  "dob":"1968-04-08",
10
- "href":"/v3/applicants/61f659cb-c90b-4067-808a-6136b5c01351",
10
+ "href":"/v3.1/applicants/61f659cb-c90b-4067-808a-6136b5c01351",
11
11
  "id_numbers":[],
12
12
  "address": {
13
13
  "flat_number":"4",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "8546921-123123-123123",
3
3
  "created_at": "2019-05-23T13:50:33Z",
4
- "href": "/v3/checks/8546921-123123-123123",
4
+ "href": "/v3.1/checks/8546921-123123-123123",
5
5
  "applicant_provides_data": "false",
6
6
  "status": "pending",
7
7
  "result": "pending",
@@ -3,7 +3,7 @@
3
3
  {
4
4
  "id": "8546921-123123-123123",
5
5
  "created_at": "2019-11-23T13:50:33Z",
6
- "href": "/v3/checks/8546921-123123-123123",
6
+ "href": "/v3.1/checks/8546921-123123-123123",
7
7
  "applicant_provides_data": "false",
8
8
  "status": "pending",
9
9
  "result": "pending",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "7568415-123123-123123",
3
3
  "created_at": "2019-11-23 13:50:33Z",
4
- "href": "/v3/documents/7568415-123123-123123",
4
+ "href": "/v3.1/documents/7568415-123123-123123",
5
5
  "file_name": "passport.jpg",
6
6
  "file_type": "png",
7
7
  "file_size": 282870,
@@ -3,7 +3,7 @@
3
3
  {
4
4
  "id": "7568415-123123-123123",
5
5
  "created_at": "2019-11-23 13:50:33Z",
6
- "href": "/v3/documents/7568415-123123-123123",
6
+ "href": "/v3.1/documents/7568415-123123-123123",
7
7
  "file_name": "passport.jpg",
8
8
  "file_type": "png",
9
9
  "file_size": 282870,
@@ -12,7 +12,7 @@
12
12
  {
13
13
  "id": "121122-123123-123123",
14
14
  "created_at": "2019-11-23 13:50:40Z",
15
- "href": "/v3/documents/7568415-123123-123123",
15
+ "href": "/v3.1/documents/7568415-123123-123123",
16
16
  "file_name": "driving_licence.png",
17
17
  "file_type": "png",
18
18
  "file_size": 282870,
@@ -0,0 +1,23 @@
1
+ {
2
+ "document_id": "7568415-123123-123123",
3
+ "document_classification": {
4
+ "issuing_country": "FRA",
5
+ "document_type": "national_identity_card"
6
+ },
7
+ "extracted_data": {
8
+ "date_of_birth": "1965-09-08",
9
+ "document_number": "400925733",
10
+ "first_name": "MARIE",
11
+ "gender": "Female",
12
+ "last_name": "MAVARINE",
13
+ "mrz_line1": "P<GBRDU<MARIE<<MAVARINE<<<<<<<<<<<<<<<<<<<<<",
14
+ "mrz_line2": "4009257333GBR6509088F1307072<<<<<<<<<<<<<<06",
15
+ "nationality": "BRITISH CITIZEN",
16
+ "full_name": "MAVARINE DU MARIE",
17
+ "date_of_expiry": "2013-07-07",
18
+ "middle_name": "DU",
19
+ "address_line_1": "52 RUE DES FLEURS",
20
+ "address_line_2": "33500 BORDEAUX",
21
+ "address_line_3": "FRANCE"
22
+ }
23
+ }