onfido 0.15.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) 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 +28 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE +2 -1
  9. data/README.md +46 -172
  10. data/lib/onfido.rb +4 -4
  11. data/lib/onfido/api.rb +21 -15
  12. data/lib/onfido/errors/connection_error.rb +2 -0
  13. data/lib/onfido/errors/onfido_error.rb +2 -0
  14. data/lib/onfido/errors/request_error.rb +2 -0
  15. data/lib/onfido/errors/server_error.rb +2 -0
  16. data/lib/onfido/options.rb +38 -0
  17. data/lib/onfido/resource.rb +44 -61
  18. data/lib/onfido/resources/address.rb +3 -2
  19. data/lib/onfido/resources/applicant.rb +8 -6
  20. data/lib/onfido/resources/check.rb +15 -19
  21. data/lib/onfido/resources/document.rb +13 -11
  22. data/lib/onfido/resources/extraction.rb +11 -0
  23. data/lib/onfido/resources/live_photo.rb +11 -14
  24. data/lib/onfido/resources/live_video.rb +7 -8
  25. data/lib/onfido/resources/report.rb +10 -9
  26. data/lib/onfido/resources/sdk_token.rb +5 -5
  27. data/lib/onfido/resources/webhook.rb +15 -11
  28. data/lib/onfido/version.rb +3 -1
  29. data/onfido.gemspec +10 -12
  30. data/spec/integrations/address_spec.rb +5 -2
  31. data/spec/integrations/applicant_spec.rb +29 -42
  32. data/spec/integrations/check_spec.rb +28 -69
  33. data/spec/integrations/document_spec.rb +22 -19
  34. data/spec/integrations/extraction_spec.rb +23 -0
  35. data/spec/integrations/live_photo_spec.rb +18 -15
  36. data/spec/integrations/live_video_spec.rb +13 -11
  37. data/spec/integrations/report_spec.rb +16 -13
  38. data/spec/integrations/resource_spec.rb +93 -0
  39. data/spec/integrations/sdk_token_spec.rb +10 -6
  40. data/spec/integrations/webhook_spec.rb +56 -37
  41. data/spec/onfido/api_spec.rb +14 -25
  42. data/spec/onfido/connection_error_spec.rb +4 -2
  43. data/spec/onfido/options_spec.rb +39 -0
  44. data/spec/onfido/request_error_spec.rb +4 -2
  45. data/spec/spec_helper.rb +3 -5
  46. data/spec/support/fake_onfido_api.rb +77 -88
  47. data/spec/support/fixtures/applicant.json +21 -42
  48. data/spec/support/fixtures/check.json +4 -4
  49. data/spec/support/fixtures/checks.json +4 -4
  50. data/spec/support/fixtures/document.json +2 -2
  51. data/spec/support/fixtures/documents.json +8 -8
  52. data/spec/support/fixtures/extraction.json +23 -0
  53. data/spec/support/fixtures/live_photo.json +3 -3
  54. data/spec/support/fixtures/live_photos.json +6 -6
  55. data/spec/support/fixtures/live_video.json +3 -3
  56. data/spec/support/fixtures/live_videos.json +4 -4
  57. data/spec/support/fixtures/report.json +4 -4
  58. data/spec/support/fixtures/reports.json +8 -8
  59. data/spec/support/fixtures/webhook.json +6 -5
  60. data/spec/support/fixtures/webhooks.json +17 -12
  61. metadata +27 -65
  62. data/Rakefile +0 -1
  63. data/lib/onfido/configuration.rb +0 -47
  64. data/lib/onfido/null_logger.rb +0 -5
  65. data/lib/onfido/resources/report_type_group.rb +0 -11
  66. data/spec/integrations/exceptions_spec.rb +0 -74
  67. data/spec/integrations/report_type_group_spec.rb +0 -19
  68. data/spec/onfido/resource_spec.rb +0 -137
  69. data/spec/onfido_spec.rb +0 -84
  70. data/spec/support/fixtures/check_with_expanded_reports.json +0 -30
  71. data/spec/support/fixtures/checks_with_expanded_reports.json +0 -34
  72. data/spec/support/fixtures/report_type_group.json +0 -25
  73. data/spec/support/fixtures/report_type_groups.json +0 -30
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Onfido
4
+ class Extraction < Resource
5
+ def create(document_id:)
6
+ payload = { document_id: document_id }
7
+
8
+ post(path: 'extractions', payload: payload)
9
+ end
10
+ end
11
+ end
@@ -1,30 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Onfido
2
4
  class LivePhoto < Resource
3
5
  # with open-uri the file can be a link or an actual file
4
6
 
5
- def create(applicant_id, payload)
6
- validate_file!(payload.fetch(:file))
7
+ def create(applicant_id:, file:, **payload)
8
+ validate_file!(file)
7
9
  payload[:applicant_id] = applicant_id
10
+ payload[:file] = file
8
11
 
9
- post(
10
- url: url_for("/live_photos"),
11
- payload: payload
12
- )
12
+ post(path: 'live_photos', payload: payload)
13
13
  end
14
14
 
15
- def find(applicant_id, live_photo_id)
16
- query_string = "applicant_id=#{applicant_id}"
17
- get(url: url_for("live_photos/#{live_photo_id}?#{query_string}"))
15
+ def find(live_photo_id)
16
+ get(path: "live_photos/#{live_photo_id}")
18
17
  end
19
18
 
20
- def download(applicant_id, live_photo_id)
21
- query_string = "applicant_id=#{applicant_id}"
22
- get(url: url_for("live_photos/#{live_photo_id}/download?#{query_string}"))
19
+ def download(live_photo_id)
20
+ get(path: "live_photos/#{live_photo_id}/download")
23
21
  end
24
22
 
25
23
  def all(applicant_id)
26
- query_string = "applicant_id=#{applicant_id}"
27
- get(url: url_for("live_photos?#{query_string}"))
24
+ get(path: "live_photos?applicant_id=#{applicant_id}")
28
25
  end
29
26
  end
30
27
  end
@@ -1,18 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Onfido
2
4
  class LiveVideo < Resource
3
- def find(applicant_id, live_video_id)
4
- query_string = "applicant_id=#{applicant_id}"
5
- get(url: url_for("live_videos/#{live_video_id}?#{query_string}"))
5
+ def find(live_video_id)
6
+ get(path: "live_videos/#{live_video_id}")
6
7
  end
7
8
 
8
- def download(applicant_id, live_video_id)
9
- query_string = "applicant_id=#{applicant_id}"
10
- get(url: url_for("live_videos/#{live_video_id}/download?#{query_string}"))
9
+ def download(live_video_id)
10
+ get(path: "live_videos/#{live_video_id}/download")
11
11
  end
12
12
 
13
13
  def all(applicant_id)
14
- query_string = "applicant_id=#{applicant_id}"
15
- get(url: url_for("live_videos?#{query_string}"))
14
+ get(path: "live_videos?applicant_id=#{applicant_id}")
16
15
  end
17
16
  end
18
17
  end
@@ -1,20 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Onfido
2
4
  class Report < Resource
3
- def find(check_id, report_id)
4
- get(url: url_for("checks/#{check_id}/reports/#{report_id}"))
5
+ def find(report_id)
6
+ get(path: "reports/#{report_id}")
5
7
  end
6
8
 
7
- def all(check_id, page: 1, per_page: 20)
8
- querystring = "page=#{page}&per_page=#{per_page}"
9
- get(url: url_for("checks/#{check_id}/reports?#{querystring}"))
9
+ def all(check_id)
10
+ get(path: "reports?check_id=#{check_id}")
10
11
  end
11
12
 
12
- def resume(check_id, report_id)
13
- post(url: url_for("checks/#{check_id}/reports/#{report_id}/resume"))
13
+ def resume(report_id)
14
+ post(path: "reports/#{report_id}/resume")
14
15
  end
15
16
 
16
- def cancel(check_id, report_id)
17
- post(url: url_for("checks/#{check_id}/reports/#{report_id}/cancel"))
17
+ def cancel(report_id)
18
+ post(path: "reports/#{report_id}/cancel")
18
19
  end
19
20
  end
20
21
  end
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Onfido
2
4
  class SdkToken < Resource
3
- def create(payload)
4
- post(
5
- url: url_for("sdk_token"),
6
- payload: payload
7
- )
5
+ def create(applicant_id:, **payload)
6
+ payload[:applicant_id] = applicant_id
7
+ post(path: 'sdk_token', payload: payload)
8
8
  end
9
9
  end
10
10
  end
@@ -1,18 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Onfido
2
4
  class Webhook < Resource
3
- def create(payload)
4
- post(
5
- url: url_for('webhooks'),
6
- payload: payload
7
- )
5
+ def create(url:, **payload)
6
+ payload[:url] = url
7
+ post(path: 'webhooks', payload: payload)
8
8
  end
9
9
 
10
10
  def find(webhooks_id)
11
- get(url: url_for("webhooks/#{webhooks_id}"))
11
+ get(path: "webhooks/#{webhooks_id}")
12
+ end
13
+
14
+ def all
15
+ get(path: 'webhooks')
12
16
  end
13
17
 
14
- def all(page: 1, per_page: 20)
15
- get(url: url_for("webhooks?page=#{page}&per_page=#{per_page}"))
18
+ def destroy(webhook_id)
19
+ delete(path: "webhooks/#{webhook_id}")
16
20
  end
17
21
 
18
22
  # As well as being a normal resource, Onfido::Webhook also supports
@@ -20,8 +24,8 @@ module Onfido
20
24
  # request to one computed from the body
21
25
  def self.valid?(request_body, request_signature, token)
22
26
  if [request_body, request_signature, token].any?(&:nil?)
23
- raise ArgumentError, "A request body, request signature and token " \
24
- "must be provided"
27
+ raise ArgumentError, 'A request body, request signature and token ' \
28
+ 'must be provided'
25
29
  end
26
30
 
27
31
  computed_signature = generate_signature(request_body, token)
@@ -29,7 +33,7 @@ module Onfido
29
33
  end
30
34
 
31
35
  def self.generate_signature(request_body, token)
32
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), token, request_body)
36
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), token, request_body)
33
37
  end
34
38
  private_class_method :generate_signature
35
39
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Onfido
2
- VERSION = '0.15.1'.freeze
4
+ VERSION = '2.0.1'
3
5
  end
data/onfido.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -7,27 +7,25 @@ require 'onfido/version'
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'onfido'
9
9
  spec.version = Onfido::VERSION
10
- spec.authors = ['Pericles Theodorou', 'Grey Baker']
11
- spec.email = ['periclestheo@gmail.com', 'grey@gocardless.com']
10
+ spec.authors = ['Onfido']
11
+ spec.email = ['engineering@onfido.com']
12
12
  spec.summary = 'A wrapper for Onfido API'
13
- spec.description = "A thin wrapper for Onfido's API. This gem supports "\
14
- "both v1 and v2 of the Onfido API. Refer to Onfido's "\
15
- "API documentation for details of the expected "\
16
- "requests and responses for both."
17
- spec.homepage = 'http://github.com/hvssle/onfido'
13
+ spec.description = "A thin wrapper for Onfido's API. This gem only supports "\
14
+ "v3 of the Onfido API. Refer to Onfido's "\
15
+ 'API documentation for details of the expected '\
16
+ 'requests and responses.'
17
+ spec.homepage = 'http://github.com/onfido/onfido-ruby'
18
18
  spec.license = 'MIT'
19
19
 
20
20
  spec.files = `git ls-files -z`.split("\x0")
21
21
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
22
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
23
  spec.require_paths = ['lib']
24
- spec.required_ruby_version = ">= 2.2.0"
24
+ spec.required_ruby_version = '>= 2.4.0'
25
25
 
26
- spec.add_development_dependency 'bundler', '~> 2.0'
27
- spec.add_development_dependency 'rake', '~> 12.0'
28
26
  spec.add_development_dependency 'rspec', '~> 3.1'
29
27
  spec.add_development_dependency 'rspec-its', '~> 1.2'
30
- spec.add_development_dependency 'rubocop', '~> 0.57.0'
28
+ spec.add_development_dependency 'rubocop', '~> 1.11'
31
29
  spec.add_development_dependency 'sinatra', '~> 1.4'
32
30
  spec.add_development_dependency 'webmock', '~> 3.0'
33
31
 
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Address do
2
- subject(:api) { Onfido::API.new }
4
+ include_context 'fake onfido api'
3
5
 
4
6
  describe '#all' do
5
7
  it 'returns the addresses matching the postcode' do
6
- response = api.address.all('SW1 4NG')
8
+ response = onfido.address.all('SW1 4NG')
9
+
7
10
  expect(response['addresses'].count).to eq(2)
8
11
  end
9
12
  end
@@ -1,38 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Applicant do
2
- subject(:applicant) { described_class.new }
4
+ include_context 'fake onfido api'
5
+
6
+ subject(:applicant) { onfido.applicant }
7
+
8
+ let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
3
9
  let(:params) do
4
10
  {
5
11
  'title' => 'Mr',
6
12
  'first_name' => 'Chandler',
7
13
  'last_name' => 'Bing',
8
- 'gender' => 'male',
9
14
  'middle_name' => 'Muriel',
10
15
  'dob' => '1968-04-08',
11
- 'telephone' => '555555555',
12
- 'mobile' => '77777777',
13
16
  'email' => 'chandler_bing_6@friends.com',
14
- 'addresses' => [
15
- {
16
- 'flat_number' => '4',
17
- 'building_number' => '100',
18
- 'building_name' => 'Awesome Building',
19
- 'street' => 'Main Street',
20
- 'sub_street' => 'A sub street',
21
- 'town' => 'London',
22
- 'postcode' => 'SW4 6EH',
23
- 'country' => 'GBR'
24
- },
25
- {
26
- 'flat_number' => '1',
27
- 'building_number' => '10',
28
- 'building_name' => 'Great Building',
29
- 'street' => 'Old Street',
30
- 'sub_street' => 'Sub Street',
31
- 'town' => 'London',
32
- 'postcode' => 'SW1 4NG',
33
- 'country' => 'GBR'
34
- }
35
- ]
17
+ 'address' => {
18
+ 'flat_number' => '4',
19
+ 'building_number' => '100',
20
+ 'building_name' => 'Awesome Building',
21
+ 'street' => 'Main Street',
22
+ 'sub_street' => 'A sub street',
23
+ 'town' => 'London',
24
+ 'postcode' => 'SW4 6EH',
25
+ 'country' => 'GBR'
26
+ }
36
27
  }
37
28
  end
38
29
 
@@ -43,9 +34,9 @@ describe Onfido::Applicant do
43
34
 
44
35
  it 'serializes the payload correctly' do
45
36
  WebMock.after_request do |request_signature, _response|
46
- if request_signature.uri.path == 'v2/applicants'
47
- expect(Rack::Utils.parse_nested_query(request_signature.body)).
48
- to eq(params)
37
+ if request_signature.uri.path == 'v3.1/applicants'
38
+ expect(Rack::Utils.parse_nested_query(request_signature.body))
39
+ .to eq(params)
49
40
  end
50
41
  end
51
42
  end
@@ -57,26 +48,22 @@ describe Onfido::Applicant do
57
48
  end
58
49
 
59
50
  describe '#update' do
60
- let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
61
-
62
51
  it 'updates an applicant' do
63
52
  response = applicant.update(applicant_id, params)
53
+
64
54
  expect(response['id']).to eq(applicant_id)
65
55
  end
66
56
  end
67
57
 
68
58
  describe '#find' do
69
- let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
70
-
71
59
  it 'returns the applicant' do
72
60
  response = applicant.find(applicant_id)
61
+
73
62
  expect(response['id']).to eq(applicant_id)
74
63
  end
75
64
  end
76
65
 
77
66
  describe '#destroy' do
78
- let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
79
-
80
67
  it 'returns success code' do
81
68
  expect { applicant.destroy(applicant_id) }.not_to raise_error
82
69
  end
@@ -86,6 +73,7 @@ describe Onfido::Applicant do
86
73
  context 'with the default page and per page params' do
87
74
  it 'returns all the applicants' do
88
75
  response = applicant.all
76
+
89
77
  expect(response['applicants'].size).to eq(2)
90
78
  end
91
79
  end
@@ -93,6 +81,7 @@ describe Onfido::Applicant do
93
81
  context 'with specific range of results for a page' do
94
82
  it 'returns the specified applicants' do
95
83
  response = applicant.all(page: 1, per_page: 1)
84
+
96
85
  expect(response['applicants'].size).to eq(1)
97
86
  end
98
87
  end
@@ -100,24 +89,22 @@ describe Onfido::Applicant do
100
89
 
101
90
  describe '#restore' do
102
91
  context 'an applicant scheduled for deletion' do
103
- let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
104
-
105
92
  it 'returns nil' do
106
93
  expect(applicant.restore(applicant_id)).to be_nil
107
94
  end
108
95
  end
109
96
 
110
97
  context 'an applicant not scheduled for deletion' do
111
- let(:applicant_id) { 'a2fb9c62-ab10-4898-a8ec-342c4b552ad5' }
112
-
113
98
  it 'returns an error' do
114
- expect { applicant.restore(applicant_id) }.to raise_error { |error|
99
+ applicant_id = 'a2fb9c62-ab10-4898-a8ec-342c4b552ad5'
100
+
101
+ expect { applicant.restore(applicant_id) }.to raise_error do |error|
115
102
  expect(error).to be_a(Onfido::RequestError)
116
103
  expect(error.message).to eq('There was a validation error on this request')
117
104
  expect(error.fields).to eq(
118
- "Applicant a2fb9c62-ab10-4898-a8ec-342c4b552ad5 is not scheduled for deletion"
105
+ 'Applicant a2fb9c62-ab10-4898-a8ec-342c4b552ad5 is not scheduled for deletion'
119
106
  )
120
- }
107
+ end
121
108
  end
122
109
  end
123
110
  end
@@ -1,105 +1,64 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Check do
2
- subject(:check) { described_class.new }
4
+ include_context 'fake onfido api'
5
+
6
+ subject(:check) { onfido.check }
7
+
3
8
  let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
9
+ let(:check_id) { '8546921-123123-123123' }
4
10
 
5
11
  describe '#create' do
6
- let(:params) { { type: 'express', reports: [{ name: 'identity' }] } }
7
-
8
12
  it 'creates a new check for an applicant' do
9
- response = check.create(applicant_id, params)
13
+ response = check.create(
14
+ applicant_id: applicant_id,
15
+ report_names: ['identity_enhanced']
16
+ )
10
17
  expect(response['id']).not_to be_nil
11
18
  end
12
19
  end
13
20
 
14
21
  describe '#find' do
15
- let(:check_id) { '8546921-123123-123123' }
16
-
17
22
  it 'returns an existing check for the applicant' do
18
- response = check.find(applicant_id, check_id)
19
- expect(response['id']).to eq(check_id)
20
- end
21
-
22
- it "returns unexpanded reports" do
23
- response = check.find(applicant_id, check_id)
24
- expect(response['reports'].first).to be_a(String)
25
- end
26
-
27
- it 'allows you to expand the reports' do
28
- response = check.find(applicant_id, check_id, expand: "reports")
29
- expect(response['reports'].first).to be_a(Hash)
30
- end
31
- end
32
-
33
- describe '#find_by_url' do
34
- let(:check_id) { '8546921-123123-123123' }
35
-
36
- context 'partial url' do
37
- let(:url) { "applicants/#{applicant_id}/checks/#{check_id}" }
38
-
39
- it 'returns an existing check for the applicant with the partial url' do
40
- response = check.find_by_url(url)
41
- expect(response['id']).to eq(check_id)
42
- end
43
-
44
- it "returns unexpanded reports" do
45
- response = check.find_by_url(url)
46
- expect(response['reports'].first).to be_a(String)
47
- end
23
+ response = check.find(check_id)
48
24
 
49
- it 'allows you to expand the reports' do
50
- response = check.find_by_url(url, expand: "reports")
51
- expect(response['reports'].first).to be_a(Hash)
52
- end
25
+ expect(response['id']).to eq(check_id)
53
26
  end
54
27
 
55
- context 'full url' do
56
- let(:url) do
57
- "https://api.onfido.com/v2/applicants/#{applicant_id}/checks/#{check_id}"
58
- end
28
+ it 'returns report_ids' do
29
+ response = check.find(check_id)
59
30
 
60
- it 'returns an existing check for the applicant with the partial url' do
61
- response = check.find_by_url(url)
62
- expect(response['id']).to eq(check_id)
63
- end
64
-
65
- it "returns unexpanded reports" do
66
- response = check.find_by_url(url)
67
- expect(response['reports'].first).to be_a(String)
68
- end
69
-
70
- it 'allows you to expand the reports' do
71
- response = check.find_by_url(url, expand: "reports")
72
- expect(response['reports'].first).to be_a(Hash)
73
- end
31
+ expect(response['report_ids'].first).to be_a(String)
74
32
  end
75
33
  end
76
34
 
77
35
  describe '#all' do
78
- let(:check_id) { '8546921-123123-123123' }
79
-
80
36
  context 'with the default page and per page params' do
81
37
  it 'returns all existing checks for the applicant' do
82
38
  response = check.all(applicant_id)
39
+
83
40
  expect(response['checks'].size).to eq(1)
84
41
  end
85
42
  end
86
43
 
87
- it "returns unexpanded reports" do
44
+ it 'returns report_ids' do
88
45
  response = check.all(applicant_id)
89
- expect(response['checks'].first['reports'].first).to be_a(String)
90
- end
91
46
 
92
- it 'allows you to expand the reports' do
93
- response = check.all(applicant_id, expand: "reports")
94
- expect(response['checks'].first['reports'].first).to be_a(Hash)
47
+ expect(response['checks'].first['report_ids'].first).to be_a(String)
95
48
  end
96
49
  end
97
50
 
98
- describe "#resume" do
99
- let(:check_id) { '8546921-123123-123123' }
100
-
51
+ describe '#resume' do
101
52
  it 'returns success response' do
102
53
  expect { check.resume(check_id) }.not_to raise_error
103
54
  end
104
55
  end
56
+
57
+ describe '#download' do
58
+ it 'returns the file data' do
59
+ response = check.download(check_id)
60
+
61
+ expect(response).not_to be_nil
62
+ end
63
+ end
105
64
  end