-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Deploying to gh-pages from @ 7c7bfe9 🚀
- Loading branch information
Showing
7 changed files
with
451 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
FROM docker.io/library/node:22 | ||
|
||
RUN git clone https://github.com/smart-on-fhir/growth-chart-app.git /app | ||
|
||
WORKDIR /app | ||
|
||
RUN npm install | ||
|
||
EXPOSE 9000 | ||
|
||
CMD ["npm", "run", "start"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# Launch growth-chart smart app on Aidbox and auth and login via KeyCloack | ||
|
||
|
||
|
||
``` sh | ||
docker compose up | ||
``` | ||
|
||
aidbox - http://localhost:8080 | ||
keycloak - http://localhost:88888 | ||
growth-chart - http://localhost:9000 | ||
|
||
## EHR launch | ||
|
||
### Patient launch | ||
|
||
Open http://localhost:7070 (ehr emulator) | ||
|
||
|
||
Need launch uri | ||
|
||
``` curl-config | ||
POST /rpc | ||
method: aidbox.smart/get-launch-uri | ||
params: | ||
user: patient | ||
iss: http://localhost:8080 | ||
client: growth_chart | ||
ctx: | ||
patient: patient | ||
``` | ||
|
||
http://localhost:9000 | ||
login using KeyCloack | ||
username: provider | ||
password: provider | ||
|
||
### Provider launch | ||
|
||
``` curl-config | ||
POST /rpc | ||
method: aidbox.smart/get-launch-uri | ||
params: | ||
user: provider | ||
iss: http://localhost:8080 | ||
client: growth_chart | ||
ctx: | ||
patient: patient | ||
``` | ||
|
||
## Stand alone launch | ||
|
||
### Patient launch | ||
|
||
`user.fhirUser` should be ref to Patient | ||
|
||
http://localhost:9000 | ||
login using KeyCloack | ||
username: patient | ||
password: patient | ||
|
||
|
||
### Provider launch - not supported |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
{ | ||
"type": "transaction", | ||
"entry": [ | ||
{ | ||
"request": { | ||
"method": "PUT", | ||
"url": "/Client/growth_chart" | ||
}, | ||
"resource": { | ||
"resourceType": "Client", | ||
"id": "growth_chart", | ||
"auth": { | ||
"authorization_code": { | ||
"redirect_uri": "http://localhost:9000/", | ||
"refresh_token": true, | ||
"token_format": "jwt", | ||
"access_token_expiration": 3600000 | ||
} | ||
}, | ||
"smart": { | ||
"launch_uri": "http://localhost:9000/launch.html" | ||
}, | ||
"type": "smart-app", | ||
"secret": "quOfCRS7ty1RMUQq", | ||
"grant_types": [ | ||
"authorization_code" | ||
] | ||
} | ||
}, | ||
{ | ||
"request": { | ||
"method": "PUT", | ||
"url": "/IdentityProvider/keycloak" | ||
}, | ||
"resource": { | ||
"resourceType": "IdentityProvider", | ||
"scopes": [ | ||
"profile", | ||
"openid" | ||
], | ||
"system": "keycloak", | ||
"userinfo_endpoint": "http://localhost:8888/realms/patients/protocol/openid-connect/userinfo", | ||
"authorize_endpoint": "http://localhost:8888/realms/patients/protocol/openid-connect/auth", | ||
"client": { | ||
"id": "aidbox", | ||
"secret": "HOuPXmduHfTjhtW0eqAeMsHZJbRNVc8x" | ||
}, | ||
"title": "Keycloak", | ||
"active": true, | ||
"id": "keycloak", | ||
"token_endpoint": "http://keycloak:8888/realms/patients/protocol/openid-connect/token", | ||
"userinfo-source": "id-token" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
version: '3.7' | ||
volumes: | ||
aidbox_pg_data: {} | ||
|
||
services: | ||
|
||
growth_chart: | ||
build: | ||
context: . | ||
dockerfile: ./Dockerfile.growthchart | ||
ports: | ||
- 9000:9000 | ||
|
||
keycloak: | ||
image: quay.io/keycloak/keycloak:26.0.6 | ||
volumes: | ||
- ./keycloak.json:/opt/keycloak/data/import/keycloak.json | ||
ports: | ||
- 8888:8888 | ||
environment: | ||
KC_HTTP_PORT: 8888 | ||
KC_BOOTSTRAP_ADMIN_USERNAME: admin | ||
KC_BOOTSTRAP_ADMIN_PASSWORD: admin | ||
command: start-dev --import-realm | ||
|
||
aidbox_db: | ||
image: healthsamurai/aidboxdb:17 | ||
volumes: | ||
- aidbox_pg_data:/data:delegated | ||
environment: | ||
PGDATA: /data | ||
POSTGRES_USER: aidbox | ||
POSTGRES_PORT: '5432' | ||
POSTGRES_DB: aidbox | ||
POSTGRES_PASSWORD: nP0s8ALcTk | ||
|
||
aidbox: | ||
image: healthsamurai/aidboxone:edge | ||
depends_on: | ||
- aidbox_db | ||
ports: | ||
- 8080:8080 | ||
volumes: | ||
- ./aidbox.json:/tmp/aidbox.json | ||
environment: | ||
BOX_INIT_BUNDLE: file:///tmp/aidbox.json | ||
AIDBOX_TERMINOLOGY_SERVICE_BASE_URL: https://tx.fhir.org/r4 | ||
AIDBOX_FHIR_PACKAGES: hl7.fhir.r4.core#4.0.1 | ||
AIDBOX_FHIR_SCHEMA_VALIDATION: true | ||
AIDBOX_CREATED_AT_URL: https://aidbox.app/ex/createdAt | ||
AIDBOX_CLIENT_SECRET: vbDPgXnz0H | ||
AIDBOX_CORRECT_AIDBOX_FORMAT: true | ||
AIDBOX_ADMIN_PASSWORD: password | ||
AIDBOX_COMPLIANCE: enabled | ||
BOX_SEARCH_FHIR__COMPARISONS: true | ||
PGHOST: aidbox_db | ||
BOX_COMPATIBILITY_VALIDATION_JSON__SCHEMA_REGEX: '#{:fhir-datetime}' | ||
PGUSER: aidbox | ||
AIDBOX_PORT: 8080 | ||
PGDATABASE: aidbox | ||
PGPASSWORD: nP0s8ALcTk | ||
PGPORT: '5432' | ||
BOX_SEARCH_INCLUDE_CONFORMANT: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>FHIR Patient List</title> | ||
</head> | ||
<body> | ||
|
||
<h1>EHR Emulator</h1> | ||
|
||
<form id="loginForm"> | ||
<h2>Login</h2> | ||
<label> | ||
Username: <input type="text" id="username" required /> | ||
</label><br/> | ||
<label> | ||
Password: <input type="password" id="password" required /> | ||
</label><br/> | ||
<button type="submit">Login</button> | ||
</form> | ||
<div id="patientList" style="display:none;"> | ||
<h1>Patient List</h1> | ||
<div id="user-info"></div> | ||
<ul id="patients"></ul> | ||
</div> | ||
|
||
<script> | ||
let accessToken = ''; | ||
|
||
// const username = 'provider'; | ||
// accessToken = ''; | ||
// showUserInfo(username); | ||
// const fhirUrl = 'http://localhost:8080/fhir/Patient?_count=20&birthdate=ge2000'; // Replace with your FHIR server endpoint | ||
// fetch(fhirUrl, {method: 'GET', headers: {'Authorization': 'Bearer ' + accessToken}}) | ||
// .then(response => response.json()) | ||
// .then(fhirData => {displayPatients(fhirData);}) | ||
// .catch(error => {console.error('Error fetching patients:', error);}); | ||
|
||
document.getElementById('loginForm').addEventListener('submit', function(e){ | ||
e.preventDefault(); | ||
|
||
const username = document.getElementById('username').value; | ||
const password = document.getElementById('password').value; | ||
const client_id = 'ehr'; // Replace with your client_id | ||
|
||
// Token endpoint URL | ||
const tokenUrl = 'http://localhost:8080/auth/token'; // Replace with your token endpoint | ||
|
||
// Prepare data for token request | ||
const data = new URLSearchParams(); | ||
data.append('grant_type', 'password'); | ||
data.append('username', username); | ||
data.append('password', password); | ||
data.append('client_id', client_id); | ||
// data.append('client_secret', client_secret); | ||
|
||
|
||
// Request an access token | ||
fetch(tokenUrl, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/x-www-form-urlencoded' | ||
}, | ||
body: data.toString() | ||
}) | ||
.then(response => response.json()) | ||
.then(tokenData => { | ||
if(tokenData.access_token){ | ||
showUserInfo(username); | ||
accessToken = tokenData.access_token; | ||
// Use the access token to fetch patients | ||
const fhirUrl = 'http://localhost:8080/fhir/Patient?_count=20&birthdate=ge2000'; | ||
fetch(fhirUrl, { | ||
method: 'GET', | ||
headers: { | ||
'Authorization': 'Bearer ' + tokenData.access_token | ||
} | ||
}) | ||
.then(response => response.json()) | ||
.then(fhirData => { | ||
displayPatients(fhirData); | ||
}) | ||
.catch(error => { | ||
console.error('Error fetching patients:', error); | ||
}); | ||
} else { | ||
console.error('Authentication failed:', tokenData); | ||
alert('Authentication failed: ' + (tokenData.error_description || 'Unknown error')); | ||
} | ||
}) | ||
.catch(error => { | ||
console.error('Error during authentication:', error); | ||
}); | ||
}); | ||
|
||
function showUserInfo(username) { | ||
const userInfo = document.getElementById('user-info'); | ||
userInfo.innerHTML = 'You logged in as ' + username; | ||
} | ||
|
||
function launch(token, patientId) { | ||
const fhirUrl = 'http://localhost:8080/rpc'; | ||
let body = { | ||
method: "aidbox.smart/get-launch-uri", | ||
params: { | ||
user: "practitioner", | ||
iss: "http://localhost:8080/fhir", | ||
client: "growth_chart", | ||
ctx: {patient: patientId} | ||
} | ||
} | ||
fetch(fhirUrl, { | ||
method: 'POST', | ||
headers: {'Authorization': 'Bearer ' + token, | ||
'content-type': 'application/json'}, | ||
body: JSON.stringify(body) | ||
}) | ||
.then(response => response.json()) | ||
.then(resp => { | ||
// console.log("resp", resp) | ||
window.location = resp.result.uri | ||
}) | ||
.catch(error => { | ||
console.error('Error fetching patients:', error); | ||
}); | ||
} | ||
|
||
function displayPatients(fhirData){ | ||
document.getElementById('loginForm').style.display = 'none'; | ||
document.getElementById('patientList').style.display = 'block'; | ||
|
||
const patientsUl = document.getElementById('patients'); | ||
patientsUl.innerHTML = ''; | ||
|
||
if(fhirData && fhirData.entry){ | ||
fhirData.entry.forEach(function(entry){ | ||
const patient = entry.resource; | ||
let name = 'Unknown'; | ||
let id = patient.id; | ||
if(patient.name && patient.name.length > 0){ | ||
const nameObj = patient.name[0]; | ||
const given = nameObj.given ? nameObj.given.join(' ') : ''; | ||
const family = nameObj.family || ''; | ||
const birthDate = patient.birthDate || ''; | ||
name = `${given} ${family} (${birthDate}) <span style="color: blue" onclick="launch('${accessToken}', '${id}')">Launch Growth chart app</span>`; | ||
} | ||
const li = document.createElement('li'); | ||
li.innerHTML = name; | ||
patientsUl.appendChild(li); | ||
}); | ||
} else { | ||
const li = document.createElement('li'); | ||
li.textContent = 'No patients found.'; | ||
patientsUl.appendChild(li); | ||
} | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"resourceType" : "Bundle", | ||
"type" : "transaction", | ||
"entry" : [ | ||
{ | ||
"request": { | ||
"method": "PUT", | ||
"url": "/Patient/marat-test-init-bundle" | ||
}, | ||
"resource" : { | ||
"resourceType" : "Patient", | ||
"id" : "marat-test-init-bundle", | ||
"gender": "male" | ||
} | ||
} | ||
] | ||
} |
Oops, something went wrong.