Anatomy of a PHA
• name • start URL
“Problems” http://problems/auth/start
• description • post-auth URL
“track your problems” http://problems/auth/after
• principal email • consumer key
problems@apps.indivo.org 838xdnwk-sdf-werkj34
• data use agreement: • consumer secret
what the app intends to do 23lnbls-235lnsdf-2343
with the data it reads from
the record.
def start_auth(request):
client = get_indivo_client(request, with_token=False)
# do we have a record_id?
record_id = request.GET.get('record_id', None)
# prepare request token parameters
params = {‘record_id’: record_id}
# request a request token
request_token = parse_token_from_response(
client.post_request_token(data=params))
# store the request token in the session
request.session['token'] = request_token
# redirect to the UI server
return HttpResponseRedirect
(settings.INDIVO_UI_SERVER_BASE + '/oauth/authorize?
oauth_token=%s' % request_token['oauth_token'])
def after_auth(request):
# get the token and verifier from the URL parameters
# retrieve request token stored in the session
client = get_indivo_client(...)
# exchange request token for access token
access_token = parse_token_from_response
(client.post_access_token(data={'oauth_verifier' :
oauth_verifier}))
# store stuff in the session
request.session['access_token'] = access_token
# get record ID that came back with token
request.session['record_id'] =
access_token['xoauth_indivo_record_id']
# go to list of problems
return HttpResponseRedirect(reverse(problem_list))
def problem_list(request):
client = get_indivo_client(request)
record_id = request.session['record_id']
# get record information
record_xml = client.read_record(record_id = record_id)
# get problem list from most recent to oldest
problems_xml = client.read_problems(record_id =
record_id, parameters={'order_by': '-date_onset'})
def new_problem(request):
# get the variables and create a problem XML
params = ...
problem_xml = render_raw('problem', params,
type='xml')
# add the problem
client = get_indivo_client(request)
client.post_document(record_id = request.session
['record_id'], data=problem_xml)
# add a notification
client.record_notify(record_id = request.session
['record_id'], data={'content':'a new problem has been
added to your problem list'})
return HttpResponseRedirect(reverse(problem_list))
Other API calls
• get reports on labs, medications, allergies,
immunizations, etc.
• get basic record information
• add documents, version them, etc.
• store application-specific data not visible to
other apps (bookkeeping)
What about sharing?
• Carenets: a space for sharing, including
documents, apps, and people
• An app can be started with a carenet_id
instead of a record_id.
• The same API calls are available with a
carenet_id, but may see only
a subset of the data.
Background Apps
- most apps don’t need access
beyond the user session
- we tie the oAuth token to the web session
... unless the user authorizes more
Summary
- your app is activated for each record
- do the oAuth dance, get an access token
- write to the input of the data pipeline,
read from the end of the data pipeline,
all simple REST+oAuth calls
- use built-in widgets to get advanced functionality