yoti 1.5.0 → 1.6.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 (45) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +0 -2
  3. data/README.md +1 -1
  4. data/Rakefile +8 -0
  5. data/lib/yoti.rb +16 -0
  6. data/lib/yoti/activity_details.rb +17 -2
  7. data/lib/yoti/client.rb +2 -1
  8. data/lib/yoti/data_type/age_verification.rb +54 -0
  9. data/lib/yoti/data_type/attribute.rb +3 -0
  10. data/lib/yoti/data_type/base_profile.rb +13 -0
  11. data/lib/yoti/data_type/document_details.rb +96 -0
  12. data/lib/yoti/data_type/profile.rb +76 -0
  13. data/lib/yoti/dynamic_share_service/dynamic_scenario.rb +67 -0
  14. data/lib/yoti/dynamic_share_service/extension/extension.rb +45 -0
  15. data/lib/yoti/dynamic_share_service/extension/location_constraint_extension.rb +88 -0
  16. data/lib/yoti/dynamic_share_service/extension/thirdparty_attribute_extension.rb +58 -0
  17. data/lib/yoti/dynamic_share_service/extension/transactional_flow_extension.rb +47 -0
  18. data/lib/yoti/dynamic_share_service/policy/dynamic_policy.rb +184 -0
  19. data/lib/yoti/dynamic_share_service/policy/source_constraint.rb +88 -0
  20. data/lib/yoti/dynamic_share_service/policy/wanted_anchor.rb +53 -0
  21. data/lib/yoti/dynamic_share_service/policy/wanted_attribute.rb +85 -0
  22. data/lib/yoti/dynamic_share_service/share_url.rb +80 -0
  23. data/lib/yoti/http/profile_request.rb +1 -0
  24. data/lib/yoti/http/request.rb +13 -0
  25. data/lib/yoti/http/signed_request.rb +0 -3
  26. data/lib/yoti/protobuf/main.rb +11 -0
  27. data/lib/yoti/protobuf/sharepubapi/DataEntry_pb.rb +29 -0
  28. data/lib/yoti/protobuf/sharepubapi/ExtraData_pb.rb +19 -0
  29. data/lib/yoti/protobuf/sharepubapi/IssuingAttributes_pb.rb +23 -0
  30. data/lib/yoti/protobuf/sharepubapi/ThirdPartyAttribute_pb.rb +20 -0
  31. data/lib/yoti/sandbox.rb +5 -0
  32. data/lib/yoti/sandbox/anchor.rb +49 -0
  33. data/lib/yoti/sandbox/attribute.rb +52 -0
  34. data/lib/yoti/sandbox/profile.rb +171 -0
  35. data/lib/yoti/sandbox/sandbox.rb +105 -0
  36. data/lib/yoti/sandbox/sandbox_client.rb +45 -0
  37. data/lib/yoti/share/attribute_issuance_details.rb +43 -0
  38. data/lib/yoti/share/extra_data.rb +25 -0
  39. data/lib/yoti/ssl.rb +7 -0
  40. data/lib/yoti/util/age_processor.rb +4 -0
  41. data/lib/yoti/version.rb +1 -1
  42. data/rubocop.yml +4 -0
  43. data/yoti.gemspec +4 -2
  44. metadata +61 -4
  45. data/.travis.yml +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 00ff1a296c371b2d5e94ccd5e0951963ff8cbcf9676717724369567e39ef1652
4
- data.tar.gz: e80cb02c9f2cd4b9fdab9ac59de05aeee58cdc1066229a0bde35f4310052d562
2
+ SHA1:
3
+ metadata.gz: 691432df23cdd73c562aedd1f85ea6077ce38508
4
+ data.tar.gz: ba22b06a08a95aaff4c3309e1e7c1db4195f4a10
5
5
  SHA512:
6
- metadata.gz: 74652cb02c63be28c4296c47e073f756baf3836289cf71f646949a36d870716a7851dbe2c4c78f9fb3b771e08213d6035e1bb2508a0a4fbae340d1964d4754a5
7
- data.tar.gz: '019dd78cc18bdfeb6bb2b852cd3ae8331062f4a5d7af312882aa143818af75ea7fc7e15e3dddf96d30c32b208c13a56327eeebc509415502a888442bd45e7b4b'
6
+ metadata.gz: b8fba42c58a939ffbd6f66d97e2970cc34a705e1b3f04ccffb5fddba494a8f273de9aadb6d9c88b5c3cd6be8a673655c23347f35da303f7f408c74cc22747155
7
+ data.tar.gz: de2c82706cd19db939a182e45134c3d0aaf282cb1b0785e443e8691cf419b76250921ad0507f84987206c3075fdf127fa4b2d1b554d499764dc95f1db43c86cd
data/Gemfile CHANGED
@@ -2,8 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'guard'
4
4
  gem 'guard-rspec'
5
- gem 'pry'
6
- gem 'pry-byebug'
7
5
  gem 'rubocop'
8
6
  gem 'rubocop-performance'
9
7
 
data/README.md CHANGED
@@ -270,7 +270,7 @@ The examples can be found in the [examples folder](examples).
270
270
  ### Ruby on Rails
271
271
 
272
272
  1. Create your application in the [Yoti Hub](https://hub.yoti.com)
273
- 1. Set the application domain of your app to `localhost:3000`
273
+ 1. Set the application domain of your app to `localhost:3001`
274
274
  1. Set the scenario callback URL to `/profile`
275
275
  1. Rename the [.env.example](examples/rails/.env.example) file to `.env`
276
276
  1. Fill in the environment variables in this file with the ones specific to your application (mentioned in the [Configuration](#configuration) section)
data/Rakefile CHANGED
@@ -9,6 +9,14 @@ require 'yaml'
9
9
  RSpec::Core::RakeTask.new
10
10
  task test: :spec
11
11
 
12
+ ################################
13
+ # Coveralls #
14
+ ################################
15
+
16
+ require 'coveralls/rake/task'
17
+ Coveralls::RakeTask.new
18
+ task test_with_coveralls: [:spec, 'coveralls:push']
19
+
12
20
  ################################
13
21
  # Rubocop #
14
22
  ################################
data/lib/yoti.rb CHANGED
@@ -12,6 +12,7 @@ require_relative 'yoti/http/profile_request'
12
12
  require_relative 'yoti/http/request'
13
13
 
14
14
  require_relative 'yoti/data_type/anchor'
15
+ require_relative 'yoti/data_type/age_verification'
15
16
  require_relative 'yoti/data_type/base_profile'
16
17
  require_relative 'yoti/data_type/application_profile'
17
18
  require_relative 'yoti/data_type/profile'
@@ -21,6 +22,7 @@ require_relative 'yoti/data_type/image'
21
22
  require_relative 'yoti/data_type/image_jpeg'
22
23
  require_relative 'yoti/data_type/image_png'
23
24
  require_relative 'yoti/data_type/multi_value'
25
+ require_relative 'yoti/data_type/document_details'
24
26
 
25
27
  require_relative 'yoti/util/age_processor'
26
28
  require_relative 'yoti/util/anchor_processor'
@@ -31,6 +33,20 @@ require_relative 'yoti/client'
31
33
 
32
34
  require_relative 'yoti/protobuf/main'
33
35
 
36
+ require_relative 'yoti/dynamic_share_service/share_url'
37
+ require_relative 'yoti/dynamic_share_service/policy/wanted_attribute'
38
+ require_relative 'yoti/dynamic_share_service/policy/wanted_anchor'
39
+ require_relative 'yoti/dynamic_share_service/policy/source_constraint'
40
+ require_relative 'yoti/dynamic_share_service/policy/dynamic_policy'
41
+ require_relative 'yoti/dynamic_share_service/dynamic_scenario'
42
+ require_relative 'yoti/dynamic_share_service/extension/extension'
43
+ require_relative 'yoti/dynamic_share_service/extension/location_constraint_extension'
44
+ require_relative 'yoti/dynamic_share_service/extension/transactional_flow_extension'
45
+ require_relative 'yoti/dynamic_share_service/extension/thirdparty_attribute_extension'
46
+
47
+ require_relative 'yoti/share/extra_data'
48
+ require_relative 'yoti/share/attribute_issuance_details'
49
+
34
50
  # The main module namespace of the Yoti gem
35
51
  module Yoti
36
52
  class << self
@@ -60,6 +60,11 @@ module Yoti
60
60
  #
61
61
  # The age under/over attribute
62
62
  #
63
+ # @deprecated 2.0.0 - replaced by:
64
+ # - Yoti::Profile#age_verifications
65
+ # - Yoti::Profile#find_age_over_verification
66
+ # - Yoti::Profile#find_age_under_verification
67
+ #
63
68
  # @return [Boolean]
64
69
  #
65
70
  attr_reader :age_verified
@@ -78,11 +83,18 @@ module Yoti
78
83
  #
79
84
  attr_reader :timestamp
80
85
 
86
+ #
87
+ # Extra data
88
+ #
89
+ # @return [ExtraData]
90
+ #
91
+ attr_reader :extra_data
92
+
81
93
  #
82
94
  # @param receipt [Hash] the receipt from the API request
83
95
  # @param decrypted_profile [Object] Protobuf AttributeList decrypted object containing the profile attributes
84
96
  #
85
- def initialize(receipt, decrypted_profile = nil, decrypted_application_profile = nil)
97
+ def initialize(receipt, decrypted_profile = nil, decrypted_application_profile = nil, extra_data = nil)
86
98
  @remember_me_id = receipt['remember_me_id']
87
99
  @user_id = @remember_me_id
88
100
  @receipt_id = receipt['receipt_id']
@@ -91,6 +103,7 @@ module Yoti
91
103
  @timestamp = receipt['timestamp'] ? Time.parse(receipt['timestamp']) : nil
92
104
  @extended_user_profile = process_decrypted_profile(decrypted_profile)
93
105
  @extended_application_profile = process_decrypted_profile(decrypted_application_profile)
106
+ @extra_data = Share::ExtraData.new(extra_data) if extra_data
94
107
  @user_profile = @extended_user_profile.map do |name, attribute|
95
108
  [name, attribute.value]
96
109
  end.to_h
@@ -99,7 +112,7 @@ module Yoti
99
112
  #
100
113
  # The user's structured postal address as JSON
101
114
  #
102
- # @deprecated replaced by Profile.structured_postal_address
115
+ # @deprecated replaced by Yoti::Profile#structured_postal_address
103
116
  #
104
117
  # @return [Hash]
105
118
  #
@@ -178,6 +191,8 @@ module Yoti
178
191
  #
179
192
  # Processes age verification
180
193
  #
194
+ # @deprecated 2.0.0
195
+ #
181
196
  # @param [Yoti::Protobuf::Attrpubapi::Attribute] attribute
182
197
  #
183
198
  def process_age_verified(attribute)
data/lib/yoti/client.rb CHANGED
@@ -15,10 +15,11 @@ module Yoti
15
15
  receipt = Yoti::ProfileRequest.new(encrypted_connect_token).receipt
16
16
  user_profile = Protobuf.user_profile(receipt)
17
17
  application_profile = Protobuf.application_profile(receipt)
18
+ extra_data = Protobuf.extra_data(receipt)
18
19
 
19
20
  return ActivityDetails.new(receipt) if user_profile.nil?
20
21
 
21
- ActivityDetails.new(receipt, user_profile, application_profile)
22
+ ActivityDetails.new(receipt, user_profile, application_profile, extra_data)
22
23
  end
23
24
 
24
25
  def self.aml_check(aml_profile)
@@ -0,0 +1,54 @@
1
+ module Yoti
2
+ #
3
+ # Wraps an 'Age Verify/Condition' attribute to provide behaviour specific
4
+ # to verifying someone's age.
5
+ #
6
+ class AgeVerification
7
+ #
8
+ # The wrapped profile attribute.
9
+ #
10
+ # Use this if you need access to the underlying list of Anchors.
11
+ #
12
+ # @return [Yoti::Attribute]
13
+ #
14
+ attr_reader :attribute
15
+
16
+ #
17
+ # Whether or not the profile passed the age check.
18
+ #
19
+ # @return [Boolean]
20
+ #
21
+ attr_reader :result
22
+
23
+ #
24
+ # The type of age check performed, as specified on Yoti Hub.
25
+ #
26
+ # Among the possible values are 'age_over' and 'age_under'.
27
+ #
28
+ # @return [String]
29
+ #
30
+ attr_reader :check_type
31
+
32
+ #
33
+ # The age that was that checked, as specified on Yoti Hub.
34
+ #
35
+ # @return [Integer]
36
+ #
37
+ attr_reader :age
38
+
39
+ #
40
+ # @param [Yoti::Attribute]
41
+ #
42
+ def initialize(attribute)
43
+ raise(ArgumentError, "'#{attribute.name}' is not a valid age verification") unless /^[^:]+:(?!.*:)[0-9]+$/.match?(attribute.name)
44
+
45
+ @attribute = attribute
46
+
47
+ split = attribute.name.split(':')
48
+ @check_type = split[0]
49
+
50
+ @age = split[1].to_i
51
+ @result = attribute.value == 'true'
52
+ end
53
+ end
54
+ end
@@ -21,10 +21,13 @@ module Yoti
21
21
  POSTAL_ADDRESS = 'postal_address'
22
22
  STRUCTURED_POSTAL_ADDRESS = 'structured_postal_address'
23
23
  DOCUMENT_IMAGES = 'document_images'
24
+ DOCUMENT_DETAILS = 'document_details'
24
25
  APPLICATION_NAME = 'application_name'
25
26
  APPLICATION_LOGO = 'application_logo'
26
27
  APPLICATION_URL = 'application_url'
27
28
  APPLICATION_RECEIPT_BGCOLOR = 'application_receipt_bgcolor'
29
+ AGE_OVER = 'age_over:'
30
+ AGE_UNDER = 'age_under:'
28
31
 
29
32
  #
30
33
  # Gets the name of the attribute.
@@ -29,5 +29,18 @@ module Yoti
29
29
 
30
30
  @attributes[attr_name]
31
31
  end
32
+
33
+ protected
34
+
35
+ #
36
+ # Find attributes starting with provided name.
37
+ #
38
+ # @param [String] name
39
+ #
40
+ # @returns [Array]
41
+ #
42
+ def find_attributes_starting_with(name)
43
+ @attributes.select { |key| key.to_s.start_with?(name) }
44
+ end
32
45
  end
33
46
  end
@@ -0,0 +1,96 @@
1
+ module Yoti
2
+ class DocumentDetails
3
+ #
4
+ # The values of the Document Details are in the format and order as defined in this pattern
5
+ # e.g PASS_CARD GBR 22719564893 - CITIZENCARD, the last two are optionals
6
+ #
7
+ VALIDATION_PATTERN = '^([A-Za-z_]*) ([A-Za-z]{3}) ([A-Za-z0-9]{1}).*$'
8
+ TYPE_INDEX = 0
9
+ COUNTRY_INDEX = 1
10
+ NUMBER_INDEX = 2
11
+ EXPIRATION_INDEX = 3
12
+ AUTHORITY_INDEX = 4
13
+
14
+ #
15
+ # Type of the document e.g. PASSPORT | DRIVING_LICENCE | NATIONAL_ID | PASS_CARD
16
+ #
17
+ # @return [String]
18
+ #
19
+ attr_reader :type
20
+
21
+ #
22
+ # ISO-3166-1 alpha-3 country code, e.g. "GBR"
23
+ #
24
+ # @return [String]
25
+ #
26
+ attr_reader :issuing_country
27
+
28
+ #
29
+ # Document number (may include letters) from the document.
30
+ #
31
+ # @return [String]
32
+ #
33
+ attr_reader :document_number
34
+
35
+ #
36
+ # Expiration date of the document in DateTime format. If the document does not expire, this
37
+ # field will not be present. The time part of this DateTime will default to 00:00:00.
38
+ #
39
+ # @return [DateTime]
40
+ #
41
+ attr_reader :expiration_date
42
+
43
+ #
44
+ # Can either be a country code (for a state), or the name of the issuing authority.
45
+ #
46
+ # @return [String]
47
+ #
48
+ attr_reader :issuing_authority
49
+
50
+ #
51
+ # @param [String] value
52
+ #
53
+ def initialize(value)
54
+ validate_value(value)
55
+ parse_value(value)
56
+ end
57
+
58
+ private
59
+
60
+ #
61
+ # Asserts provided matches VALIDATION_PATTERN
62
+ #
63
+ # @param [String] value
64
+ #
65
+ def validate_value(value)
66
+ raise(ArgumentError, "Invalid value for #{self.class.name}") unless /#{VALIDATION_PATTERN}/.match?(value)
67
+ end
68
+
69
+ #
70
+ # Parses provided value into separate attributes
71
+ #
72
+ # @param [String] value
73
+ #
74
+ def parse_value(value)
75
+ attributes = value.split(' ')
76
+ @type = attributes[TYPE_INDEX]
77
+ @issuing_country = attributes[COUNTRY_INDEX]
78
+ @document_number = attributes[NUMBER_INDEX]
79
+ @expiration_date = parse_date_from_string(attributes[EXPIRATION_INDEX]) if attributes.length > 3
80
+ @issuing_authority = attributes[AUTHORITY_INDEX] if attributes.length > 4
81
+ end
82
+
83
+ #
84
+ # Converts provided date string into DateTime
85
+ #
86
+ # @param [String] date_string
87
+ #
88
+ # @return [DateTime]
89
+ #
90
+ def parse_date_from_string(date_string)
91
+ return nil if date_string == '-'
92
+
93
+ DateTime.iso8601(date_string)
94
+ end
95
+ end
96
+ end
@@ -1,3 +1,5 @@
1
+ require_relative 'base_profile'
2
+
1
3
  module Yoti
2
4
  #
3
5
  # Encapsulates Yoti user profile
@@ -116,6 +118,47 @@ module Yoti
116
118
  get_attribute(Yoti::Attribute::STRUCTURED_POSTAL_ADDRESS)
117
119
  end
118
120
 
121
+ #
122
+ # Document Details.
123
+ #
124
+ # @return [Attribute, nil]
125
+ #
126
+ def document_details
127
+ get_attribute(Yoti::Attribute::DOCUMENT_DETAILS)
128
+ end
129
+
130
+ # Finds all the 'Age Over' and 'Age Under' derived attributes returned with the profile,
131
+ # and returns them wrapped in AgeVerification objects
132
+ #
133
+ # @return [Array]
134
+ #
135
+ def age_verifications
136
+ find_all_age_verifications
137
+ @age_verifications.values
138
+ end
139
+
140
+ #
141
+ # Searches for an AgeVerification corresponding to an 'Age Over' check for the given age
142
+ #
143
+ # @param [Integer] age
144
+ #
145
+ # @return [AgeVerification|nil]
146
+ #
147
+ def find_age_over_verification(age)
148
+ find_age_verification(Yoti::Attribute::AGE_OVER, age)
149
+ end
150
+
151
+ #
152
+ # Searches for an AgeVerification corresponding to an 'Age Under' check for the given age.
153
+ #
154
+ # @param [Integer] age
155
+ #
156
+ # @return [AgeVerification|nil]
157
+ #
158
+ def find_age_under_verification(age)
159
+ find_age_verification(Yoti::Attribute::AGE_UNDER, age)
160
+ end
161
+
119
162
  protected
120
163
 
121
164
  #
@@ -134,5 +177,38 @@ module Yoti
134
177
  structured_postal_address.verifiers
135
178
  )
136
179
  end
180
+
181
+ private
182
+
183
+ #
184
+ # Searches for an AgeVerification corresponding to provided type and age.
185
+ #
186
+ # @param [String] type
187
+ # @param [Integer] age
188
+ #
189
+ # @return [Yoti::AgeVerification|nil]
190
+ #
191
+ def find_age_verification(type, age)
192
+ raise(ArgumentError, "#{age} is not a valid age") unless age.is_a?(Integer)
193
+
194
+ find_all_age_verifications
195
+ @age_verifications[type + age.to_s] || nil
196
+ end
197
+
198
+ #
199
+ # Find all age verifications and put in key value Hash.
200
+ #
201
+ def find_all_age_verifications
202
+ return @age_verifications unless @age_verifications.nil?
203
+
204
+ @age_verifications = {}
205
+
206
+ find_attributes_starting_with(Yoti::Attribute::AGE_OVER).each do |_name, attribute|
207
+ @age_verifications[attribute.name] = Yoti::AgeVerification.new(attribute)
208
+ end
209
+ find_attributes_starting_with(Yoti::Attribute::AGE_UNDER).each do |_name, attribute|
210
+ @age_verifications[attribute.name] = Yoti::AgeVerification.new(attribute)
211
+ end
212
+ end
137
213
  end
138
214
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ # Describes a dynamic share
6
+ class DynamicScenario
7
+ attr_reader :policy
8
+ attr_reader :extensions
9
+ attr_reader :callback_endpoint
10
+
11
+ def initialize
12
+ @extensions = []
13
+ end
14
+
15
+ def to_json(*_args)
16
+ as_json.to_json
17
+ end
18
+
19
+ def as_json(*_args)
20
+ {
21
+ policy: @policy,
22
+ extensions: @extensions,
23
+ callback_endpoint: @callback_endpoint
24
+ }
25
+ end
26
+
27
+ def self.builder
28
+ DynamicScenarioBuilder.new
29
+ end
30
+ end
31
+
32
+ # Builder for DynamicScenario
33
+ class DynamicScenarioBuilder
34
+ def initialize
35
+ @scenario = DynamicScenario.new
36
+ end
37
+
38
+ def build
39
+ Marshal.load Marshal.dump @scenario
40
+ end
41
+
42
+ #
43
+ # @param [Yoti::DynamicSharingService::DynamicPolicy] policy
44
+ #
45
+ def with_policy(policy)
46
+ @scenario.instance_variable_set(:@policy, policy)
47
+ self
48
+ end
49
+
50
+ #
51
+ # @param [Yoti::DynamicSharingService::Extension] extension
52
+ #
53
+ def with_extension(extension)
54
+ @scenario.instance_variable_get(:@extensions) << extension
55
+ self
56
+ end
57
+
58
+ #
59
+ # @param [String] endpoint
60
+ #
61
+ def with_callback_endpoint(endpoint)
62
+ @scenario.instance_variable_set(:@callback_endpoint, endpoint)
63
+ self
64
+ end
65
+ end
66
+ end
67
+ end