Module: DaVinciCRDTestKit::HookRequestFieldValidation

Constant Summary

Constants included from ProfilesAndResourceTypes

ProfilesAndResourceTypes::ORDER_OR_ENCOUNTER_RESOURCE_CLASSES, ProfilesAndResourceTypes::ORDER_RESOURCE_CLASSES, ProfilesAndResourceTypes::ORDER_RESOURCE_TYPES

Constants included from RequestsLogicalModelValidation

RequestsLogicalModelValidation::CRD_CDS_HOOK_REQUEST_MODEL_URL, RequestsLogicalModelValidation::PERFORMER_ALLOWED_RESOURCE_TYPES, RequestsLogicalModelValidation::USER_ID_ALLOWED_RESOURCE_TYPES

Instance Method Summary collapse

Methods included from ProfilesAndResourceTypes

#structure_definition_map, #structure_definition_map_v201, #structure_definition_map_v221

Methods included from ServerBaseURLs

#client_fhir_base_url, #fhir_url, #instance_url, #search_url

Methods included from BaseURLs

#inferno_base_url, #resume_fail_url, #resume_pass_url

Methods included from RequestsLogicalModelValidation

#validate_request_against_logical_model

Methods included from LogicalModelsOverrideHelper

#allowed_resource_type?, #check_appointment_conformance, #check_order_like_resource_conformance, #check_resource_conformance_to_coverage_profile, #check_resource_conformance_to_order_or_encounter_profile, #check_resource_conformance_to_order_profile, #check_resource_conformance_to_questionnaire_task_profile, #check_resource_type_and_validate, #local_reference?, #manually_check_appointment_validation_errors, #parse_action_resource, #primary_performer_type?, #referenced_resource_present_in_bundle?, #reject_resource_issues, #resolved_participant_patient_slice_issue?, #resolved_participant_primary_performer_slice_issue?

Instance Method Details

#hook_request_context_check(context, hook_name, ig_version: 'v201') ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/davinci_crd_test_kit/cross_suite/hook_request_field_validation.rb', line 50

def hook_request_context_check(context, hook_name, ig_version: 'v201')
  required_fields =
    if hook_name == 'order-dispatch'
      context_required_order_dispatch_fields[ig_version]
    else
      context_required_fields_by_hook[hook_name]
    end
  required_fields.each do |field, type|
    validate_presence_and_type(context, field, type,
                               "#{request_number}#{hook_name} request context")
  end
  context_validate_optional_fields(context, hook_name, ig_version:)
  hook_specific_context_check(context, hook_name, ig_version:)
end

#hook_request_optional_fields_check(request_body, ig_version: 'v201') ⇒ Object

rubocop:disable Lint/UnusedMethodArgument



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/davinci_crd_test_kit/cross_suite/hook_request_field_validation.rb', line 37

def hook_request_optional_fields_check(request_body, ig_version: 'v201') # rubocop:disable Lint/UnusedMethodArgument
  hook_request_optional_fields_check_type(request_body)

  defined_fields = hook_required_fields.keys + hook_optional_fields.keys
  request_body.keys.reject { |field| defined_fields.include?(field) }.each do |field|
    if request_body[field].blank?
      add_message('error', "#{request_number}Hook request field `#{field}` cannot be defined but blank.")
    end
  end

  hook_request_fhir_auth_check(request_body)
end

#hook_request_prefetch_check(advertised_prefetch_fields, received_prefetch, received_context, ig_version: 'v201') ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/davinci_crd_test_kit/cross_suite/hook_request_field_validation.rb', line 65

def hook_request_prefetch_check(advertised_prefetch_fields, received_prefetch, received_context, ig_version: 'v201')
  received_prefetch.each do |received_prefetch_key, received_prefetch_hash|
    unless advertised_prefetch_fields.key?(received_prefetch_key)
      add_message('error', "#{request_number}Client sent non-requested Prefetch field `#{received_prefetch_key}`.")
      next
    end

    unless received_prefetch_hash.is_a?(Hash)
      add_message('error', "#{request_number}Prefetch field `#{received_prefetch_key}` is not of type `Hash`.")
      next
    end

    received_prefetch_resource = FHIR.from_contents(received_prefetch[received_prefetch_key].to_json)
    advertised_prefetch_template = advertised_prefetch_fields[received_prefetch_key]
    if advertised_prefetch_template.include?('?')
      advertised_prefetch_fhir_search = advertised_prefetch_template.gsub(/{|}/, '').split('?')
      advertised_prefetch_resource_type = advertised_prefetch_fhir_search.first

      if advertised_prefetch_resource_type == 'Coverage'
        advertised_coverage_query_params = Rack::Utils.parse_nested_query(advertised_prefetch_fhir_search.last)

        advertised_patient_token = advertised_coverage_query_params['patient']
        advertised_context_patient_id_key = advertised_patient_token.split('.').last
        received_context_patient_id = received_context[advertised_context_patient_id_key]

        advertised_status_param = advertised_coverage_query_params['status']

        validate_prefetch_coverages(received_prefetch_resource, received_prefetch_key, received_context_patient_id,
                                    advertised_status_param, ig_version:)
      end
    else
      advertised_prefetch_token = advertised_prefetch_template.gsub(/{|}/, '').split('/')
      advertised_context_id = advertised_prefetch_token.last.split('.').last

      if advertised_prefetch_token.length == 1
        received_context_reference = FHIR::Reference.new(reference: received_context[advertised_context_id])
        received_context_resource_type = received_context_reference.resource_type
        received_context_id = received_context_reference.reference_id
      else
        received_context_id = received_context[advertised_context_id]
        received_context_resource_type = advertised_prefetch_token.first
      end
      validate_prefetch_resource(received_prefetch_resource, received_prefetch_key,
                                 received_context_resource_type, received_context_id, ig_version:)
    end
  end
end

#hook_request_required_fields_check(request_body, hook_name, ig_version: 'v201') ⇒ Object

rubocop:disable Lint/UnusedMethodArgument



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/davinci_crd_test_kit/cross_suite/hook_request_field_validation.rb', line 18

def hook_request_required_fields_check(request_body, hook_name, ig_version: 'v201') # rubocop:disable Lint/UnusedMethodArgument
  hook_request_required_fields_check_presence_and_types(request_body)

  if request_body['hook'] != hook_name
    add_message('error',
                "#{request_number}The `hook` field should be #{hook_name}, but was #{request_body['hook']}")
  end

  if request_body['fhirAuthorization'].present? && request_body['fhirServer'].blank?
    add_message('error', %(
                #{request_number}Missing `fhirServer` field: If `fhirAuthorization` is provided, this field is
                #REQUIRED.))
  end

  return unless request_body['hookInstance'].present? && !guid?(request_body['hookInstance'])

  add_message('error', "#{request_number}`hookInstance` field must be a globally unique UUID.")
end

#json_parse(json) ⇒ Object



11
12
13
14
15
16
# File 'lib/davinci_crd_test_kit/cross_suite/hook_request_field_validation.rb', line 11

def json_parse(json)
  JSON.parse(json)
rescue JSON::ParserError
  add_message('error', "#{request_number}Invalid JSON.")
  false
end

#no_error_validation(message) ⇒ Object



113
114
115
# File 'lib/davinci_crd_test_kit/cross_suite/hook_request_field_validation.rb', line 113

def no_error_validation(message)
  assert messages.none? { |msg| msg[:type] == 'error' }, message
end