Skip to content

Commit 85f1949

Browse files
committed
Merge branch 'clewellyn-nava/BB2-4266/C4DIC-endpoint' of https://github.com/CMSgov/bluebutton-web-server into clewellyn-nava/BB2-4266/C4DIC-endpoint
2 parents 70f4826 + a96d9ce commit 85f1949

File tree

9 files changed

+59
-47
lines changed

9 files changed

+59
-47
lines changed

apps/fhir/bluebutton/permissions.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,8 @@ def has_permission(self, request, view):
106106
)
107107

108108
return True
109+
110+
111+
class AlwaysDeny(permissions.BasePermission):
112+
def has_permission(self, request, view):
113+
return False

apps/fhir/bluebutton/tests/test_fhir_resources_read_search_w_validation.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ def _search_eob_by_parameter_tag(self, version=1):
224224
def catchall_w_tag_qparam(url, req):
225225
# this is called in case EOB search with good tag
226226
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/ExplanationOfBenefit/', req.url)
227-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
227+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
228228
# parameters encoded in prepared request's body
229229
self.assertTrue(('_tag=Adjudicated' in req.url) or ('_tag=PartiallyAdjudicated' in req.url))
230230

@@ -236,7 +236,7 @@ def catchall_w_tag_qparam(url, req):
236236
@all_requests
237237
def catchall(url, req):
238238
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/ExplanationOfBenefit/', req.url)
239-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
239+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
240240

241241
return {
242242
'status_code': 200,
@@ -280,7 +280,7 @@ def _search_eob_by_parameters_request(self, version=1):
280280
@all_requests
281281
def catchall(url, req):
282282
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/ExplanationOfBenefit/', req.url)
283-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
283+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
284284

285285
return {
286286
'status_code': 200,

apps/fhir/bluebutton/tests/test_read_and_search.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
def get_expected_read_request(version: int):
2727
return {
2828
'method': 'GET',
29-
'url': f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/Patient/{FHIR_ID_V2}/?_format=application/json+fhir&_id={FHIR_ID_V2}',
29+
'url': f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/Patient/{FHIR_ID_V2}/?_format=application/fhir+json&_id={FHIR_ID_V2}',
3030
'headers': {
3131
# 'User-Agent': 'python-requests/2.20.0',
3232
'Accept-Encoding': 'gzip, deflate',
@@ -284,7 +284,7 @@ def _search_request(self, version: int = 1):
284284
@all_requests
285285
def catchall(url, req):
286286
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/Patient/', req.url)
287-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
287+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
288288
self.assertIn(f'_id={FHIR_ID_V2}', req.url)
289289
self.assertIn('_count=5', req.url)
290290
self.assertNotIn('hello', req.url)
@@ -362,7 +362,7 @@ def _search_request_not_found(self, version: int = 1):
362362
@all_requests
363363
def catchall(url, req):
364364
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/Patient/', req.url)
365-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
365+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
366366
self.assertIn(f'_id={FHIR_ID_V2}', req.url)
367367
self.assertEqual(expected_request['method'], req.method)
368368
self.assertDictContainsSubset(expected_request['headers'], req.headers)
@@ -444,7 +444,7 @@ def _search_request_failed(self, version: int = 1, bfd_status_code=500):
444444
@all_requests
445445
def catchall(url, req):
446446
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/Patient/', req.url)
447-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
447+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
448448
self.assertIn(f'_id={FHIR_ID_V2}', req.url)
449449
self.assertEqual(expected_request['method'], req.method)
450450
self.assertDictContainsSubset(expected_request['headers'], req.headers)
@@ -499,7 +499,7 @@ def fhir_request(url, req):
499499
@all_requests
500500
def catchall(url, req):
501501
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/Patient/', req.url)
502-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
502+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
503503
self.assertIn(f'_id={FHIR_ID_V2}', req.url)
504504
self.assertEqual(expected_request['method'], req.method)
505505
self.assertDictContainsSubset(expected_request['headers'], req.headers)
@@ -532,7 +532,7 @@ def _search_parameters_request(self, version: int = 1):
532532
@all_requests
533533
def catchall(url, req):
534534
self.assertIn(f'{FHIR_SERVER["FHIR_URL"]}/v{version}/fhir/ExplanationOfBenefit/', req.url)
535-
self.assertIn('_format=application%2Fjson%2Bfhir', req.url)
535+
self.assertIn('_format=application%2Ffhir%2Bjson', req.url)
536536

537537
return {
538538
'status_code': 200,

apps/fhir/bluebutton/v2/urls.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,28 @@
44
from apps.fhir.bluebutton.views.read import (
55
ReadViewCoverage,
66
ReadViewExplanationOfBenefit,
7+
ReadViewPatient,
78
)
89
from apps.fhir.bluebutton.views.search import (
910
SearchViewCoverage,
1011
SearchViewExplanationOfBenefit,
12+
SearchViewPatient,
1113
)
12-
from apps.fhir.bluebutton.views.patient_viewset import PatientViewSet
1314

1415
admin.autodiscover()
1516

1617
urlpatterns = [
1718
# Patient ReadView
1819
re_path(
19-
r'Patient/(?P<resource_id>[^/]+)',
20-
PatientViewSet.as_view({'get': 'read'}, version=2),
21-
name='bb_oauth_fhir_patient_read_or_update_or_delete_v2',
20+
r"Patient/(?P<resource_id>[^/]+)",
21+
ReadViewPatient.as_view(version=2),
22+
name="bb_oauth_fhir_patient_read_or_update_or_delete_v2",
2223
),
2324
# Patient SearchView
2425
re_path(
25-
r'Patient[/]?',
26-
PatientViewSet.as_view({'get': 'search'}, version=2),
27-
name='bb_oauth_fhir_patient_search_v2',
26+
r"Patient[/]?",
27+
SearchViewPatient.as_view(version=2),
28+
name="bb_oauth_fhir_patient_search_v2",
2829
),
2930
# Coverage ReadView
3031
re_path(

apps/fhir/bluebutton/v3/urls.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,53 @@
55
from apps.fhir.bluebutton.views.read import (
66
ReadViewCoverage,
77
ReadViewExplanationOfBenefit,
8+
ReadViewPatient,
89
)
910
from apps.fhir.bluebutton.views.search import (
1011
SearchViewCoverage,
1112
SearchViewExplanationOfBenefit,
13+
SearchViewPatient,
1214
)
13-
from apps.fhir.bluebutton.views.patient_viewset import PatientViewSet
1415
from apps.fhir.bluebutton.views.insurancecard import DigitalInsuranceCardView
1516

1617
admin.autodiscover()
1718

1819
urlpatterns = [
1920
# Patient ReadView
2021
re_path(
21-
r'Patient/(?P<resource_id>[^/]+)',
22-
waffle_switch('v3_endpoints')(PatientViewSet.as_view({'get': 'read'}, version=3)),
23-
name='bb_oauth_fhir_patient_read_or_update_or_delete_v3',
22+
r"Patient/(?P<resource_id>[^/]+)",
23+
waffle_switch("v3_endpoints")(ReadViewPatient.as_view(version=3)),
24+
name="bb_oauth_fhir_patient_read_or_update_or_delete_v3",
2425
),
2526
# Patient SearchView
2627
re_path(
27-
r'Patient[/]?',
28-
waffle_switch('v3_endpoints')(PatientViewSet.as_view({'get': 'search'}, version=3)),
29-
name='bb_oauth_fhir_patient_search_v3',
28+
r"Patient[/]?",
29+
waffle_switch("v3_endpoints")(SearchViewPatient.as_view(version=3)),
30+
name="bb_oauth_fhir_patient_search_v3",
3031
),
3132
# Coverage ReadView
3233
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',
34+
r"Coverage/(?P<resource_id>[^/]+)",
35+
waffle_switch("v3_endpoints")(ReadViewCoverage.as_view(version=3)),
36+
name="bb_oauth_fhir_coverage_read_or_update_or_delete_v3",
3637
),
3738
# Coverage SearchView
3839
re_path(
39-
r'Coverage[/]?',
40-
waffle_switch('v3_endpoints')(SearchViewCoverage.as_view(version=3)),
41-
name='bb_oauth_fhir_coverage_search_v3',
40+
r"Coverage[/]?",
41+
waffle_switch("v3_endpoints")(SearchViewCoverage.as_view(version=3)),
42+
name="bb_oauth_fhir_coverage_search_v3",
4243
),
4344
# EOB ReadView
4445
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',
46+
r"ExplanationOfBenefit/(?P<resource_id>[^/]+)",
47+
waffle_switch("v3_endpoints")(ReadViewExplanationOfBenefit.as_view(version=3)),
48+
name="bb_oauth_fhir_eob_read_or_update_or_delete_v3",
4849
),
4950
# EOB SearchView
5051
re_path(
51-
r'ExplanationOfBenefit[/]?',
52-
waffle_switch('v3_endpoints')(SearchViewExplanationOfBenefit.as_view(version=3)),
53-
name='bb_oauth_fhir_eob_search_v3',
52+
r"ExplanationOfBenefit[/]?",
53+
waffle_switch("v3_endpoints")(SearchViewExplanationOfBenefit.as_view(version=3)),
54+
name="bb_oauth_fhir_eob_search_v3",
5455
),
5556
# C4DIC
5657
# Digital Insurance Card ViewSet

apps/fhir/bluebutton/views/read.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ def get(self, request, *args, **kwargs):
3535

3636
def build_parameters(self, *args, **kwargs):
3737
return {
38-
'_format': 'json'
38+
'_format': 'application/fhir+json'
39+
# '_format': 'json'
3940
}
4041

4142
def build_url(self, fhir_settings, resource_type, resource_id, **kwargs): # type: ignore

apps/fhir/bluebutton/views/search.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def __init__(self, version=1):
9595

9696
def build_parameters(self, request, *args, **kwargs):
9797
return {
98-
'_format': 'application/json+fhir',
98+
'_format': 'application/fhir+json',
9999
}
100100

101101

@@ -109,7 +109,7 @@ def __init__(self, version=1):
109109

110110
def build_parameters(self, request, *args, **kwargs):
111111
return {
112-
'_format': 'application/json+fhir',
112+
'_format': 'application/fhir+json',
113113
'beneficiary': 'Patient/' + request.crosswalk.fhir_id(self.version)
114114
}
115115

@@ -165,7 +165,7 @@ def __init__(self, version=1):
165165

166166
def build_parameters(self, request, *args, **kwargs):
167167
return {
168-
'_format': 'application/json+fhir',
168+
'_format': 'application/fhir+json',
169169
'patient': request.crosswalk.fhir_id(self.version),
170170
}
171171

apps/fhir/bluebutton/views/viewsets_base.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from rest_framework.response import Response
33
from voluptuous import Schema, REMOVE_EXTRA
44

5+
from apps.fhir.bluebutton.permissions import AlwaysDeny
56
from apps.fhir.bluebutton.views.generic import FhirDataView
67

78

@@ -25,12 +26,14 @@ def initial(self, request, *args, **kwargs):
2526

2627
def get_permissions(self):
2728
action = getattr(self, 'action', None)
28-
if action == 'list':
29+
if action == 'search':
2930
permission_classes = getattr(self, 'SEARCH_PERMISSION_CLASSES', self.SEARCH_PERMISSION_CLASSES)
30-
elif action == 'retrieve':
31+
elif action == 'read':
3132
permission_classes = getattr(self, 'READ_PERMISSION_CLASSES', self.READ_PERMISSION_CLASSES)
3233
else:
33-
permission_classes = (permissions.IsAuthenticated,)
34+
# If it's not a read or search call, make the permissions_classes list contain a single class,
35+
# permissions.AlwaysDeny, as if it is not a search or read call, we should not proceed.
36+
permission_classes = (AlwaysDeny,)
3437
return [permission_class() for permission_class in permission_classes]
3538

3639
def search(self, request, *args, **kwargs):
@@ -71,8 +74,9 @@ def filter_parameters(self, request) -> dict:
7174
return schema(params)
7275

7376
# TODO - investigate a better way to structure this
77+
# TODO - seems like we could be adding parameters that don't need to be added
7478
def build_parameters(self, request):
75-
if getattr(self, 'action', None) != 'list':
79+
if getattr(self, 'action', None) != 'search':
7680
return {
7781
'_format': 'application/json+fhir',
7882
}

apps/testclient/constants.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class EndpointUrl:
3131
coverage = "coverage"
3232
nav = "nav"
3333

34-
# TODO - theses are all format=json, not format=application/json+fhir, is this good?
34+
# TODO - theses are all format=json, not format=application/fhir+json, is this good?
3535
@staticmethod
3636
def fmt(name: str, uri: str, version: int, patient: str = BAD_PATIENT_ID):
3737
version_as_string = Versions.as_str(version)
@@ -42,11 +42,11 @@ def fmt(name: str, uri: str, version: int, patient: str = BAD_PATIENT_ID):
4242
if patient is None or patient == BAD_PATIENT_ID:
4343
logger.error('EndpointUrl format called with invalid patient id')
4444
raise EndpointFormatException('EndpointUrl format called with invalid patient id')
45-
return f'{uri}/{version_as_string}/fhir/Patient/{patient}?_format=json'
45+
return f'{uri}/{version_as_string}/fhir/Patient/{patient}?_format=application/fhir+json'
4646
case EndpointUrl.explanation_of_benefit:
47-
return f'{uri}/{version_as_string}/fhir/ExplanationOfBenefit/?_format=json'
47+
return f'{uri}/{version_as_string}/fhir/ExplanationOfBenefit/?_format=application/fhir+json'
4848
case EndpointUrl.coverage:
49-
return f'{uri}/{version_as_string}/fhir/Coverage/?_format=json'
49+
return f'{uri}/{version_as_string}/fhir/Coverage/?_format=application/fhir+json'
5050
case _:
5151
logger.error(f'Could not match name in EndpointUrl: {name}')
5252

0 commit comments

Comments
 (0)