class SelfSDK::Services::Facts

Input class to handle authentication requests on self network.

Public Class Methods

new(messaging, client) click to toggle source

Creates a new facts service. Facts service mainly manages fact requests against self users wanting to share their verified facts with your app.

@param messaging [SelfSDK::Messaging] messaging object. @param client [SelfSDK::Client] http client object.

@return [SelfSDK::Services::Facts] facts service.

# File lib/services/facts.rb, line 21
def initialize(messaging, client)
  @messaging = messaging.client
  @messaging_service = messaging
  @client = client
end

Public Instance Methods

generate_qr(facts, opts = {}) click to toggle source

Generates a QR code so users can send facts to your app.

@param facts [Array] a list of facts to be requested. @option opts [String] :cid The unique identifier of the authentication request. @option opts [String] :options Options you want to share with the identity.

@return [String, String] conversation id or encoded body.

# File lib/services/facts.rb, line 97
def generate_qr(facts, opts = {})
  opts[:request] = false
  selfid = opts.fetch(:selfid, "-")
  req = request(selfid, facts, opts)
  ::RQRCode::QRCode.new(req, level: 'l')
end
request(selfid, facts, opts = {}, &block) click to toggle source

Sends a fact request to the specified selfid. An fact request allows your app to access trusted facts of your user with its permission.

@overload request(selfid, facts, opts = {}, &block)

@param selfid [string] the receiver of the authentication request.
@param [Hash] opts the options to authenticate.
@option opts [String] :cid The unique identifier of the authentication request.
@yield [request] Invokes the block with a street name for each result.
@return [Object] SelfSDK:::Messages::FactRequest

@overload request(selfid, facts, opts = {})

@param selfid [string] the receiver of the authentication request.
@param [Hash] opts the options to authenticate.
@option opts [String] :cid The unique identifier of the authentication request.
@option opts [Integer] :exp_timeout timeout in seconds to expire the request.
@return [Object] SelfSDK:::Messages::FactRequest
# File lib/services/facts.rb, line 44
def request(selfid, facts, opts = {}, &block)
  SelfSDK.logger.info "authenticating #{selfid}"
  rq = opts.fetch(:request, true)
  if rq
    raise "You're not permitting connections from #{selfid}" unless @messaging_service.is_permitted?(selfid)
  end

  req = SelfSDK::Messages::FactRequest.new(@messaging)
  req.populate(selfid, prepare_facts(facts), opts)

  body = @client.jwt.prepare(req.body)
  return body unless rq

  # when a block is given the request will always be asynchronous.
  if block_given?
    @messaging.set_observer(req, timeout: req.exp_timeout, &block)
    return req.send_message
  end

  # Otherwise the request is synchronous
  req.request
end
request_via_intermediary(selfid, facts, opts = {}, &block) click to toggle source

Sends a request through an intermediary. An intermediary is an entity trusted by the user and acting as a proxy between you and the recipient of your fact request. Intermediaries usually do not provide the original user facts, but they create its own assertions based on your request and the user's facts.

@param selfid [string] the receiver of the authentication request.
@param [Hash] opts the options to authenticate.
@option opts [String] intermediary an intermediary identity to be used.
@return [Object] SelfSDK:::Messages::FactRequest
# File lib/services/facts.rb, line 77
def request_via_intermediary(selfid, facts, opts = {}, &block)
  opts[:intermediary] = opts.fetch(:intermediary, DEFAULT_INTERMEDIARY)
  request(selfid, facts, opts, &block)
end
subscribe(&block) click to toggle source

Adds an observer for a fact response Whenever you receive a fact response registered observers will receive a notification.

@yield [request] Invokes the block with a fact response message.
# File lib/services/facts.rb, line 86
def subscribe(&block)
  @messaging.subscribe(:fact_response, &block)
end

Private Instance Methods

prepare_facts(facts) click to toggle source

As request facts can accept an array of strings this populates with necessary structure this short fact definitions.

@param facts [Array] an array of strings or hashes. @return [Array] a list of hashed facts.

# File lib/services/facts.rb, line 132
def prepare_facts(facts)
  fs = []
  facts.each do |f|
    fact = if f.is_a?(Hash)
            f
          else
            { fact: f }
          end
    # validate_fact!(fact)
    fs << fact
  end      
  fs
end
validate_fact!(f) click to toggle source
# File lib/services/facts.rb, line 146
def validate_fact!(f)
  errInvalidFactToSource = 'provided source does not support given fact'
  errInvalidSource = 'provided fact does not specify a valid source'

  raise 'provided fact does not specify a name' if f[:fact].empty?
  return unless f.has_key? :sources

  valid_sources = [SOURCE_USER_SPECIFIED, SOURCE_PASSPORT, SOURCE_DRIVING_LICENSE, SOURCE_IDENTITY_CARD]
  factsForPassport = [ FACT_DOCUMENT_NUMBER, 
    FACT_SURNAME, 
    FACT_GIVEN_NAMES,
    FACT_DATE_OF_BIRTH,
    FACT_DATE_OF_EXPIRATION, 
    FACT_SEX, 
    FACT_NATIONALITY,
    FACT_COUNTRY_OF_ISSUANCE ]

  factsForDL = [ FACT_DOCUMENT_NUMBER,
    FACT_SURNAME,
    FACT_GIVEN_NAMES,
    FACT_DATE_OF_BIRTH,
    FACT_DATE_OF_ISSUANCE,
    FACT_DATE_OF_EXPIRATION,
    FACT_ADDRESS, 
    FACT_ISSUING_AUTHORITY,
    FACT_PLACE_OF_BIRTH, 
    FACT_COUNTRY_OF_ISSUANCE ]

  factsForUser = [ FACT_DOCUMENT_NUMBER,
    FACT_DISPLAY_NAME,
    FACT_EMAIL,
    FACT_PHONE ]
    
  f[:sources].each do |s|
    raise errInvalidSource unless valid_sources.include? s.to_s

    if s.to_s == SOURCE_PASSPORT || s.to_s == SOURCE_IDENTITY_CARD
      raise errInvalidFactToSource unless factsForPassport.include? f[:fact]
    end

    if s.to_s == SOURCE_DRIVING_LICENSE
      raise errInvalidFactToSource unless factsForDL.include? f[:fact]
    end

    if s.to_s == SOURCE_USER_SPECIFIED
      raise errInvalidFactToSource unless factsForUser.include? f[:fact].to_s
    end
  end
end