How to Build an Indivo X Personal Health App
-
Upload
ben-adida -
Category
Health & Medicine
-
view
3.566 -
download
0
description
Transcript of How to Build an Indivo X Personal Health App
How to buildan Indivo X
Personal Health AppBen Adida
Indivo X Users Meeting15 April 2010
Demo
Four Steps
1. Scope and framing of your app
2. Authentication and Authorization
3. REST API calls
4. UI widgets
Basic Terminology
• Account
• Record
• PHA / User App
• Admin App
• (Chrome App)
1. Scope
Screen Real-Estatecontrolled by PHA
For Example
Anatomy of a PHA• name
“Problems”
• description“track your problems”
• principal [email protected]
• data use agreement:what the app intends to do with the data it reads from the record.
• start URLhttp://problems/auth/start
• post-auth URLhttp://problems/auth/after
• consumer key838xdnwk-sdf-werkj34
• consumer secret23lnbls-235lnsdf-2343
2. Auth
Components
User's
Browser
Indivo Server PHA
Access Token
OAuth Protocolconsumer_tokenconsumer_secret
authentication
signed
HTTP+POX
User's
Browser
Indivo Server
(Data Service)PHA
(Consumer)
HMAC-SHA1
RSA-SHA1
....
With the first click...
begin the auth process
IFRAME directed tothe PHA’s start URL
with parameter record_id
User's
BrowserIndivo
ServerPHA
Connection
Step (1)
add
token
GET request_token
REDIRECT
authorize
authorize the app
User's
Browser
Indivo
ServerPHA
Connection
Step (2)
Authorization
Process
post-add
REDIRECT
authorize
redirect to app
IFRAME directed tothe PHA’s post-auth URL
which finishes the oAuth process
User's
Browser
Indivo
ServerPHA
Connection
Step (3)
post-add
GET access_token
token
Interaction
Phase
User's
Browser
Indivo
ServerPHA
token
GET data
data
OAuth Request
Authorization: OAuth realm="https://indivohealth.org/", oauth_consumer_key="0685bd9184jfhq22", oauth_signature_method="HMAC-SHA1", oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", oauth_timestamp="137131200", oauth_nonce="4572616e48616d6d65724c61686176", oauth_version="1.0"
The code must beawfully complicated ...
def get_indivo_client(request, with_token=True): client = IndivoClient(CONSUMER_KEY,
CONSUMER_SECRET, INDIVO_SERVER_LOCATION)
if with_token: client.update_token(request.session['token']) return client
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))
3. REST API Calls
get data, e.g. problem list
web platform model
User's
Browser
Indivo Server PHA
Access Token
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 onlya subset of the data.
4. UI Widgets
Auto-Complete
Auto-Completedef code_lookup(request): client = get_indivo_client(request) query = request.GET['query']
# reformat this for the jQuery autocompleter codes = simplejson.loads(
client.lookup_code(coding_system='umls-snomed',parameters= {'q' : query}))
formatted_codes = {'query': query, 'suggestions': [c['full_value'] for c in codes], 'data': codes}
return HttpResponse(simplejson.dumps(formatted_codes), mimetype="text/plain")
Auto-Complete <script src="jquery.js"></script> <script src="jquery-ui.js"></script> <script src="jquery.autocomplete.js"></script>
<script> $('#problem_fullname').autocomplete({ serviceUrl: 'codelookup', minChars: 2, onSelect: function(value, data) { $('#problem_code').val(data.code); } });</script>
Sharing & Audit
def one_problem(request, problem_id): ... surl_credentials = client.get_surl_credentials() ...
Sharing & Audit
<script src="{{SERVER_BASE}}/lib/widgets.js"></script>
<script> Indivo.setup('{{INDIVO_UI_SERVER_BASE}}');</script>
<script>Indivo.Auth.setToken("{{token}}","{{secret}}");
Indivo.Widget.DocumentAccess.add('{{record_id}}', '{{problem_id}}');</script>
Upcoming Features...
Background Apps
- most apps don’t need accessbeyond 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