Class: HealthCards::Payload

Inherits:
Object
  • Object
show all
Extended by:
PayloadTypes
Includes:
AttributeFilters
Defined in:
lib/health_cards/payload.rb

Overview

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

Direct Known Subclasses

COVIDPayload, MonkeypoxPayload

Constant Summary collapse

FHIR_REF_REGEX =
%r{((http|https)://([A-Za-z0-9\-\\.:%$]*/)+)?(
Account|ActivityDefinition|AdverseEvent|AllergyIntolerance|Appointment|AppointmentResponse|AuditEvent|Basic|
Binary|BiologicallyDerivedProduct|BodyStructure|Bundle|CapabilityStatement|CarePlan|CareTeam|CatalogEntry|
ChargeItem|ChargeItemDefinition|Claim|ClaimResponse|ClinicalImpression|CodeSystem|Communication|
CommunicationRequest|CompartmentDefinition|Composition|ConceptMap|Condition|Consent|Contract|Coverage|
CoverageEligibilityRequest|CoverageEligibilityResponse|DetectedIssue|Device|DeviceDefinition|DeviceMetric
|DeviceRequest|DeviceUseStatement|DiagnosticReport|DocumentManifest|DocumentReference|EffectEvidenceSynthesis|
Encounter|Endpoint|EnrollmentRequest|EnrollmentResponse|EpisodeOfCare|EventDefinition|Evidence|EvidenceVariable|
ExampleScenario|ExplanationOfBenefit|FamilyMemberHistory|Flag|Goal|GraphDefinition|Group|GuidanceResponse|
HealthcareService|ImagingStudy|Immunization|ImmunizationEvaluation|ImmunizationRecommendation|
ImplementationGuide|InsurancePlan|Invoice|Library|Linkage|List|Location|Measure|MeasureReport|Media|Medication|
MedicationAdministration|MedicationDispense|MedicationKnowledge|MedicationRequest|MedicationStatement|
MedicinalProduct|MedicinalProductAuthorization|MedicinalProductContraindication|MedicinalProductIndication|
MedicinalProductIngredient|MedicinalProductInteraction|MedicinalProductManufactured|MedicinalProductPackaged|
MedicinalProductPharmaceutical|MedicinalProductUndesirableEffect|MessageDefinition|MessageHeader|
MolecularSequence|NamingSystem|NutritionOrder|Observation|ObservationDefinition|OperationDefinition|
OperationOutcome|Organization|OrganizationAffiliation|Patient|PaymentNotice|PaymentReconciliation|Person|
PlanDefinition|Practitioner|PractitionerRole|Procedure|Provenance|Questionnaire|QuestionnaireResponse|
RelatedPerson|RequestGroup|ResearchDefinition|ResearchElementDefinition|ResearchStudy|ResearchSubject|
RiskAssessment|RiskEvidenceSynthesis|Schedule|SearchParameter|ServiceRequest|Slot|Specimen|SpecimenDefinition|
StructureDefinition|StructureMap|Subscription|Substance|SubstanceNucleicAcid|SubstancePolymer|SubstanceProtein|
SubstanceReferenceInformation|SubstanceSourceMaterial|SubstanceSpecification|SupplyDelivery|SupplyRequest|Task|
TerminologyCapabilities|TestReport|TestScript|ValueSet|VerificationResult|VisionPrescription)/
[A-Za-z0-9\-.]{1,64}(/_history/[A-Za-z0-9\-.]{1,64})?}x.freeze

Constants included from AttributeFilters

AttributeFilters::ALL_FHIR_RESOURCES

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from PayloadTypes

additional_types, supports_type?, types

Methods included from AttributeFilters

#handle_allowable, #handle_disallowable, included

Constructor Details

#initialize(bundle:, issuer: nil) ⇒ Payload

Create a Payload

Parameters:

  • bundle (FHIR::Bundle)

    VerifiableCredential containing a fhir bundle

  • issuer (String) (defaults to: nil)

    The url from the Issuer of the Payload

Raises:



113
114
115
116
117
118
# File 'lib/health_cards/payload.rb', line 113

def initialize(bundle:, issuer: nil)
  raise InvalidPayloadError unless bundle.is_a?(FHIR::Bundle) # && bundle.valid?

  @issuer = issuer
  @bundle = bundle
end

Instance Attribute Details

#bundleObject (readonly)

Returns the value of attribute bundle.



40
41
42
# File 'lib/health_cards/payload.rb', line 40

def bundle
  @bundle
end

#issuerObject (readonly)

Returns the value of attribute issuer.



40
41
42
# File 'lib/health_cards/payload.rb', line 40

def issuer
  @issuer
end

#nbfObject (readonly)

Returns the value of attribute nbf.



40
41
42
# File 'lib/health_cards/payload.rb', line 40

def nbf
  @nbf
end

Class Method Details

.compress_payload(payload) ⇒ Object

Compress an arbitrary payload, useful for debugging

Parameters:

  • payload (Object)

    Any object that responds to to_s

Returns:

  • A compressed version of that payload parameter



79
80
81
# File 'lib/health_cards/payload.rb', line 79

def compress_payload(payload)
  Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(payload.to_s, Zlib::FINISH)
end

.decompress_payload(payload) ⇒ Hash

Decompress an arbitrary payload, useful for debugging

Parameters:

  • payload (String)

    compressed payload

Returns:

  • (Hash)

    Hash built from JSON contents of payload



71
72
73
74
# File 'lib/health_cards/payload.rb', line 71

def decompress_payload(payload)
  inf = Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(payload)
  JSON.parse(inf)
end

.extract_bundle(payload) ⇒ FHIR::Bundle

Extract a bundle from a compressed payload

Parameters:

  • payload (String)

Returns:

  • (FHIR::Bundle)

Raises:



59
60
61
62
63
64
65
66
# File 'lib/health_cards/payload.rb', line 59

def extract_bundle(payload)
  json = decompress_payload(payload)
  bundle_hash = json.dig('vc', 'credentialSubject', 'fhirBundle')

  raise HealthCards::InvalidCredentialError unless bundle_hash

  FHIR::Bundle.new(bundle_hash)
end

.fhir_version(ver = nil) ⇒ String

Sets/Gets the fhir version that will be passed through to the credential created by an instnace of this Payload (sub)class will only return the current value value (used as a getter)

Parameters:

  • ver (String) (defaults to: nil)

    FHIR Version supported by this Payload (sub)class. Leaving this param out

Returns:

  • (String)

    Current FHIR version supported



89
90
91
92
93
94
95
96
# File 'lib/health_cards/payload.rb', line 89

def fhir_version(ver = nil)
  if @fhir_version.nil? && ver.nil?
    @fhir_version = superclass.fhir_version unless self == HealthCards::Payload
  elsif ver
    @fhir_version = ver
  end
  @fhir_version
end

.from_payload(payload) ⇒ HealthCards::Payload

Create a Payload from a compressed payload

Parameters:

  • payload (String)

Returns:

Raises:



46
47
48
49
50
51
52
53
54
# File 'lib/health_cards/payload.rb', line 46

def from_payload(payload)
  json = decompress_payload(payload)
  bundle_hash = json.dig('vc', 'credentialSubject', 'fhirBundle')

  raise HealthCards::InvalidCredentialError unless bundle_hash

  bundle = extract_bundle(payload)
  new(issuer: json['iss'], bundle: bundle)
end

Instance Method Details

#strip_fhir_bundleHash

Processes the bundle according to smarthealth.cards/#health-cards-are-small and returns a Hash with equivalent values to SMART Health Cards framework and any constraints created by subclasses

Returns:

  • (Hash)

    A hash with the same content as the FHIR::Bundle, processed accoding



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/health_cards/payload.rb', line 156

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, , _|
      case ['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(filter: true) ⇒ Hash

Parameters:

  • filter (Boolean) (defaults to: true)

    specifies whether the bundle should apply allow/disallow rules and meta filtering features. Defaults to true.

Returns:

  • (Hash)


124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/health_cards/payload.rb', line 124

def to_hash(filter: true)
  fhir_bundle = filter ? strip_fhir_bundle : bundle
  {
    iss: issuer,
    nbf: Time.now.to_i,
    vc: {
      type: self.class.types,
      credentialSubject: {
        fhirVersion: self.class.fhir_version,
        fhirBundle: fhir_bundle.to_hash
      }
    }
  }
end

#to_json(*args) ⇒ String

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

Returns:

  • (String)

    JSON string



148
149
150
# File 'lib/health_cards/payload.rb', line 148

def to_json(*args)
  to_hash.to_json(*args)
end

#to_sObject

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

Returns:

  • String compressed payload



142
143
144
# File 'lib/health_cards/payload.rb', line 142

def to_s
  Payload.compress_payload(to_json)
end