How to Build an Indivo X Personal Health App

Post on 06-May-2015

3.569 views 0 download

description

Details on building an app for the Indivo X Personally Controlled Health Record

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 emailproblems@apps.indivo.org

• 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