Skip to content

Commit 255143f

Browse files
authored
Add support for separate V2/V3 BFD endpoints (#1359)
1 parent 06b547d commit 255143f

File tree

9 files changed

+44
-22
lines changed

9 files changed

+44
-22
lines changed

apps/fhir/bluebutton/utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,9 @@ def get_patient_by_id(id, request):
702702
headers = generate_info_headers(request)
703703
headers["BlueButton-Application"] = "BB2-Tools"
704704
headers["includeIdentifiers"] = "true"
705-
url = "{}Patient/{}?_format={}".format(
705+
# for now this will only work for v1/v2 patients, but we'll need to be able to
706+
# determine if the user is V3 and use those endpoints later
707+
url = "{}/v2/fhir/Patient/{}?_format={}".format(
706708
get_resourcerouter().fhir_url, id, settings.FHIR_PARAM_FORMAT
707709
)
708710
s = requests.Session()

apps/fhir/bluebutton/views/home.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020

2121

2222
def fhir_conformance_v2(request, via_oauth=False):
23-
return fhir_conformance(request, via_oauth, True)
23+
return fhir_conformance(request, via_oauth, "v2")
2424

2525

26-
def fhir_conformance(request, via_oauth=False, v2=False, *args):
26+
def fhir_conformance_v3(request, via_oauth=False):
27+
return fhir_conformance(request, via_oauth, "v3")
28+
29+
30+
def fhir_conformance(request, via_oauth=False, ver_str="v1", *args):
2731
""" Pull and filter fhir Conformance statement
2832
2933
BaseStu3 = "CapabilityStatement"
@@ -36,13 +40,14 @@ def fhir_conformance(request, via_oauth=False, v2=False, *args):
3640
"""
3741
crosswalk = None
3842
resource_router = get_resourcerouter()
39-
parsed_url = urlparse(resource_router.fhir_url)
43+
fhir_url = resource_router.fhir_url_v3 if ver_str == "v3" else resource_router.fhir_url
44+
parsed_url = urlparse(fhir_url)
4045
call_to = None
4146
if parsed_url.path is not None:
42-
call_to = '{}://{}/{}/fhir/metadata'.format(parsed_url.scheme, parsed_url.netloc, 'v2' if v2 else 'v1')
47+
call_to = '{}://{}/{}/fhir/metadata'.format(parsed_url.scheme, parsed_url.netloc, ver_str)
4348
else:
4449
# url with no path
45-
call_to = '{}/{}/fhir/metadata'.format(resource_router.fhir_url, 'v2' if v2 else 'v1')
50+
call_to = '{}/{}/fhir/metadata'.format(fhir_url, ver_str)
4651

4752
pass_params = {'_format': 'json'}
4853

apps/fhir/bluebutton/views/read.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,19 @@ def build_url(self, resource_router, resource_type, resource_id, **kwargs):
4343
# only if called by tests
4444
return "{}{}/{}/".format(resource_router.fhir_url, resource_type, resource_id)
4545
else:
46+
fhir_url = resource_router.fhir_url
4647
match self.version:
4748
case 3:
4849
version_str = 'v3'
50+
if resource_router.fhir_url_v3:
51+
fhir_url = resource_router.fhir_url_v3
4952
case 2:
5053
version_str = 'v2'
5154
case _:
5255
version_str = 'v1'
5356

5457
return "{base_url}/{version}/fhir/{resource_type}/{resource_id}/".format(
55-
base_url=resource_router.fhir_url,
58+
base_url=fhir_url,
5659
version=version_str,
5760
resource_type=resource_type,
5861
resource_id=resource_id

apps/fhir/bluebutton/views/search.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,19 @@ def build_url(self, resource_router, resource_type, *args, **kwargs):
7373
# only if called by tests
7474
return "{}{}/".format(resource_router.fhir_url, resource_type)
7575
else:
76+
fhir_url = resource_router.fhir_url
7677
match self.version:
7778
case 3:
7879
version_str = 'v3'
80+
if resource_router.fhir_url_v3:
81+
fhir_url = resource_router.fhir_url_v3
7982
case 2:
8083
version_str = 'v2'
8184
case _:
8285
version_str = 'v1'
8386

8487
return "{base_url}/{version}/fhir/{resource_type}/".format(
85-
base_url=resource_router.fhir_url,
88+
base_url=fhir_url,
8689
version=version_str,
8790
resource_type=resource_type
8891
)

apps/fhir/server/authentication.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,12 @@ def search_fhir_id_by_identifier(search_identifier, request=None):
7777
headers = None
7878

7979
# Build URL with patient ID search by identifier.
80+
resource_router = get_resourcerouter()
8081
ver = "v{}".format(request.session.get('version', 1))
81-
url = f"{get_resourcerouter().fhir_url}/{ver}/fhir/Patient/_search"
82+
fhir_url = resource_router.fhir_url
83+
if ver == 'v3' and resource_router.fhir_url_v3:
84+
fhir_url = resource_router.fhir_url_v3
85+
url = f"{fhir_url}/{ver}/fhir/Patient/_search"
8286

8387
max_retries = 3
8488
retries = 0

apps/fhir/server/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
DEFAULTS = {
1818
"FHIR_URL": None,
19+
"FHIR_URL_V3": None,
1920
"CLIENT_AUTH": False,
2021
"CERT_FILE": "",
2122
"KEY_FILE": "",

apps/mymedicare_cb/views.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@ def authenticate(request):
8989

9090
@never_cache
9191
def callback(request, version=2):
92+
state = request.GET.get('relay')
93+
if not state:
94+
return JsonResponse({"error": 'The state parameter is required'}, status=status.HTTP_400_BAD_REQUEST)
95+
96+
try:
97+
anon_user_state = AnonUserState.objects.get(state=state)
98+
except AnonUserState.DoesNotExist:
99+
return JsonResponse({"error": 'The requested state was not found'}, status=status.HTTP_400_BAD_REQUEST)
100+
next_uri = anon_user_state.next_uri or ""
101+
if "/v3/o/authorize" in next_uri:
102+
version = 3
103+
elif "/v2/o/authorize" in next_uri:
104+
version = 2
105+
92106
user_not_found_error = None
93107
try:
94108
authenticate(request)
@@ -112,17 +126,6 @@ def callback(request, version=2):
112126
"error": e.detail,
113127
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
114128

115-
state = request.GET.get('relay')
116-
117-
if not state:
118-
return JsonResponse({"error": 'The state parameter is required'}, status=status.HTTP_400_BAD_REQUEST)
119-
120-
try:
121-
anon_user_state = AnonUserState.objects.get(state=state)
122-
except AnonUserState.DoesNotExist:
123-
return JsonResponse({"error": 'The requested state was not found'}, status=status.HTTP_400_BAD_REQUEST)
124-
next_uri = anon_user_state.next_uri
125-
126129
scheme, netloc, path, query_string, fragment = urlsplit(next_uri)
127130

128131
if user_not_found_error:

hhs_oauth_server/settings/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@
600600

601601
FHIR_SERVER = {
602602
"FHIR_URL": env("FHIR_URL", "https://fhir.backend.bluebutton.hhsdevcloud.us"),
603+
"FHIR_URL_V3": env("FHIR_URL_V3", "https://fhir.backend.bluebutton.hhsdevcloud.us"),
603604
"CERT_FILE": os.path.join(
604605
FHIR_CLIENT_CERTSTORE, env("FHIR_CERT_FILE", "ca.cert.pem")
605606
),

hhs_oauth_server/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.contrib import admin
77

88
from apps.accounts.views.oauth2_profile import openidconnect_userinfo
9-
from apps.fhir.bluebutton.views.home import fhir_conformance, fhir_conformance_v2
9+
from apps.fhir.bluebutton.views.home import fhir_conformance, fhir_conformance_v2, fhir_conformance_v3
1010
from apps.wellknown.views.openid import smart_configuration, smart_configuration_v3
1111
from hhs_oauth_server.hhs_oauth_server_context import IsAppInstalled
1212
from .views import testobject
@@ -46,7 +46,7 @@ def robots_txt(request):
4646
path("v2/fhir/metadata", fhir_conformance_v2, name="fhir_conformance_metadata_v2"),
4747
path("v2/fhir/", include("apps.fhir.bluebutton.v2.urls")),
4848
path("v3/fhir/.well-known/smart-configuration", smart_configuration_v3, name="smart_configuration_v3"),
49-
path("v3/fhir/metadata", fhir_conformance_v2, name="fhir_conformance_metadata_v3"),
49+
path("v3/fhir/metadata", fhir_conformance_v3, name="fhir_conformance_metadata_v3"),
5050
path("v3/fhir/", include("apps.fhir.bluebutton.v3.urls")),
5151
path("v2/o/", include("apps.dot_ext.v2.urls")),
5252
path("v2/o/", include("apps.authorization.v2.urls")),

0 commit comments

Comments
 (0)