forked from smart-on-fhir/client-py
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flask_app.py
129 lines (104 loc) · 4.07 KB
/
flask_app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# -*- coding: utf-8 -*-
import logging
from fhirclient import client
from fhirclient.models.medication import Medication
from fhirclient.models.medicationrequest import MedicationRequest
from flask import Flask, request, redirect, session
# app setup
smart_defaults = {
'app_id': 'my_web_app',
'api_base': 'https://sb-fhir-stu3.smarthealthit.org/smartstu3/data',
'redirect_uri': 'http://localhost:8000/fhir-app/',
}
app = Flask(__name__)
def _save_state(state):
session['state'] = state
def _get_smart():
state = session.get('state')
if state:
return client.FHIRClient(state=state, save_func=_save_state)
else:
return client.FHIRClient(settings=smart_defaults, save_func=_save_state)
def _logout():
if 'state' in session:
smart = _get_smart()
smart.reset_patient()
def _reset():
if 'state' in session:
del session['state']
def _get_prescriptions(smart):
bundle = MedicationRequest.where({'patient': smart.patient_id}).perform(smart.server)
pres = [be.resource for be in bundle.entry] if bundle is not None and bundle.entry is not None else None
if pres is not None and len(pres) > 0:
return pres
return None
def _get_medication_by_ref(ref, smart):
med_id = ref.split("/")[1]
return Medication.read(med_id, smart.server).code
def _med_name(med):
if med.coding:
name = next((coding.display for coding in med.coding if coding.system == 'http://www.nlm.nih.gov/research/umls/rxnorm'), None)
if name:
return name
if med.text and med.text:
return med.text
return "Unnamed Medication(TM)"
def _get_med_name(prescription, client=None):
if prescription.medicationCodeableConcept is not None:
med = prescription.medicationCodeableConcept
return _med_name(med)
elif prescription.medicationReference is not None and client is not None:
med = _get_medication_by_ref(prescription.medicationReference.reference, client)
return _med_name(med)
else:
return 'Error: medication not found'
# views
@app.route('/')
@app.route('/index.html')
def index():
""" The app's main page.
"""
smart = _get_smart()
body = "<h1>Hello</h1>"
if smart.ready and smart.patient is not None: # "ready" may be true but the access token may have expired, making smart.patient = None
name = smart.human_name(smart.patient.name[0] if smart.patient.name and len(smart.patient.name) > 0 else 'Unknown')
# generate simple body text
body += "<p>You are authorized and ready to make API requests for <em>{0}</em>.</p>".format(name)
pres = _get_prescriptions(smart)
if pres is not None:
body += "<p>{0} prescriptions: <ul><li>{1}</li></ul></p>".format("His" if 'male' == smart.patient.gender else "Her", '</li><li>'.join([_get_med_name(p,smart) for p in pres]))
else:
body += "<p>(There are no prescriptions for {0})</p>".format("him" if 'male' == smart.patient.gender else "her")
body += """<p><a href="/logout">Change patient</a></p>"""
else:
auth_url = smart.authorize_url
if auth_url is not None:
body += """<p>Please <a href="{0}">authorize</a>.</p>""".format(auth_url)
else:
body += """<p>Running against a no-auth server, nothing to demo here. """
body += """<p><a href="/reset" style="font-size:small;">Reset</a></p>"""
return body
@app.route('/fhir-app/')
def callback():
""" OAuth2 callback interception.
"""
smart = _get_smart()
try:
smart.handle_callback(request.url)
except Exception as e:
return """<h1>Authorization Error</h1><p>{0}</p><p><a href="/">Start over</a></p>""".format(e)
return redirect('/')
@app.route('/logout')
def logout():
_logout()
return redirect('/')
@app.route('/reset')
def reset():
_reset()
return redirect('/')
# start the app
if '__main__' == __name__:
import flaskbeaker
flaskbeaker.FlaskBeaker.setup_app(app)
logging.basicConfig(level=logging.DEBUG)
app.run(debug=True, port=8000)