Skip to content

Commit f40fd2e

Browse files
refactor the fhirapi views and util functions
1 parent 480fe3c commit f40fd2e

File tree

16 files changed

+331
-192
lines changed

16 files changed

+331
-192
lines changed

apps/fhir/bluebutton/permissions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def has_object_permission(self, request, view, obj):
7272

7373

7474
class SearchCrosswalkPermission(HasCrosswalk):
75-
def has_object_permission(self, request, view, obj):
75+
def has_object_permission(self, request, view, obj): # type: ignore
7676
if view.version in Versions.supported_versions():
7777
patient_id = request.crosswalk.fhir_id(view.version)
7878
else:

apps/fhir/bluebutton/tests/test_utils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from apps.test import BaseApiTest
88
from apps.fhir.bluebutton.models import Crosswalk
99
from apps.versions import Versions
10+
from apps.fhir.server.settings import fhir_settings
11+
1012

1113
from apps.fhir.bluebutton.utils import (
1214
notNone,
@@ -16,7 +18,6 @@
1618
prepend_q,
1719
dt_patient_reference,
1820
crosswalk_patient_id,
19-
get_resourcerouter,
2021
build_oauth_resource,
2122
valid_patient_read_or_search_call,
2223
)
@@ -123,13 +124,12 @@ def test_FhirServerAuth(self):
123124

124125
""" Test 1: pass nothing"""
125126

126-
resource_router = get_resourcerouter()
127127
expected = {}
128-
expected['client_auth'] = resource_router.client_auth
128+
expected['client_auth'] = fhir_settings.client_auth
129129
expected['cert_file'] = os.path.join(settings.FHIR_CLIENT_CERTSTORE,
130-
resource_router.cert_file)
130+
fhir_settings.cert_file)
131131
expected['key_file'] = os.path.join(settings.FHIR_CLIENT_CERTSTORE,
132-
resource_router.key_file)
132+
fhir_settings.key_file)
133133

134134
response = FhirServerAuth()
135135

apps/fhir/bluebutton/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
from django.contrib import admin
33

44
from apps.fhir.bluebutton.views.read import (
5+
ReadViewPatient,
56
ReadViewCoverage,
67
ReadViewExplanationOfBenefit,
7-
ReadViewPatient,
88
)
99
from apps.fhir.bluebutton.views.search import (
10+
SearchViewPatient,
1011
SearchViewCoverage,
1112
SearchViewExplanationOfBenefit,
12-
SearchViewPatient,
1313
)
1414

1515
admin.autodiscover()

apps/fhir/bluebutton/utils.py

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -221,20 +221,15 @@ def request_call(request, call_url, crosswalk=None, timeout=None, get_parameters
221221
call_url = target server URL and search parameters to be sent
222222
crosswalk = Crosswalk record. The crosswalk is keyed off Request.user
223223
timeout allows a timeout in seconds to be set.
224-
225-
FhirServer is joined to Crosswalk.
226-
FhirServerAuth and FhirServerVerify receive crosswalk and lookup
227-
values in the linked fhir_server model.
228-
229224
"""
230225

231226
logger_perf = bb2logging.getLogger(bb2logging.PERFORMANCE_LOGGER, request)
232227

233228
# Updated to receive crosswalk (Crosswalk entry for user)
234229
# call FhirServer_Auth(crosswalk) to get authentication
235-
auth_state = FhirServerAuth(crosswalk)
230+
auth_state = FhirServerAuth()
236231

237-
verify_state = FhirServerVerify(crosswalk)
232+
verify_state = fhir_settings.verify_server
238233
if auth_state["client_auth"]:
239234
# cert puts cert and key file together
240235
# (cert_file_path, key_file_path)
@@ -326,16 +321,21 @@ def notNone(value=None, default=None):
326321
return value
327322

328323

329-
def FhirServerAuth(crosswalk=None):
330-
# Get default clientauth settings from base.py
331-
# Receive a crosswalk.id or None
332-
# Return a dict
324+
def FhirServerAuth() -> dict:
325+
"""Helper class to modify cert paths if client_auth is true
326+
TODO - this can probably be refactored or removed, rolled into the FHIRServerSettings class
327+
328+
Returns:
329+
dict: A dictionary with the following:
330+
- client_auth (bool): if client authentication is required
331+
- cert_file (str): path to cert file
332+
- key_file (str): path to key file
333+
"""
333334

334335
auth_settings = {}
335-
resource_router = get_resourcerouter()
336-
auth_settings["client_auth"] = resource_router.client_auth
337-
auth_settings["cert_file"] = resource_router.cert_file
338-
auth_settings["key_file"] = resource_router.key_file
336+
auth_settings["client_auth"] = fhir_settings.client_auth
337+
auth_settings["cert_file"] = fhir_settings.cert_file
338+
auth_settings["key_file"] = fhir_settings.key_file
339339

340340
if auth_settings["client_auth"]:
341341
# join settings.FHIR_CLIENT_CERTSTORE to cert_file and key_file
@@ -351,12 +351,6 @@ def FhirServerAuth(crosswalk=None):
351351
return auth_settings
352352

353353

354-
def FhirServerVerify(crosswalk=None):
355-
# Get default Server Verify Setting
356-
# Return True or False (Default)
357-
return get_resourcerouter().verify_server
358-
359-
360354
def mask_with_this_url(request, host_path="", in_text="", find_url=""):
361355
"""find_url in in_text and replace with url for this server"""
362356

@@ -455,10 +449,6 @@ def get_crosswalk(user):
455449
return None
456450

457451

458-
def get_resourcerouter(crosswalk=None):
459-
return fhir_settings
460-
461-
462452
def handle_http_error(e):
463453
"""Handle http error from request_call
464454
@@ -605,7 +595,7 @@ def get_response_text(fhir_response=None):
605595
return text_in
606596

607597

608-
def build_oauth_resource(request, version=Versions.NOT_AN_API_VERSION, format_type="json"):
598+
def build_oauth_resource(request, version=Versions.NOT_AN_API_VERSION, format_type="json") -> dict | str:
609599
"""
610600
Create a resource entry for oauth endpoint(s) for insertion
611601
into the conformance/capabilityStatement
@@ -707,17 +697,15 @@ def get_v2_patient_by_id(id, request):
707697
a helper adapted to just get patient given an id out of band of auth flow
708698
or normal data flow, use by tools such as BB2-Tools admin viewers
709699
"""
710-
auth_settings = FhirServerAuth(None)
700+
auth_settings = FhirServerAuth()
711701
certs = (auth_settings["cert_file"], auth_settings["key_file"])
712702

713703
headers = generate_info_headers(request)
714704
headers["BlueButton-Application"] = "BB2-Tools"
715705
headers["includeIdentifiers"] = "true"
716706
# for now this will only work for v1/v2 patients, but we'll need to be able to
717707
# determine if the user is V3 and use those endpoints later
718-
url = "{}/v2/fhir/Patient/{}?_format={}".format(
719-
get_resourcerouter().fhir_url, id, settings.FHIR_PARAM_FORMAT
720-
)
708+
url = f'{fhir_settings.fhir_url}/v2/fhir/Patient/{id}?_format={settings.FHIR_PARAM_FORMAT}'
721709
s = requests.Session()
722710
req = requests.Request("GET", url, headers=headers)
723711
prepped = req.prepare()
@@ -730,17 +718,15 @@ def get_v2_patient_by_id(id, request):
730718
# of the ticket to remove the user_mbi_hash column from the crosswalk table
731719
# We can remove this entire function at that point
732720
def get_patient_by_mbi_hash(mbi_hash, request):
733-
auth_settings = FhirServerAuth(None)
721+
auth_settings = FhirServerAuth()
734722
certs = (auth_settings["cert_file"], auth_settings["key_file"])
735723
headers = generate_info_headers(request)
736724
headers["BlueButton-Application"] = "BB2-Tools"
737725
headers["includeIdentifiers"] = "true"
738726

739727
search_identifier = f'https://bluebutton.cms.gov/resources/identifier/mbi-hash|{mbi_hash}' # noqa: E231
740728
payload = {'identifier': search_identifier}
741-
url = '{}/v2/fhir/Patient/_search'.format(
742-
get_resourcerouter().fhir_url
743-
)
729+
url = f'{fhir_settings.fhir_url}/v2/fhir/Patient/_search'
744730

745731
s = requests.Session()
746732
req = requests.Request("POST", url, headers=headers, data=payload)

apps/fhir/bluebutton/v2/urls.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,27 @@
44
from apps.fhir.bluebutton.views.read import (
55
ReadViewCoverage,
66
ReadViewExplanationOfBenefit,
7-
ReadViewPatient,
87
)
98
from apps.fhir.bluebutton.views.search import (
109
SearchViewCoverage,
1110
SearchViewExplanationOfBenefit,
12-
SearchViewPatient,
1311
)
12+
from apps.fhir.bluebutton.views.patient_viewset import PatientViewSet
1413

1514
admin.autodiscover()
1615

1716
urlpatterns = [
1817
# Patient ReadView
1918
re_path(
20-
r"Patient/(?P<resource_id>[^/]+)",
21-
ReadViewPatient.as_view(version=2),
22-
name="bb_oauth_fhir_patient_read_or_update_or_delete_v2",
19+
r'Patient/(?P<resource_id>[^/]+)',
20+
PatientViewSet.as_view({'get': 'retrieve'}, version=2),
21+
name='bb_oauth_fhir_patient_read_or_update_or_delete_v2',
2322
),
2423
# Patient SearchView
2524
re_path(
26-
r"Patient[/]?",
27-
SearchViewPatient.as_view(version=2),
28-
name="bb_oauth_fhir_patient_search_v2",
25+
r'Patient[/]?',
26+
PatientViewSet.as_view({'get': 'list'}, version=2),
27+
name='bb_oauth_fhir_patient_search_v2',
2928
),
3029
# Coverage ReadView
3130
re_path(

apps/fhir/bluebutton/v3/urls.py

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,56 +5,58 @@
55
from apps.fhir.bluebutton.views.read import (
66
ReadViewCoverage,
77
ReadViewExplanationOfBenefit,
8-
ReadViewPatient,
98
)
109
from apps.fhir.bluebutton.views.search import (
1110
SearchViewCoverage,
1211
SearchViewExplanationOfBenefit,
13-
SearchViewPatient,
1412
)
13+
from apps.fhir.bluebutton.views.patient_viewset import PatientViewSet
14+
from apps.fhir.bluebutton.views.insurancecard_viewset import DigitalInsuranceCardViewSet
1515

1616
admin.autodiscover()
1717

1818
urlpatterns = [
1919
# Patient ReadView
2020
re_path(
21-
r"Patient/(?P<resource_id>[^/]+)",
22-
waffle_switch("v3_endpoints")(ReadViewPatient.as_view(version=3)),
23-
name="bb_oauth_fhir_patient_read_or_update_or_delete_v3",
21+
r'Patient/(?P<resource_id>[^/]+)',
22+
waffle_switch('v3_endpoints')(PatientViewSet.as_view({'get': 'retrieve'}, version=3)),
23+
name='bb_oauth_fhir_patient_read_or_update_or_delete_v3',
2424
),
2525
# Patient SearchView
2626
re_path(
27-
r"Patient[/]?",
28-
waffle_switch("v3_endpoints")(SearchViewPatient.as_view(version=3)),
29-
name="bb_oauth_fhir_patient_search_v3",
27+
r'Patient[/]?',
28+
waffle_switch('v3_endpoints')(PatientViewSet.as_view({'get': 'list'}, version=3)),
29+
name='bb_oauth_fhir_patient_search_v3',
3030
),
3131
# Coverage ReadView
3232
re_path(
33-
r"Coverage/(?P<resource_id>[^/]+)",
34-
waffle_switch("v3_endpoints")(ReadViewCoverage.as_view(version=3)),
35-
name="bb_oauth_fhir_coverage_read_or_update_or_delete_v3",
33+
r'Coverage/(?P<resource_id>[^/]+)',
34+
waffle_switch('v3_endpoints')(ReadViewCoverage.as_view(version=3)),
35+
name='bb_oauth_fhir_coverage_read_or_update_or_delete_v3',
3636
),
3737
# Coverage SearchView
3838
re_path(
39-
r"Coverage[/]?",
40-
waffle_switch("v3_endpoints")(SearchViewCoverage.as_view(version=3)),
41-
name="bb_oauth_fhir_coverage_search_v3",
39+
r'Coverage[/]?',
40+
waffle_switch('v3_endpoints')(SearchViewCoverage.as_view(version=3)),
41+
name='bb_oauth_fhir_coverage_search_v3',
4242
),
4343
# EOB ReadView
4444
re_path(
45-
r"ExplanationOfBenefit/(?P<resource_id>[^/]+)",
46-
waffle_switch("v3_endpoints")(ReadViewExplanationOfBenefit.as_view(version=3)),
47-
name="bb_oauth_fhir_eob_read_or_update_or_delete_v3",
45+
r'ExplanationOfBenefit/(?P<resource_id>[^/]+)',
46+
waffle_switch('v3_endpoints')(ReadViewExplanationOfBenefit.as_view(version=3)),
47+
name='bb_oauth_fhir_eob_read_or_update_or_delete_v3',
4848
),
4949
# EOB SearchView
5050
re_path(
51-
r"ExplanationOfBenefit[/]?",
52-
waffle_switch("v3_endpoints")(SearchViewExplanationOfBenefit.as_view(version=3)),
53-
name="bb_oauth_fhir_eob_search_v3",
51+
r'ExplanationOfBenefit[/]?',
52+
waffle_switch('v3_endpoints')(SearchViewExplanationOfBenefit.as_view(version=3)),
53+
name='bb_oauth_fhir_eob_search_v3',
5454
),
5555
# C4DIC
56-
# Digital Insurance Card ReadView
56+
# Digital Insurance Card ViewSet
5757
re_path(
58-
r'', waffle_switch
59-
)
58+
r'DigitalInsuranceCard[/]?',
59+
waffle_switch('v3_endpoints')(DigitalInsuranceCardViewSet.as_view({'get': 'list'}, version=3)),
60+
name='bb_oauth_fhir_dic_read',
61+
),
6062
]

0 commit comments

Comments
 (0)