From 5b2883eb111a90e23d422a2b5e05b9fff15b8df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Cidre?= <593270+adriacidre@users.noreply.github.com> Date: Mon, 17 Jun 2024 11:10:43 +0200 Subject: [PATCH] object fact request --- examples/object_fact_request/lib.rb | 72 +++++++++++++++++++++++++++++ lib/messages/attestation.rb | 25 +++++----- lib/messages/fact.rb | 2 +- lib/messages/fact_response.rb | 19 +++++++- test/messages/fact_test.rb | 4 +- 5 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 examples/object_fact_request/lib.rb diff --git a/examples/object_fact_request/lib.rb b/examples/object_fact_request/lib.rb new file mode 100644 index 00000000..86c53ad9 --- /dev/null +++ b/examples/object_fact_request/lib.rb @@ -0,0 +1,72 @@ +# Copyright 2020 Self Group Ltd. All Rights Reserved. +# frozen_string_literal: true + +module ObjectFactRequest + class Runner + def initialize(client, prompt) + @client = client + @prompt = prompt + end + + def help + <<-MSG +Your app can request certain bits of information to your +connected users. To do this, you'll only need its _SelfID_ +and the fields you want to request you can find a list of +updated valid fields [here](https://github.com/selfid-net/selfid-gem/blob/main/lib/sources.rb). + +Due of its nature the information request is an asynchronous +process, where your program should wait for user's input before +processing the response. This process is fully managed by +`request_information` gem function. + MSG + end + + def run + # printexample + begin + # Request the user id to send a fact request to + user_id = @prompt.ask("Please introduce the user id you want to send a fact request to: ") do |q| + q.required true + end + + mutex = Mutex.new + condvar = ConditionVariable.new + + # Send an fact request + puts "" + puts "we're sending an fact reuqest to #{user_id}'s device" + @client.facts.request(user_id, [{sources: [:passport], fact: :photo}]) do |res| + # Information request has been rejected by the user + if res.status == "rejected" + puts 'Information request rejected' + condvar.signal + end + + # Response comes in form of facts easy to access with facts method + attestations = res.attestation_values_for(:photo) + photo = res.object(attestations.first) + + path = "/tmp/tmp.jpg" + # puts photo.original_issuer + # puts photo.original_subscriberin + photo.save(path) + + puts "The requested passport photo has been stored at #{path}!" + condvar.signal + end + rescue => e + # Raised exceptions usually happen because of requests timing out. + puts "Oops! this is embarassing, but we found an error with your request" + puts "#{e}" + condvar.signal + end + + mutex.synchronize do + condvar.wait(mutex) + end + puts "DONE" + # !printexample + end + end +end diff --git a/lib/messages/attestation.rb b/lib/messages/attestation.rb index 601df027..d9b73df7 100644 --- a/lib/messages/attestation.rb +++ b/lib/messages/attestation.rb @@ -7,34 +7,35 @@ module SelfSDK module Messages class Attestation - attr_accessor :verified, :origin, :source, :value, :operator, :expected_value, :fact_name, :to, :audience + attr_accessor :verified, :origin, :source, :value, :operator, :expected_value, :fact_name, :to, :audience, :payload def initialize(messaging) @messaging = messaging end def parse(name, attestation) - payload = JSON.parse(@messaging.jwt.decode(attestation[:payload]), symbolize_names: true) - @origin = payload[:iss] - @to = payload[:sub] - @audience = payload[:aud] - @source = payload[:source] + @payload = JSON.parse(@messaging.jwt.decode(attestation[:payload]), symbolize_names: true) + @origin = @payload[:iss] + @to = @payload[:sub] + @audience = @payload[:aud] + @source = @payload[:source] header = JSON.parse(@messaging.jwt.decode(attestation[:protected]), symbolize_names: true) @verified = valid_signature?(attestation, header[:kid]) - @expected_value = payload[:expected_value] - @operator = payload[:operator] + @expected_value = @payload[:expected_value] + @operator = @payload[:operator] @fact_name = name.to_s - if payload[name].nil? - return if payload[:facts].nil? - payload[:facts].each do |f| + if @payload[name].nil? + return if @payload[:facts].nil? + + @payload[:facts].each do |f| if f[:key] == name.to_s @value = f[:value] break end end else - @value = payload[name] + @value = @payload[name] end end diff --git a/lib/messages/fact.rb b/lib/messages/fact.rb index 148dbf29..44148dba 100644 --- a/lib/messages/fact.rb +++ b/lib/messages/fact.rb @@ -31,7 +31,7 @@ def parse(fact) fact[:attestations]&.each do |a| attestation = SelfSDK::Messages::Attestation.new(@messaging) attestation.parse(fact[:fact].to_sym, a) - @attestations.push(attestation) + @attestations.push(attestation) unless attestation.value.nil? end end diff --git a/lib/messages/fact_response.rb b/lib/messages/fact_response.rb index 56e963f3..280597d5 100644 --- a/lib/messages/fact_response.rb +++ b/lib/messages/fact_response.rb @@ -35,6 +35,9 @@ def parse(input, envelope=nil) payload[:facts].each do |f| begin fact = SelfSDK::Messages::Fact.new(@messaging) + if f[:fact] == 'photo' + f[:fact] = :image_hash + end fact.parse(f) @facts.push(fact) rescue StandardError => e @@ -45,10 +48,12 @@ def parse(input, envelope=nil) issuer = envelope.sender.split(":") @from_device = issuer.last end + end def fact(name) name = @messaging.source.normalize_fact_name(name) + name = "image_hash" if name == 'photo' @facts.select{|f| f.name == name}.first end @@ -59,8 +64,8 @@ def attestations_for(name) end def attestation_values_for(name) - a = attestations_for(name) - a.map{|a| a.value} + aa = attestations_for(name) + aa.map{|a| a.value} end def validate!(original) @@ -92,6 +97,16 @@ def body def auth_response? @auth == true end + + def object(hash) + payload[:objects].each do |o| + if o[:image_hash] == hash + return SelfSDK::Chat::FileObject.new( + @messaging.client.jwt.auth_token, + @messaging.client.self_url).build_from_object(o) + end + end + end end end end diff --git a/test/messages/fact_test.rb b/test/messages/fact_test.rb index 51f360af..0dd27adb 100644 --- a/test/messages/fact_test.rb +++ b/test/messages/fact_test.rb @@ -39,9 +39,9 @@ def test_parse assert_equal "display_name", parsed_fact[:fact] assert_equal "==", parsed_fact[:operator] - assert_equal 1, parsed_fact[:attestations].length + assert_equal nil, parsed_fact[:attestations] assert_equal "lol", parsed_fact[:expected_value] end end end -end \ No newline at end of file +end