class HealthCards::HealthCard

A HealthCard which implements the credential claims specified by smarthealth.cards/

Constants

FHIR_REF_REGEX

Attributes

bundle[R]
issuer[R]
nbf[R]

Public Class Methods

compress_payload(payload) click to toggle source

Compress an arbitrary payload, useful for debugging @param payload [Object] Any object that responds to to_s @return A compressed version of that payload parameter

# File lib/health_cards/health_card.rb, line 77
def compress_payload(payload)
  Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(payload.to_s, Zlib::FINISH)
end
decompress_payload(payload) click to toggle source

Decompress an arbitrary payload, useful for debugging @param payload [String] compressed payload @return [Hash] Hash built from JSON contents of payload

# File lib/health_cards/health_card.rb, line 69
def decompress_payload(payload)
  inf = Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(payload)
  JSON.parse(inf)
end
fhir_version(ver = nil) click to toggle source

Sets/Gets the fhir version that will be passed through to the credential created by an instnace of this HealthCard (sub)class @param ver [String] FHIR Version supported by this HealthCard (sub)class. Leaving this param out will only return the current value value (used as a getter) @return [String] Current FHIR version supported

# File lib/health_cards/health_card.rb, line 87
def fhir_version(ver = nil)
  @fhir_version ||= ver unless ver.nil?
  @fhir_version
end
from_jws(jws, public_key: nil, key: nil) click to toggle source

Creates a HealthCard from a JWS @param jws [String] the JWS string @param public_key [HealthCards::PublicKey] the public key associated with the JWS @param key [HealthCards::PrivateKey] the private key associated with the JWS @return [HealthCards::HealthCard]

# File lib/health_cards/health_card.rb, line 48
def from_jws(jws, public_key: nil, key: nil)
  jws = JWS.from_jws(jws, public_key: public_key, key: key)
  from_payload(jws.payload)
end
from_payload(payload) click to toggle source

Create a HealthCard from a compressed payload @param payload [String] @return [HealthCards::HealthCard]

# File lib/health_cards/health_card.rb, line 56
def from_payload(payload)
  json = decompress_payload(payload)
  bundle_hash = json.dig('vc', 'credentialSubject', 'fhirBundle')

  raise HealthCards::InvalidCredentialError unless bundle_hash

  bundle = FHIR::Bundle.new(bundle_hash)
  new(issuer: json['iss'], bundle: bundle)
end
new(bundle:, issuer: nil) click to toggle source

Create a HealthCard

@param bundle [FHIR::Bundle] VerifiableCredential containing a fhir bundle @param issuer [String] The url from the Issuer of the HealthCard

# File lib/health_cards/health_card.rb, line 103
def initialize(bundle:, issuer: nil)
  raise InvalidPayloadError unless bundle.is_a?(FHIR::Bundle) # && bundle.valid?

  @issuer = issuer
  @bundle = bundle
end

Public Instance Methods

strip_fhir_bundle() click to toggle source

Processes the bundle according to smarthealth.cards/#health-cards-are-small and returns a Hash with equivalent values @return [Hash] A hash with the same content as the FHIR::Bundle, processed accoding to SMART Health Cards framework and any constraints created by subclasses

# File lib/health_cards/health_card.rb, line 143
def strip_fhir_bundle
  return [] unless bundle.entry

  new_bundle = duplicate_bundle
  url_map = redefine_uris(new_bundle)

  new_bundle.entry.each do |entry|
    entry.each_element do |value, metadata, _|
      case metadata['type']
      when 'Reference'
        value.reference = process_reference(url_map, entry, value)
      when 'Resource'
        value.meta = nil unless value.meta&.security
      end

      handle_allowable(value)
      handle_disallowable(value)
    end
  end

  new_bundle
end
to_hash() click to toggle source

A Hash matching the VC structure specified by smarthealth.cards/#health-cards-are-encoded-as-compact-serialization-json-web-signatures-jws @return [Hash]

# File lib/health_cards/health_card.rb, line 112
def to_hash
  {
    iss: issuer,
    nbf: Time.now.to_i,
    vc: {
      type: self.class.types,
      credentialSubject: {
        fhirVersion: self.class.fhir_version,
        fhirBundle: strip_fhir_bundle.to_hash
      }
    }
  }
end
to_json(*_args) click to toggle source

A minified JSON string matching the VC structure specified by smarthealth.cards/#health-cards-are-encoded-as-compact-serialization-json-web-signatures-jws @return [String] JSON string

# File lib/health_cards/health_card.rb, line 135
def to_json(*_args)
  to_hash.to_json
end
to_s() click to toggle source

A compressed version of the FHIR::Bundle based on the SMART Health Cards frame work and any other constraints defined by a subclass @return String compressed payload

# File lib/health_cards/health_card.rb, line 129
def to_s
  HealthCard.compress_payload(to_json)
end

Private Instance Methods

duplicate_bundle() click to toggle source
# File lib/health_cards/health_card.rb, line 168
def duplicate_bundle
  FHIR::Bundle.new(bundle.to_hash)
end
process_reference(url_map, entry, ref) click to toggle source
# File lib/health_cards/health_card.rb, line 185
def process_reference(url_map, entry, ref)
  entry_url = URI(url_map.key(entry.fullUrl))
  ref_url = ref.reference

  return unless ref_url

  return url_map[ref_url] if url_map[ref_url]

  fhir_base_url = FHIR_REF_REGEX.match(entry_url.to_s)[1]
  full_url = URI.join(fhir_base_url, ref_url).to_s

  new_url = url_map[full_url]

  raise InvalidBundleReferenceError, full_url unless new_url

  new_url
end
redefine_uris(bundle) click to toggle source
# File lib/health_cards/health_card.rb, line 172
def redefine_uris(bundle)
  url_map = {}
  resource_count = 0
  bundle.entry.each do |entry|
    old_url = entry.fullUrl
    new_url = "resource:#{resource_count}"
    url_map[old_url] = new_url
    entry.fullUrl = new_url
    resource_count += 1
  end
  url_map
end