yoti 1.5.0 → 1.6.4

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +17 -0
  3. data/CONTRIBUTING.md +0 -29
  4. data/Gemfile +0 -2
  5. data/README.md +1 -1
  6. data/Rakefile +16 -3
  7. data/lib/yoti.rb +16 -0
  8. data/lib/yoti/activity_details.rb +21 -2
  9. data/lib/yoti/client.rb +2 -1
  10. data/lib/yoti/data_type/age_verification.rb +54 -0
  11. data/lib/yoti/data_type/attribute.rb +3 -0
  12. data/lib/yoti/data_type/base_profile.rb +13 -0
  13. data/lib/yoti/data_type/document_details.rb +88 -0
  14. data/lib/yoti/data_type/profile.rb +76 -0
  15. data/lib/yoti/dynamic_share_service/dynamic_scenario.rb +67 -0
  16. data/lib/yoti/dynamic_share_service/extension/extension.rb +45 -0
  17. data/lib/yoti/dynamic_share_service/extension/location_constraint_extension.rb +88 -0
  18. data/lib/yoti/dynamic_share_service/extension/thirdparty_attribute_extension.rb +119 -0
  19. data/lib/yoti/dynamic_share_service/extension/transactional_flow_extension.rb +47 -0
  20. data/lib/yoti/dynamic_share_service/policy/dynamic_policy.rb +184 -0
  21. data/lib/yoti/dynamic_share_service/policy/source_constraint.rb +88 -0
  22. data/lib/yoti/dynamic_share_service/policy/wanted_anchor.rb +53 -0
  23. data/lib/yoti/dynamic_share_service/policy/wanted_attribute.rb +85 -0
  24. data/lib/yoti/dynamic_share_service/share_url.rb +82 -0
  25. data/lib/yoti/http/profile_request.rb +1 -0
  26. data/lib/yoti/http/request.rb +15 -0
  27. data/lib/yoti/http/signed_request.rb +0 -3
  28. data/lib/yoti/protobuf/main.rb +25 -4
  29. data/lib/yoti/protobuf/sharepubapi/DataEntry_pb.rb +29 -0
  30. data/lib/yoti/protobuf/sharepubapi/ExtraData_pb.rb +19 -0
  31. data/lib/yoti/protobuf/sharepubapi/IssuingAttributes_pb.rb +23 -0
  32. data/lib/yoti/protobuf/sharepubapi/ThirdPartyAttribute_pb.rb +20 -0
  33. data/lib/yoti/share/attribute_issuance_details.rb +43 -0
  34. data/lib/yoti/share/extra_data.rb +25 -0
  35. data/lib/yoti/ssl.rb +8 -0
  36. data/lib/yoti/util/age_processor.rb +4 -0
  37. data/lib/yoti/version.rb +1 -1
  38. data/rubocop.yml +4 -0
  39. data/yoti.gemspec +3 -3
  40. metadata +31 -14
  41. data/.travis.yml +0 -17
@@ -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
@@ -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,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+
5
+ module Yoti
6
+ module DynamicSharingService
7
+ class ThirdPartyAttributeDefinition
8
+ #
9
+ # @param [String] name
10
+ #
11
+ def initialize(name)
12
+ @name = name
13
+ end
14
+
15
+ def as_json(*_args)
16
+ { name: @name }
17
+ end
18
+
19
+ def to_json(*_args)
20
+ as_json.to_json
21
+ end
22
+ end
23
+
24
+ class ThirdPartyAttributeExtensionBuilder
25
+ def initialize
26
+ @expiry_date = nil
27
+ @definitions = []
28
+ end
29
+
30
+ #
31
+ # @param [DateTime,Time] expiry_date
32
+ #
33
+ # @return [self]
34
+ #
35
+ def with_expiry_date(expiry_date)
36
+ @expiry_date = expiry_date
37
+ self
38
+ end
39
+
40
+ #
41
+ # @param [String] *names
42
+ #
43
+ # @return [self]
44
+ #
45
+ def with_definitions(*names)
46
+ @definitions += names.map do |name|
47
+ ThirdPartyAttributeDefinition.new(name)
48
+ end
49
+ self
50
+ end
51
+
52
+ #
53
+ # @return [ThirdPartyAttributeExtension]
54
+ #
55
+ def build
56
+ content = ThirdPartyAttributeExtensionContent.new(@expiry_date, @definitions)
57
+ ThirdPartyAttributeExtension.new(content)
58
+ end
59
+ end
60
+
61
+ class ThirdPartyAttributeExtension
62
+ EXTENSION_TYPE = 'THIRD_PARTY_ATTRIBUTE'
63
+
64
+ # @return [ThirdPartyAttributeExtensionContent]
65
+ attr_reader :content
66
+
67
+ # @return [String]
68
+ attr_reader :type
69
+
70
+ #
71
+ # @param [ThirdPartyAttributeExtensionContent] content
72
+ #
73
+ def initialize(content = nil)
74
+ @content = content
75
+ @type = EXTENSION_TYPE
76
+ end
77
+
78
+ def as_json(*_args)
79
+ json = {}
80
+ json[:type] = @type
81
+ json[:content] = @content.as_json unless @content.nil?
82
+ json
83
+ end
84
+
85
+ def to_json(*_args)
86
+ as_json.to_json
87
+ end
88
+
89
+ #
90
+ # @return [ThirdPartyAttributeExtensionBuilder]
91
+ #
92
+ def self.builder
93
+ ThirdPartyAttributeExtensionBuilder.new
94
+ end
95
+ end
96
+
97
+ class ThirdPartyAttributeExtensionContent
98
+ #
99
+ # @param [DateTime,Time] expiry_date
100
+ # @param [Array<ThirdPartyAttributeDefinition>] definitions
101
+ #
102
+ def initialize(expiry_date, definitions)
103
+ @expiry_date = expiry_date
104
+ @definitions = definitions
105
+ end
106
+
107
+ def as_json(*_args)
108
+ json = {}
109
+ json[:expiry_date] = @expiry_date.to_time.utc.strftime('%FT%T.%3NZ') unless @expiry_date.nil?
110
+ json[:definitions] = @definitions.map(&:as_json)
111
+ json
112
+ end
113
+
114
+ def to_json(*_args)
115
+ as_json.to_json
116
+ end
117
+ end
118
+ end
119
+ 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