yoti_sandbox 1.0.0 → 1.4.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +8 -1
  4. data/lib/yoti_sandbox.rb +1 -0
  5. data/lib/yoti_sandbox/doc_scan.rb +25 -0
  6. data/lib/yoti_sandbox/doc_scan/client.rb +59 -0
  7. data/lib/yoti_sandbox/doc_scan/errors.rb +83 -0
  8. data/lib/yoti_sandbox/doc_scan/request/check/check.rb +115 -0
  9. data/lib/yoti_sandbox/doc_scan/request/check/document_authenticity_check.rb +29 -0
  10. data/lib/yoti_sandbox/doc_scan/request/check/document_check.rb +48 -0
  11. data/lib/yoti_sandbox/doc_scan/request/check/document_face_match_check.rb +29 -0
  12. data/lib/yoti_sandbox/doc_scan/request/check/document_text_data_check.rb +78 -0
  13. data/lib/yoti_sandbox/doc_scan/request/check/id_document_comparison_check.rb +56 -0
  14. data/lib/yoti_sandbox/doc_scan/request/check/liveness_check.rb +34 -0
  15. data/lib/yoti_sandbox/doc_scan/request/check/report/breakdown.rb +97 -0
  16. data/lib/yoti_sandbox/doc_scan/request/check/report/detail.rb +34 -0
  17. data/lib/yoti_sandbox/doc_scan/request/check/report/recommendation.rb +88 -0
  18. data/lib/yoti_sandbox/doc_scan/request/check/supplementary_document_text_data_check.rb +78 -0
  19. data/lib/yoti_sandbox/doc_scan/request/check/zoom_liveness_check.rb +36 -0
  20. data/lib/yoti_sandbox/doc_scan/request/check_reports.rb +182 -0
  21. data/lib/yoti_sandbox/doc_scan/request/document_filter.rb +77 -0
  22. data/lib/yoti_sandbox/doc_scan/request/response_config.rb +75 -0
  23. data/lib/yoti_sandbox/doc_scan/request/task/document_id_photo.rb +35 -0
  24. data/lib/yoti_sandbox/doc_scan/request/task/document_text_data_extraction_task.rb +170 -0
  25. data/lib/yoti_sandbox/doc_scan/request/task/supplementary_document_text_data_extraction_task.rb +152 -0
  26. data/lib/yoti_sandbox/doc_scan/request/task/text_data_extraction_reason.rb +78 -0
  27. data/lib/yoti_sandbox/doc_scan/request/task/text_data_extraction_recommendation.rb +86 -0
  28. data/lib/yoti_sandbox/doc_scan/request/task_results.rb +96 -0
  29. data/lib/yoti_sandbox/profile.rb +5 -0
  30. data/lib/yoti_sandbox/profile/age_verification.rb +7 -0
  31. data/lib/yoti_sandbox/profile/client.rb +8 -26
  32. data/lib/yoti_sandbox/profile/document_images.rb +69 -0
  33. data/lib/yoti_sandbox/profile/extra_data.rb +92 -0
  34. data/lib/yoti_sandbox/profile/third_party.rb +158 -0
  35. data/lib/yoti_sandbox/profile/token_request.rb +47 -6
  36. data/yoti_sandbox.gemspec +18 -5
  37. metadata +38 -18
  38. data/.github/ISSUE_TEMPLATE.md +0 -17
  39. data/.gitignore +0 -56
  40. data/CONTRIBUTING.md +0 -30
  41. data/Guardfile +0 -11
  42. data/Rakefile +0 -41
  43. data/rubocop.yml +0 -44
  44. data/yardstick.yml +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee3b93e52cfe923f7311c9fb4e426c82f543d335d77986afce33a156020ebd49
4
- data.tar.gz: c364243f9462bce1e2d115b4d538353b34c764412109e5fdbde6587e90e07ad3
3
+ metadata.gz: 50664707d70da0ad9d28f183b68074c795f74ef59c05dbf4fbd1a0cef280d819
4
+ data.tar.gz: 6bae10a1f1675592f178d9ae1f47fdf3992196f1480a03e6a736b177a7638ea9
5
5
  SHA512:
6
- metadata.gz: 942ea35d3fb25a5d7b7cf9dc70c8bef7e61b15109295de0c56fabbb5ae15d8cf10fbb202a54b879cda88980ef940ceed2293fe0c0db3506a2318dce9c213f58d
7
- data.tar.gz: 965241d45bb97c05cd45c3d2a88c5ac843655ce427787c76b5a4b84c57fd4d9d2501f8a8f7a8317e7a55e81c780a768dd172e167e38623346acfb2522d20990d
6
+ metadata.gz: fe42559fa4b25d2a3f5d239471bfe86a0f1b59e00cb6c4bcb52cd895b52f2e2a4bf8087ce710d50be5514cf745e804204e245dac7f8bdf1dccf6157c9092efa1
7
+ data.tar.gz: 8de1edf888b5ede3604532ed62dd4210f7a55aa3de899c79062fefa980c37bd7d1ebf4045a40e9d879b5c87e83b3f2331d79985d7ecc447c1224a28f836afef7
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'guard'
4
4
  gem 'guard-rspec'
5
- gem 'rubocop'
5
+ gem 'rubocop', '~> 1.1', require: false
6
6
  gem 'rubocop-performance'
7
7
 
8
8
  gemspec
data/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Yoti Ruby Sandbox SDK
2
2
 
3
+ [![Build Status](https://travis-ci.com/getyoti/yoti-ruby-sdk-sandbox.svg?branch=master)](https://travis-ci.com/getyoti/yoti-ruby-sdk-sandbox)
4
+ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=getyoti%3Aruby-sandbox&metric=coverage)](https://sonarcloud.io/dashboard?id=getyoti%3Aruby-sandbox)
5
+ [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=getyoti%3Aruby-sandbox&metric=bugs)](https://sonarcloud.io/dashboard?id=getyoti%3Aruby-sandbox)
6
+ [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=getyoti%3Aruby-sandbox&metric=code_smells)](https://sonarcloud.io/dashboard?id=getyoti%3Aruby-sandbox)
7
+ [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=getyoti%3Aruby-sandbox&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=getyoti%3Aruby-sandbox)
8
+
3
9
  This repository contains the tools you need to test your Yoti integration.
4
10
 
5
11
  ## Installing the Sandbox
@@ -42,4 +48,5 @@ end
42
48
 
43
49
  ## Examples
44
50
 
45
- - See [examples/profile](examples/profile) for a general example of how to use the Profile Sandbox in your tests.
51
+ - [Profile Sandbox](examples/profile)
52
+ - [Doc Scan Sandbox](examples/doc_scan)
@@ -1 +1,2 @@
1
1
  require_relative 'yoti_sandbox/profile'
2
+ require_relative 'yoti_sandbox/doc_scan'
@@ -0,0 +1,25 @@
1
+ require 'yoti'
2
+
3
+ require_relative 'doc_scan/client'
4
+ require_relative 'doc_scan/errors'
5
+ require_relative 'doc_scan/request/task_results'
6
+ require_relative 'doc_scan/request/check_reports'
7
+ require_relative 'doc_scan/request/response_config'
8
+ require_relative 'doc_scan/request/document_filter'
9
+ require_relative 'doc_scan/request/check/check'
10
+ require_relative 'doc_scan/request/check/document_check'
11
+ require_relative 'doc_scan/request/check/document_authenticity_check'
12
+ require_relative 'doc_scan/request/check/id_document_comparison_check'
13
+ require_relative 'doc_scan/request/check/document_face_match_check'
14
+ require_relative 'doc_scan/request/check/document_text_data_check'
15
+ require_relative 'doc_scan/request/check/supplementary_document_text_data_check'
16
+ require_relative 'doc_scan/request/check/liveness_check'
17
+ require_relative 'doc_scan/request/check/zoom_liveness_check'
18
+ require_relative 'doc_scan/request/check/report/breakdown'
19
+ require_relative 'doc_scan/request/check/report/recommendation'
20
+ require_relative 'doc_scan/request/check/report/detail'
21
+ require_relative 'doc_scan/request/task/document_text_data_extraction_task'
22
+ require_relative 'doc_scan/request/task/supplementary_document_text_data_extraction_task'
23
+ require_relative 'doc_scan/request/task/document_id_photo'
24
+ require_relative 'doc_scan/request/task/text_data_extraction_recommendation'
25
+ require_relative 'doc_scan/request/task/text_data_extraction_reason'
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module Sandbox
5
+ module DocScan
6
+ #
7
+ # Client for the Doc Scan sandbox service
8
+ #
9
+ class Client
10
+ #
11
+ # @param [String] base_url
12
+ #
13
+ def initialize(base_url: nil)
14
+ @base_url = base_url || "#{Yoti.configuration.api_url}/sandbox/idverify/v1"
15
+ end
16
+
17
+ #
18
+ # @param [String] session_id
19
+ # @param [Yoti::SandboxDocScan::Request::ResponseConfig] response_config
20
+ #
21
+ def configure_session_response(session_id, response_config)
22
+ request = Yoti::Request
23
+ .builder
24
+ .with_http_method('PUT')
25
+ .with_base_url(@base_url)
26
+ .with_endpoint("sessions/#{session_id}/response-config")
27
+ .with_query_param('sdkId', Yoti.configuration.client_sdk_id)
28
+ .with_payload(response_config)
29
+ .build
30
+
31
+ begin
32
+ request.execute
33
+ rescue Yoti::RequestError => e
34
+ raise Yoti::Sandbox::DocScan::Error.wrap(e)
35
+ end
36
+ end
37
+
38
+ #
39
+ # @param [Yoti::SandboxDocScan::Request::ResponseConfig] response_config
40
+ #
41
+ def configure_application_response(response_config)
42
+ request = Yoti::Request
43
+ .builder
44
+ .with_http_method('PUT')
45
+ .with_base_url(@base_url)
46
+ .with_endpoint("apps/#{Yoti.configuration.client_sdk_id}/response-config")
47
+ .with_payload(response_config)
48
+ .build
49
+
50
+ begin
51
+ request.execute
52
+ rescue Yoti::RequestError => e
53
+ raise Yoti::Sandbox::DocScan::Error.wrap(e)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,83 @@
1
+ require 'json'
2
+
3
+ module Yoti
4
+ module Sandbox
5
+ module DocScan
6
+ #
7
+ # Raises exceptions related to Doc Scan Sandbox API requests
8
+ #
9
+ class Error < RequestError
10
+ def initialize(msg = nil, response = nil)
11
+ super(msg, response)
12
+
13
+ @default_message = msg
14
+ end
15
+
16
+ def message
17
+ @message ||= format_message
18
+ end
19
+
20
+ #
21
+ # Wraps an existing error
22
+ #
23
+ # @param [Error] error
24
+ #
25
+ # @return [self]
26
+ #
27
+ def self.wrap(error)
28
+ new(error.message, error.response)
29
+ end
30
+
31
+ private
32
+
33
+ #
34
+ # Formats error message from response.
35
+ #
36
+ # @return [String]
37
+ #
38
+ def format_message
39
+ return @default_message if @response.nil? || @response['Content-Type'] != 'application/json'
40
+
41
+ json = JSON.parse(@response.body)
42
+ format_response(json) || @default_message
43
+ end
44
+
45
+ #
46
+ # Format JSON error response.
47
+ #
48
+ # @param [Hash] json
49
+ #
50
+ # @return [String, nil]
51
+ #
52
+ def format_response(json)
53
+ return nil if json['code'].nil? || json['message'].nil?
54
+
55
+ code_message = "#{json['code']} - #{json['message']}"
56
+
57
+ unless json['errors'].nil?
58
+ property_errors = format_property_errors(json['errors'])
59
+
60
+ return "#{code_message}: #{property_errors.compact.join(', ')}" if property_errors.count.positive?
61
+ end
62
+
63
+ code_message
64
+ end
65
+
66
+ #
67
+ # Format property errors.
68
+ #
69
+ # @param [Array<Hash>] errors
70
+ #
71
+ # @return [Array<String>]
72
+ #
73
+ def format_property_errors(errors)
74
+ errors
75
+ .map do |e|
76
+ "#{e['property']} \"#{e['message']}\"" if e['property'] && e['message']
77
+ end
78
+ .compact
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module Sandbox
5
+ module DocScan
6
+ module Request
7
+ class Check
8
+ #
9
+ # @param [CheckResult] result
10
+ #
11
+ def initialize(result)
12
+ raise(TypeError, "#{self.class} cannot be instantiated") if instance_of?(Check)
13
+
14
+ Validation.assert_is_a(CheckResult, result, 'result')
15
+ @result = result
16
+ end
17
+
18
+ def to_json(*_args)
19
+ as_json.to_json
20
+ end
21
+
22
+ def as_json(*_args)
23
+ {
24
+ result: @result.as_json
25
+ }
26
+ end
27
+ end
28
+
29
+ class CheckBuilder
30
+ def initialize
31
+ @breakdowns = []
32
+ end
33
+
34
+ #
35
+ # @param [Recommendation] recommendation
36
+ #
37
+ # @return [self]
38
+ #
39
+ def with_recommendation(recommendation)
40
+ Validation.assert_is_a(Recommendation, recommendation, 'recommendation')
41
+ @recommendation = recommendation
42
+ self
43
+ end
44
+
45
+ #
46
+ # @param [Breakdown] breakdown
47
+ #
48
+ # @return [self]
49
+ #
50
+ def with_breakdown(breakdown)
51
+ Validation.assert_is_a(Breakdown, breakdown, 'breakdown')
52
+ @breakdowns.push(breakdown)
53
+ self
54
+ end
55
+
56
+ #
57
+ # @param [Array<Breakdown>] breakdowns
58
+ #
59
+ # @return [self]
60
+ #
61
+ def with_breakdowns(breakdowns)
62
+ Validation.assert_is_a(Array, breakdowns, 'breakdown')
63
+ @breakdowns = breakdowns
64
+ self
65
+ end
66
+ end
67
+
68
+ class CheckResult
69
+ #
70
+ # @param [CheckReport] report
71
+ #
72
+ def initialize(report)
73
+ Validation.assert_is_a(CheckReport, report, 'report')
74
+ @report = report
75
+ end
76
+
77
+ def to_json(*_args)
78
+ as_json.to_json
79
+ end
80
+
81
+ def as_json(*_args)
82
+ {
83
+ report: @report.as_json
84
+ }
85
+ end
86
+ end
87
+
88
+ class CheckReport
89
+ #
90
+ # @param [Recommendation] recommendation
91
+ # @param [Breakdown] breakdowns
92
+ #
93
+ def initialize(recommendation, breakdowns)
94
+ Validation.assert_is_a(Recommendation, recommendation, 'recommendation')
95
+ @recommendation = recommendation
96
+
97
+ Validation.assert_is_a(Array, breakdowns, 'breakdowns')
98
+ @breakdowns = breakdowns
99
+ end
100
+
101
+ def to_json(*_args)
102
+ as_json.to_json
103
+ end
104
+
105
+ def as_json(*_args)
106
+ {
107
+ recommendation: @recommendation.as_json,
108
+ breakdown: @breakdowns.map(&:as_json)
109
+ }
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module Sandbox
5
+ module DocScan
6
+ module Request
7
+ class DocumentAuthenticityCheck < DocumentCheck
8
+ #
9
+ # @return [DocumentAuthenticityCheckBuilder]
10
+ #
11
+ def self.builder
12
+ DocumentAuthenticityCheckBuilder.new
13
+ end
14
+ end
15
+
16
+ class DocumentAuthenticityCheckBuilder < DocumentCheckBuilder
17
+ #
18
+ # @return [DocumentAuthenticityCheck]
19
+ #
20
+ def build
21
+ report = CheckReport.new(@recommendation, @breakdowns)
22
+ result = CheckResult.new(report)
23
+ DocumentAuthenticityCheck.new(result, @document_filter)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module Sandbox
5
+ module DocScan
6
+ module Request
7
+ class DocumentCheck < Check
8
+ #
9
+ # @param [CheckResult] result
10
+ # @param [DocumentFilter] document_filter
11
+ #
12
+ def initialize(result, document_filter)
13
+ raise(TypeError, "#{self.class} cannot be instantiated") if instance_of?(DocumentCheck)
14
+
15
+ super(result)
16
+
17
+ Validation.assert_is_a(DocumentFilter, document_filter, 'document_filter', true)
18
+ @document_filter = document_filter
19
+ end
20
+
21
+ def as_json(*_args)
22
+ json = super
23
+ json[:document_filter] = @document_filter.as_json unless @document_filter.nil?
24
+ json
25
+ end
26
+ end
27
+
28
+ class DocumentCheckBuilder < CheckBuilder
29
+ def initialize
30
+ raise(TypeError, "#{self.class} cannot be instantiated") if instance_of?(DocumentCheckBuilder)
31
+
32
+ super
33
+ end
34
+
35
+ #
36
+ # @param [DocumentFilter] document_filter
37
+ #
38
+ # @return [self]
39
+ #
40
+ def with_document_filter(document_filter)
41
+ @document_filter = document_filter
42
+ self
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module Sandbox
5
+ module DocScan
6
+ module Request
7
+ class DocumentFaceMatchCheck < DocumentCheck
8
+ #
9
+ # @return [DocumentFaceMatchCheckBuilder]
10
+ #
11
+ def self.builder
12
+ DocumentFaceMatchCheckBuilder.new
13
+ end
14
+ end
15
+
16
+ class DocumentFaceMatchCheckBuilder < DocumentCheckBuilder
17
+ #
18
+ # @return [DocumentFaceMatchCheck]
19
+ #
20
+ def build
21
+ report = CheckReport.new(@recommendation, @breakdowns)
22
+ result = CheckResult.new(report)
23
+ DocumentFaceMatchCheck.new(result, @document_filter)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Yoti
6
+ module Sandbox
7
+ module DocScan
8
+ module Request
9
+ class DocumentTextDataCheck < DocumentCheck
10
+ #
11
+ # @return [DocumentTextDataCheckBuilder]
12
+ #
13
+ def self.builder
14
+ DocumentTextDataCheckBuilder.new
15
+ end
16
+ end
17
+
18
+ class DocumentTextDataCheckResult < CheckResult
19
+ #
20
+ # @param [CheckReport] report
21
+ # @param [Hash,nil] document_fields
22
+ #
23
+ def initialize(report, document_fields)
24
+ super(report)
25
+
26
+ unless document_fields.nil?
27
+ Validation.assert_is_a(Hash, document_fields, 'document_fields')
28
+ document_fields.each { |_k, v| Validation.assert_respond_to(:to_json, v, 'document_fields value') }
29
+ end
30
+ @document_fields = document_fields
31
+ end
32
+
33
+ def as_json(*_args)
34
+ super.merge(
35
+ document_fields: @document_fields
36
+ ).compact
37
+ end
38
+ end
39
+
40
+ class DocumentTextDataCheckBuilder < DocumentCheckBuilder
41
+ #
42
+ # @param [String] key
43
+ # @param [#to_json] value
44
+ #
45
+ # @return [self]
46
+ #
47
+ def with_document_field(key, value)
48
+ Validation.assert_is_a(String, key, 'key')
49
+ Validation.assert_respond_to(:to_json, value, 'value')
50
+ @document_fields ||= {}
51
+ @document_fields[key] = value
52
+ self
53
+ end
54
+
55
+ #
56
+ # @param [Hash] document_fields
57
+ #
58
+ # @return [self]
59
+ #
60
+ def with_document_fields(document_fields)
61
+ Validation.assert_is_a(Hash, document_fields, 'document_fields')
62
+ @document_fields = document_fields
63
+ self
64
+ end
65
+
66
+ #
67
+ # @return [DocumentTextDataCheck]
68
+ #
69
+ def build
70
+ report = CheckReport.new(@recommendation, @breakdowns)
71
+ result = DocumentTextDataCheckResult.new(report, @document_fields)
72
+ DocumentTextDataCheck.new(result, @document_filter)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end