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
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ class Extension
6
+ attr_reader :type
7
+ attr_reader :content
8
+
9
+ def to_json(*_args)
10
+ as_json.to_json
11
+ end
12
+
13
+ def as_json(*_args)
14
+ {
15
+ type: @type,
16
+ content: @content
17
+ }
18
+ end
19
+
20
+ def self.builder
21
+ ExtensionBuilder.new
22
+ end
23
+ end
24
+
25
+ class ExtensionBuilder
26
+ def initialize
27
+ @extension = Extension.new
28
+ end
29
+
30
+ def with_type(type)
31
+ @extension.instance_variable_set(:@type, type)
32
+ self
33
+ end
34
+
35
+ def with_content(content)
36
+ @extension.instance_variable_set(:@content, content)
37
+ self
38
+ end
39
+
40
+ def build
41
+ Marshal.load Marshal.dump @extension
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ # A Location Constraint
6
+ class LocationConstraintExtension
7
+ EXTENSION_TYPE = 'LOCATION_CONSTRAINT'
8
+
9
+ attr_reader :content
10
+ attr_reader :type
11
+
12
+ def initialize
13
+ @content = {}
14
+ @type = EXTENSION_TYPE
15
+ end
16
+
17
+ def as_json(*_args)
18
+ {
19
+ type: @type,
20
+ content: @content
21
+ }
22
+ end
23
+
24
+ def to_json(*_args)
25
+ as_json.to_json
26
+ end
27
+
28
+ def self.builder
29
+ LocationConstraintExtensionBuilder.new
30
+ end
31
+ end
32
+
33
+ # Builder for LocationConstraintExtension
34
+ class LocationConstraintExtensionBuilder
35
+ def with_latitude(latitude)
36
+ raise ArgumentError, 'Latitude must be Integer or Float'\
37
+ unless latitude.is_a?(Integer) || latitude.is_a?(Float)
38
+ raise ArgumentError, 'Latitude must be between -90 and 90'\
39
+ unless latitude >= -90 && latitude <= 90
40
+
41
+ @latitude = latitude
42
+ self
43
+ end
44
+
45
+ def with_longitude(longitude)
46
+ raise ArgumentError, 'Longitude must be Integer or Float'\
47
+ unless longitude.is_a?(Integer) || longitude.is_a?(Float)
48
+ raise ArgumentError, 'Longitude must be between -180 and 180'\
49
+ unless longitude >= -180 && longitude <= 180
50
+
51
+ @longitude = longitude
52
+ self
53
+ end
54
+
55
+ def with_radius(radius)
56
+ raise ArgumentError, 'Radius must be Integer or Float'\
57
+ unless radius.is_a?(Integer) || radius.is_a?(Float)
58
+ raise ArgumentError, 'Radius must be >= 0' unless radius >= 0
59
+
60
+ @radius = radius
61
+ self
62
+ end
63
+
64
+ def with_max_uncertainty(uncertainty)
65
+ raise ArgumentError, 'Uncertainty must be Integer or Float'\
66
+ unless uncertainty.is_a?(Integer) || uncertainty.is_a?(Float)
67
+ raise ArgumentError, 'Uncertainty must be >= 0' unless uncertainty >= 0
68
+
69
+ @uncertainty = uncertainty
70
+ self
71
+ end
72
+
73
+ def build
74
+ @radius ||= 150 unless @radius
75
+ @uncertainty ||= 150 unless @uncertainty
76
+
77
+ extension = LocationConstraintExtension.new
78
+ extension.instance_variable_get(:@content)[:expected_device_location] = {
79
+ latitude: @latitude,
80
+ longitude: @longitude,
81
+ radius: @radius,
82
+ max_uncertainty_radius: @uncertainty
83
+ }
84
+ extension
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ class ThirdPartyAttributeExtensionBuilder
6
+ def initialize
7
+ @expiry_date = nil
8
+ @definitions = []
9
+ end
10
+
11
+ def with_expiry_date(expiry_date)
12
+ @expiry_date = expiry_date
13
+ self
14
+ end
15
+
16
+ def with_definitions(*names)
17
+ names.each do |s|
18
+ @definitions += [{ name: s }]
19
+ end
20
+ self
21
+ end
22
+
23
+ def build
24
+ extension = ThirdPartyAttributeExtension.new
25
+ extension.instance_variable_get(:@content)[:expiry_date] = @expiry_date
26
+ extension.instance_variable_get(:@content)[:definitions] = @definitions
27
+ extension
28
+ end
29
+ end
30
+
31
+ class ThirdPartyAttributeExtension
32
+ EXTENSION_TYPE = 'THIRD_PARTY_ATTRIBUTE'
33
+
34
+ attr_reader :content
35
+ attr_reader :type
36
+
37
+ def initialize
38
+ @content = {}
39
+ @type = EXTENSION_TYPE
40
+ end
41
+
42
+ def as_json(*_args)
43
+ {
44
+ type: @type,
45
+ content: @content
46
+ }
47
+ end
48
+
49
+ def to_json(*_args)
50
+ as_json.to_json
51
+ end
52
+
53
+ def self.builder
54
+ ThirdPartyAttributeExtensionBuilder.new
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ # Extension for transactional flows
6
+ class TransactionalFlowExtension
7
+ EXTENSION_TYPE = 'TRANSACTIONAL_FLOW'
8
+ attr_reader :content
9
+ attr_reader :type
10
+
11
+ def initialize
12
+ @type = EXTENSION_TYPE
13
+ end
14
+
15
+ def to_json(*_args)
16
+ as_json.to_json
17
+ end
18
+
19
+ def as_json(*_args)
20
+ {
21
+ content: @content,
22
+ type: @type
23
+ }
24
+ end
25
+
26
+ def self.builder
27
+ TransactionalFlowExtensionBuilder.new
28
+ end
29
+ end
30
+
31
+ # Builder for TransactionalFlowExtension
32
+ class TransactionalFlowExtensionBuilder
33
+ def initialize
34
+ @extension = TransactionalFlowExtension.new
35
+ end
36
+
37
+ def with_content(content)
38
+ @extension.instance_variable_set(:@content, content)
39
+ self
40
+ end
41
+
42
+ def build
43
+ Marshal.load Marshal.dump @extension
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ # Describes a policy for a dynamic share
6
+ class DynamicPolicy
7
+ SELFIE_AUTH_TYPE = 1
8
+ PIN_AUTH_TYPE = 2
9
+
10
+ attr_reader :wanted_auth_types
11
+ attr_reader :wanted
12
+
13
+ def wanted_remember_me
14
+ return true if @wanted_remember_me
15
+
16
+ false
17
+ end
18
+
19
+ def to_json(*args)
20
+ as_json.to_json(*args)
21
+ end
22
+
23
+ def as_json(*_args)
24
+ {
25
+ wanted_auth_types: @wanted_auth_types,
26
+ wanted: @wanted
27
+ }
28
+ end
29
+
30
+ def self.builder
31
+ DynamicPolicyBuilder.new
32
+ end
33
+ end
34
+
35
+ # Builder for DynamicPolicy
36
+ class DynamicPolicyBuilder
37
+ def initialize
38
+ @policy = DynamicPolicy.new
39
+ @wanted_auth_types = {}
40
+ @wanted_attributes = {}
41
+ end
42
+
43
+ def build
44
+ @policy.instance_variable_set(
45
+ :@wanted_auth_types,
46
+ @wanted_auth_types
47
+ .select { |_, wanted| wanted }
48
+ .keys
49
+ )
50
+ @policy.instance_variable_set(:@wanted, @wanted_attributes.values)
51
+ Marshal.load Marshal.dump @policy
52
+ end
53
+
54
+ #
55
+ # @param [Bool] wanted
56
+ #
57
+ def with_wanted_remember_me(wanted = true)
58
+ @policy.instance_variable_set(:@wanted_remember_me, wanted)
59
+ self
60
+ end
61
+
62
+ #
63
+ # @param [Integer] auth
64
+ # @param [Bool] wanted
65
+ #
66
+ def with_wanted_auth_type(auth, wanted = true)
67
+ @wanted_auth_types[auth] = wanted
68
+ self
69
+ end
70
+
71
+ #
72
+ # @param [Bool] wanted
73
+ #
74
+ def with_selfie_auth(wanted = true)
75
+ with_wanted_auth_type(DynamicPolicy::SELFIE_AUTH_TYPE, wanted)
76
+ end
77
+
78
+ #
79
+ # @param [Bool] wanted
80
+ #
81
+ def with_pin_auth(wanted = true)
82
+ with_wanted_auth_type(DynamicPolicy::PIN_AUTH_TYPE, wanted)
83
+ end
84
+
85
+ #
86
+ # @param [Yoti::DynamicSharingService::WantedAttribute] attribute
87
+ #
88
+ def with_wanted_attribute(attribute)
89
+ key = attribute.derivation || attribute.name
90
+ @wanted_attributes[key] = attribute
91
+ self
92
+ end
93
+
94
+ #
95
+ # @param [String] name
96
+ # @param [Hash] constraints
97
+ #
98
+ def with_wanted_attribute_by_name(name, constraints: nil)
99
+ attribute_builder = WantedAttribute.builder.with_name(name)
100
+ constraints&.each do |constraint|
101
+ attribute_builder.with_constraint constraint
102
+ end
103
+ attribute = attribute_builder.build
104
+ with_wanted_attribute attribute
105
+ end
106
+
107
+ def with_family_name(options = {})
108
+ with_wanted_attribute_by_name Attribute::FAMILY_NAME, options
109
+ end
110
+
111
+ def with_given_names(options = {})
112
+ with_wanted_attribute_by_name Attribute::GIVEN_NAMES, options
113
+ end
114
+
115
+ def with_full_name(options = {})
116
+ with_wanted_attribute_by_name Attribute::FULL_NAME, options
117
+ end
118
+
119
+ def with_date_of_birth(options = {})
120
+ with_wanted_attribute_by_name Attribute::DATE_OF_BIRTH, options
121
+ end
122
+
123
+ #
124
+ # @param [String] derivation
125
+ # @param [Hash] constraints
126
+ #
127
+ def with_age_derived_attribute(derivation, constraints: nil)
128
+ attribute_builder = WantedAttribute.builder
129
+ attribute_builder.with_name(Attribute::DATE_OF_BIRTH)
130
+ attribute_builder.with_derivation(derivation)
131
+ constraints&.each do |constraint|
132
+ attribute_builder.with_constraint constraint
133
+ end
134
+ with_wanted_attribute(attribute_builder.build)
135
+ end
136
+
137
+ #
138
+ # @param [Integer] derivation
139
+ #
140
+ def with_age_over(age, options = {})
141
+ with_age_derived_attribute(Attribute::AGE_OVER + age.to_s, options)
142
+ end
143
+
144
+ #
145
+ # @param [Integer] derivation
146
+ #
147
+ def with_age_under(age, options = {})
148
+ with_age_derived_attribute(Attribute::AGE_UNDER + age.to_s, options)
149
+ end
150
+
151
+ def with_gender(options = {})
152
+ with_wanted_attribute_by_name Attribute::GENDER, options
153
+ end
154
+
155
+ def with_postal_address(options = {})
156
+ with_wanted_attribute_by_name(Attribute::POSTAL_ADDRESS, options)
157
+ end
158
+
159
+ def with_structured_postal_address(options = {})
160
+ with_wanted_attribute_by_name(Attribute::STRUCTURED_POSTAL_ADDRESS, options)
161
+ end
162
+
163
+ def with_nationality(options = {})
164
+ with_wanted_attribute_by_name(Attribute::NATIONALITY, options)
165
+ end
166
+
167
+ def with_phone_number(options = {})
168
+ with_wanted_attribute_by_name(Attribute::PHONE_NUMBER, options)
169
+ end
170
+
171
+ def with_selfie(options = {})
172
+ with_wanted_attribute_by_name(Attribute::SELFIE, options)
173
+ end
174
+
175
+ def with_email(options = {})
176
+ with_wanted_attribute_by_name(Attribute::EMAIL_ADDRESS, options)
177
+ end
178
+
179
+ def with_document_details
180
+ with_wanted_attribute_by_name(Attribute::DOCUMENT_DETAILS)
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ # A list of anchors to require for a dynamic share
6
+ class SourceConstraint
7
+ DRIVING_LICENCE = 'DRIVING_LICENCE'
8
+ PASSPORT = 'PASSPORT'
9
+ NATIONAL_ID = 'NATIONAL_ID'
10
+ PASS_CARD = 'PASS_CARD'
11
+
12
+ SOURCE_CONSTRAINT = 'SOURCE'
13
+
14
+ attr_reader :anchors
15
+
16
+ def soft_preference
17
+ return @soft_preference if @soft_preference
18
+
19
+ false
20
+ end
21
+
22
+ def to_json(*_args)
23
+ as_json.to_json
24
+ end
25
+
26
+ def as_json(*_args)
27
+ obj = {
28
+ type: SOURCE_CONSTRAINT,
29
+ preferred_sources: {
30
+ anchors: @anchors.map(&:as_json)
31
+ }
32
+ }
33
+ obj[:preferred_sources][:soft_preference] = @soft_preference unless @soft_preference.nil?
34
+ obj
35
+ end
36
+
37
+ def initialize
38
+ @anchors = []
39
+ end
40
+
41
+ def self.builder
42
+ SourceConstraintBuilder.new
43
+ end
44
+ end
45
+
46
+ # Builder for SourceConstraint
47
+ class SourceConstraintBuilder
48
+ def initialize
49
+ @constraint = SourceConstraint.new
50
+ end
51
+
52
+ def with_anchor_by_value(value, sub_type)
53
+ anchor = WantedAnchor.builder.with_value(value).with_sub_type(sub_type).build
54
+ with_anchor(anchor)
55
+ end
56
+
57
+ def with_anchor(anchor)
58
+ @constraint.anchors.push(anchor)
59
+ self
60
+ end
61
+
62
+ def with_passport(sub_type = nil)
63
+ with_anchor_by_value(SourceConstraint::PASSPORT, sub_type)
64
+ end
65
+
66
+ def with_driving_licence(sub_type = nil)
67
+ with_anchor_by_value(SourceConstraint::DRIVING_LICENCE, sub_type)
68
+ end
69
+
70
+ def with_national_id(sub_type = nil)
71
+ with_anchor_by_value(SourceConstraint::NATIONAL_ID, sub_type)
72
+ end
73
+
74
+ def with_passcard(sub_type = nil)
75
+ with_anchor_by_value(SourceConstraint::PASS_CARD, sub_type)
76
+ end
77
+
78
+ def with_soft_preference(preference = true)
79
+ @constraint.instance_variable_set(:@soft_preference, preference)
80
+ self
81
+ end
82
+
83
+ def build
84
+ Marshal.load Marshal.dump @constraint
85
+ end
86
+ end
87
+ end
88
+ end