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,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ # A wanted anchor for a source based constraint
6
+ class WantedAnchor
7
+ attr_reader :value
8
+ attr_reader :sub_type
9
+
10
+ def initialize
11
+ @value = ''
12
+ @sub_type = nil
13
+ end
14
+
15
+ def to_json(*_args)
16
+ as_json.to_json
17
+ end
18
+
19
+ def as_json
20
+ obj = {
21
+ name: @value
22
+ }
23
+ obj[:sub_type] = @sub_type if @sub_type
24
+ obj
25
+ end
26
+
27
+ def self.builder
28
+ WantedAnchorBuilder.new
29
+ end
30
+ end
31
+
32
+ # Builder for WantedAnchor
33
+ class WantedAnchorBuilder
34
+ def initialize
35
+ @anchor = WantedAnchor.new
36
+ end
37
+
38
+ def with_value(value)
39
+ @anchor.instance_variable_set(:@value, value)
40
+ self
41
+ end
42
+
43
+ def with_sub_type(sub_type = nil)
44
+ @anchor.instance_variable_set(:@sub_type, sub_type)
45
+ self
46
+ end
47
+
48
+ def build
49
+ Marshal.load Marshal.dump @anchor
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ # Describes a wanted attribute in a dynamic sharing policy
6
+ class WantedAttribute
7
+ attr_reader :name
8
+ attr_reader :derivation
9
+ attr_reader :constraints
10
+
11
+ def initialize
12
+ @constraints = []
13
+ end
14
+
15
+ def accept_self_asserted
16
+ return true if @accept_self_asserted
17
+
18
+ false
19
+ end
20
+
21
+ def to_json(*_args)
22
+ as_json.to_json
23
+ end
24
+
25
+ def as_json(*_args)
26
+ obj = {
27
+ name: @name
28
+ }
29
+ obj[:derivation] = @derivation if derivation
30
+ obj[:accept_self_asserted] = @accept_self_asserted if accept_self_asserted
31
+ obj[:constraints] = @constraints.map(&:as_json) unless constraints.empty?
32
+ obj
33
+ end
34
+
35
+ def self.builder
36
+ WantedAttributeBuilder.new
37
+ end
38
+ end
39
+
40
+ # Builder for WantedAttribute
41
+ class WantedAttributeBuilder
42
+ def initialize
43
+ @attribute = WantedAttribute.new
44
+ end
45
+
46
+ #
47
+ # @param [String] name
48
+ #
49
+ def with_name(name)
50
+ @attribute.instance_variable_set(:@name, name)
51
+ self
52
+ end
53
+
54
+ #
55
+ # @param [String] derivation
56
+ #
57
+ def with_derivation(derivation)
58
+ @attribute.instance_variable_set(:@derivation, derivation)
59
+ self
60
+ end
61
+
62
+ #
63
+ # @param constraint Constraint to apply to the requested attribute
64
+ #
65
+ def with_constraint(constraint)
66
+ @attribute.constraints.push(constraint)
67
+ self
68
+ end
69
+
70
+ #
71
+ # @param [Bool] accept
72
+ #
73
+ def with_accept_self_asserted(accept = true)
74
+ @attribute.instance_variable_set(:@accept_self_asserted, accept)
75
+ self
76
+ end
77
+
78
+ def build
79
+ raise 'Attribute name missing' if @attribute.name.nil? || @attribute.name == ''
80
+
81
+ Marshal.load Marshal.dump @attribute
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yoti
4
+ module DynamicSharingService
5
+ class Share
6
+ attr_reader :share_url, :ref_id
7
+
8
+ def initialize(data)
9
+ @share_url = data['qrcode']
10
+ @ref_id = data['ref_id']
11
+ end
12
+ end
13
+
14
+ def self.create_share_url_endpoint
15
+ "/qrcodes/apps/#{Yoti.configuration.client_sdk_id}"
16
+ end
17
+
18
+ def self.create_share_url_query
19
+ "?nonce=#{SecureRandom.uuid}&timestamp=#{Time.now.to_i}"
20
+ end
21
+
22
+ def self.create_share_url(scenario)
23
+ endpoint = "#{create_share_url_endpoint}#{create_share_url_query}"
24
+ uri = URI("#{Yoti.configuration.api_endpoint}#{endpoint}")
25
+
26
+ unsigned = Net::HTTP::Post.new uri
27
+ unsigned.body = scenario.to_json
28
+
29
+ signed_request = Yoti::SignedRequest.new(
30
+ unsigned,
31
+ endpoint,
32
+ scenario
33
+ ).sign
34
+
35
+ response = Net::HTTP.start(
36
+ uri.hostname,
37
+ uri.port,
38
+ use_ssl: true
39
+ ) do |http|
40
+ http.request signed_request
41
+ end
42
+
43
+ create_share_url_parse_response response
44
+ end
45
+
46
+ def self.create_share_url_parse_response(response)
47
+ if response.code.to_i < 200 || response.code.to_i >= 300
48
+ case response.code
49
+ when '400'
50
+ raise InvalidDataError
51
+ when '404'
52
+ raise ApplicationNotFoundError
53
+ else
54
+ raise UnknownHTTPError, response.code
55
+ end
56
+ end
57
+
58
+ Share.new JSON.parse response.body
59
+ end
60
+
61
+ class InvalidDataError < StandardError
62
+ def initialize(msg = 'JSON is incorrect, contains invalid data')
63
+ super
64
+ end
65
+ end
66
+
67
+ class ApplicationNotFoundError < StandardError
68
+ def initialize(msg = 'Application was not found')
69
+ super
70
+ end
71
+ end
72
+
73
+ class UnknownHTTPError < StandardError
74
+ def initialize(code = nil, msg = 'Unknown HTTP Error')
75
+ msg = "#{msg}: #{code}" unless code.nil?
76
+ super msg
77
+ end
78
+ end
79
+ end
80
+ end
@@ -15,6 +15,7 @@ module Yoti
15
15
 
16
16
  def request
17
17
  yoti_request = Yoti::Request.new
18
+ yoti_request.add_header('X-Yoti-Auth-Key', Yoti::SSL.auth_key_from_pem)
18
19
  yoti_request.encrypted_connect_token = @encrypted_connect_token
19
20
  yoti_request.http_method = 'GET'
20
21
  yoti_request.endpoint = 'profile'
@@ -14,6 +14,15 @@ module Yoti
14
14
  # @return [Hash] the body sent with the request
15
15
  attr_accessor :payload
16
16
 
17
+ def initialize
18
+ @headers = {}
19
+ end
20
+
21
+ # Adds a HTTP header to the request
22
+ def add_header(header, value)
23
+ @headers[header] = value
24
+ end
25
+
17
26
  # Makes a HTTP request after signing the headers
18
27
  # @return [Hash] the body from the HTTP request
19
28
  def body
@@ -51,6 +60,10 @@ module Yoti
51
60
  raise RequestError, "Request method not allowed: #{@http_method}"
52
61
  end
53
62
 
63
+ @headers.each do |header, value|
64
+ http_req[header] = value
65
+ end
66
+
54
67
  http_req
55
68
  end
56
69
 
@@ -11,12 +11,9 @@ module Yoti
11
11
  end
12
12
 
13
13
  def sign
14
- @http_req['X-Yoti-Auth-Key'] = @auth_key
15
14
  @http_req['X-Yoti-Auth-Digest'] = message_signature
16
15
  @http_req['X-Yoti-SDK'] = Yoti.configuration.sdk_identifier
17
16
  @http_req['X-Yoti-SDK-Version'] = "#{Yoti.configuration.sdk_identifier}-#{Yoti::VERSION}"
18
- @http_req['Content-Type'] = 'application/json'
19
- @http_req['Accept'] = 'application/json'
20
17
  @http_req
21
18
  end
22
19
 
@@ -6,6 +6,9 @@ require 'json'
6
6
  require_relative 'attrpubapi/List_pb.rb'
7
7
  require_relative 'compubapi/EncryptedData_pb.rb'
8
8
  require_relative 'compubapi/SignedTimestamp_pb.rb'
9
+ require_relative 'sharepubapi/ExtraData_pb.rb'
10
+ require_relative 'sharepubapi/IssuingAttributes_pb.rb'
11
+ require_relative 'sharepubapi/ThirdPartyAttribute_pb.rb'
9
12
 
10
13
  module Yoti
11
14
  module Protobuf
@@ -40,12 +43,20 @@ module Yoti
40
43
  decipher_profile(receipt['profile_content'], receipt['wrapped_receipt_key'])
41
44
  end
42
45
 
46
+ def extra_data(receipt)
47
+ return nil unless valid_receipt?(receipt)
48
+
49
+ decipher_profile(receipt['extra_data'], receipt['wrapped_receipt_key']) if receipt['extra_data']
50
+ end
51
+
43
52
  def attribute_list(data)
44
53
  Yoti::Protobuf::Attrpubapi::AttributeList.decode(data)
45
54
  end
46
55
 
47
56
  def value_based_on_attribute_name(value, attr_name)
48
57
  case attr_name
58
+ when Yoti::Attribute::DOCUMENT_DETAILS
59
+ Yoti::DocumentDetails.new(value)
49
60
  when Yoti::Attribute::DOCUMENT_IMAGES
50
61
  raise(TypeError, 'Document Images could not be decoded') unless value.is_a?(Yoti::MultiValue)
51
62
 
@@ -0,0 +1,29 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: DataEntry.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "sharepubapi_v1.DataEntry" do
8
+ optional :type, :enum, 1, "sharepubapi_v1.DataEntry.Type"
9
+ optional :value, :bytes, 2
10
+ end
11
+ add_enum "sharepubapi_v1.DataEntry.Type" do
12
+ value :UNDEFINED, 0
13
+ value :INVOICE, 1
14
+ value :PAYMENT_TRANSACTION, 2
15
+ value :LOCATION, 3
16
+ value :TRANSACTION, 4
17
+ value :AGE_VERIFICATION_SECRET, 5
18
+ value :THIRD_PARTY_ATTRIBUTE, 6
19
+ end
20
+ end
21
+
22
+ module Yoti
23
+ module Protobuf
24
+ module Sharepubapi
25
+ DataEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("sharepubapi_v1.DataEntry").msgclass
26
+ DataEntry::Type = Google::Protobuf::DescriptorPool.generated_pool.lookup("sharepubapi_v1.DataEntry.Type").enummodule
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: ExtraData.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require_relative 'DataEntry_pb'
7
+ Google::Protobuf::DescriptorPool.generated_pool.build do
8
+ add_message "sharepubapi_v1.ExtraData" do
9
+ repeated :list, :message, 1, "sharepubapi_v1.DataEntry"
10
+ end
11
+ end
12
+
13
+ module Yoti
14
+ module Protobuf
15
+ module Sharepubapi
16
+ ExtraData = Google::Protobuf::DescriptorPool.generated_pool.lookup("sharepubapi_v1.ExtraData").msgclass
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: IssuingAttributes.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "sharepubapi_v1.IssuingAttributes" do
8
+ optional :expiry_date, :string, 1
9
+ repeated :definitions, :message, 2, "sharepubapi_v1.Definition"
10
+ end
11
+ add_message "sharepubapi_v1.Definition" do
12
+ optional :name, :string, 1
13
+ end
14
+ end
15
+
16
+ module Yoti
17
+ module Protobuf
18
+ module Sharepubapi
19
+ IssuingAttributes = Google::Protobuf::DescriptorPool.generated_pool.lookup("sharepubapi_v1.IssuingAttributes").msgclass
20
+ Definition = Google::Protobuf::DescriptorPool.generated_pool.lookup("sharepubapi_v1.Definition").msgclass
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: ThirdPartyAttribute.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require_relative 'IssuingAttributes_pb'
7
+ Google::Protobuf::DescriptorPool.generated_pool.build do
8
+ add_message "sharepubapi_v1.ThirdPartyAttribute" do
9
+ optional :issuance_token, :bytes, 1
10
+ optional :issuing_attributes, :message, 2, "sharepubapi_v1.IssuingAttributes"
11
+ end
12
+ end
13
+
14
+ module Yoti
15
+ module Protobuf
16
+ module Sharepubapi
17
+ ThirdPartyAttribute = Google::Protobuf::DescriptorPool.generated_pool.lookup("sharepubapi_v1.ThirdPartyAttribute").msgclass
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'sandbox/anchor'
2
+ require_relative 'sandbox/attribute'
3
+ require_relative 'sandbox/profile'
4
+ require_relative 'sandbox/sandbox_client'
5
+ require_relative 'sandbox/sandbox'
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sandbox
4
+ # Anchor describes an anchor on a Sandbox Attribute
5
+ class Anchor
6
+ attr_reader :type
7
+ attr_reader :value
8
+ attr_reader :sub_type
9
+ attr_reader :timestamp
10
+
11
+ def initialize(type:, value:, sub_type: '', timestamp: Time.now)
12
+ @type = type
13
+ @value = value
14
+ @sub_type = sub_type
15
+ @timestamp = timestamp
16
+ end
17
+
18
+ def as_json(*_args)
19
+ {
20
+ type: @type,
21
+ value: @value,
22
+ sub_type: @sub_type,
23
+ timestamp: @timestamp.to_i
24
+ }
25
+ end
26
+
27
+ def to_json(*args)
28
+ as_json.to_json(*args)
29
+ end
30
+
31
+ def self.source(value, sub_type: '', timestamp: Time.now)
32
+ Anchor.new(
33
+ type: 'SOURCE',
34
+ value: value,
35
+ sub_type: sub_type,
36
+ timestamp: timestamp
37
+ )
38
+ end
39
+
40
+ def self.verifier(value, sub_type: '', timestamp: Time.now)
41
+ Anchor.new(
42
+ type: 'VERIFIER',
43
+ value: value,
44
+ sub_type: sub_type,
45
+ timestamp: timestamp
46
+ )
47
+ end
48
+ end
49
+ end