yoti 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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