Denne guide er primært målrettet til anvender/udvikler, som skal implementere en ny afprøvningsløsning og den har til formål, at give et eksempel på en eksisterede web applikation og facade.
Guiden beskriver en web applikation som bruger en backend, som interagere med Dokumentdelingsservice (DDS), og som bruger sikkerhed i henhold til NAP konteksten.
Der er beskrevet instruktioner til opsætning af et web projekt og en backend, som overholder givne NSP standarder. Guiden indeholder eksempler på kodeimplementationer, men ellers er projekterne tilgængelig på svn.nspop.dk og kan bruges som inspiration til et afprøvningsprojekt.
Hvis der er behov for yderligere dokumentation omkring hele NAP platformen, henvises til NAP Platform - Guide til anvendere.
Derudover findes der yderligere diagrammer og NAP SDK'erne på NAP SDK - Design og Arkitektur beskrivelse.
nap-reference-web er en web applikation, som anvender nap-typescript-sdk og nap-angular-sdk.
Dette kan køres indlejret i et værtssytem (eks. nap-java-host), hvori der tilføjes en NAP Bridge på den givne applikations global scope, således der kan kommunikeres med SDK'erne. Igennem kommunikationen vil der blive håndteret sikkerhed igennem anvendelse af en SAML assertion og patient konteksten vil kunne blive brugt igennem det indlejret værtssystem.
Derefter tilføjes SAML assertion som en header, samt en hardcoded SOR værdi som X-Organization Sor header, til kaldet af dokumentationdelingsservicen, som går igennem nap-reference facade.
nap-reference-facade er en java applikation, som anvender SEAL.java til at validere den SAMLAssertion der bliver sendt ind. Den står for at hente relevante aftale dokumenter (org.openehealth.ipf.commons) fra den valgte patient. For at formatere aftaledokumenterne fra XML til objekter, bruges biblioteket "dk.s4.hl7.builders". Før objekterne returneres, bliver kun relevant information sendt tilbage til nap-reference-web.
Nap-reference-web er bygget med Angular version 9 og fungerer som illustration på:
Brug af NAP SDK
Applikationens hovedfunktionalitet er at vise aftaledokumenter for den patient, der er i kontekst i det værtssystem, den er indlejret i (f.eks. nap-java-host).
Når applikationen er indlejret i et værtssystem er der to muligheder for at starte web klienten med docker-compose (INDSÆT LINK TIL OPSÆTNING AF DOCKER-COMPOSE)
1) Når projektet er opsat, kan man køre med dummy projekter således det ikke er nødvendigt at starte nap-reference-facade. Dette kan gøres ved at ændre i compose filen for development. (compose/development/docker-compose.yml)
command: npx ng serve --port 8080 --host 0.0.0.0 --disableHostCheck --public-host=localhost/nap/reference/web/
rettes til
command: npx ng serve --port 8080 --host 0.0.0.0 --disableHostCheck --public-host=localhost/nap/reference/web/ –-configuration=mock
2) Projektet startes samtidig med nap-reference-facade, hvor der hentes projekter fra backenden.
Da angular frameworket lægger sig op af model-view-controller pattern er dette også implementeret i nap-reference-web.
Derfor er der simple komponenter til at visning aftaler, hjælpinformation, fejl osv.
Services håndterer forretningslogikken.
Derfor er der simple services til håndtering af authentication, applikationsfejl og konfigurering osv.
Der ligger en .npmrc, som sætter npm registry til https://nexus.nspop.dk/nexus/repository/nsp-npm/
Nap-reference-web benytter sig af en konfigurationsfil (assets/configurtation.json), som loades via configuration-servicen. Denne konfigurationsfil bliver således overskrevet i de forskellige docker-compose setups.
Da NSP web applikationer kan blive deployet på vilkårlige paths, er det vigtigt at applikationen fungerer med relative paths. Detter er opnået ved hashrouting.
@NgModule({ imports: [RouterModule.forRoot(routes, { useHash: true })], exports: [RouterModule] }) export class AppRoutingModule { } |
Nap-reference-web benytter sig af testframeworket Karma, da det kommer default med angular. Karma bruger Istanbul til at genere test-coverage rapporter. Testene køres i en headless chromium browser.
Kodedokumentationen bliver generet med TSDoc.
Nap-reference-web implementerer version 1 af eventkataloget.
Session-open starter en trusted session hvor brugerens SAMLassertion overføres. Session-close lukker sessionen og brugerens SAMLassertion slettes. Denne funktionalitet findes i auth-servicen.
export class AuthService { private sessionMessageSubject = new BehaviorSubject<NAPMessage | undefined>( undefined ); /** * The current session * * @memberof AuthService */ public session$ = this.sessionMessageSubject.asObservable(); constructor(private napSDK: NapAngularService) { this.napSDK.incomming$ .pipe( filterEvents([ NAPEventCatalogue.v1.SessionOpen, NAPEventCatalogue.v1.SessionClose, ]) ) .subscribe((napMessage) => { if (napMessage.event.type === NAPEventCatalogue.v1.SessionOpen) { this.sessionMessageSubject.next(napMessage); } else { this.sessionMessageSubject.next(undefined); } }); const napMsg: NAPMessage = { date: new Date().toISOString(), id: UUID(), event: { type: NAPEventCatalogue.v1.SessionOpen }, }; // Ask for the SAMLassertion in host this.napSDK.sendMessage(napMsg); } /** * Tricker logout event */ logout(): void { this.sessionMessageSubject.next(undefined); const napMsg: NAPMessage = { date: new Date().toISOString(), id: UUID(), event: { type: NAPEventCatalogue.v1.SessionClose }, }; this.napSDK.sendMessage(napMsg); } } |
Patient-open sender den brugervalgte patient journal og patient-close lukker den bruger valgte patient (set fra det indlejrede systems perspektiv). Et eksempel på dette kan ses i appointment.component
constructor( private napSDK: NapAngularService, private appointmentService: AppointmentService, private authService: AuthService ) { const napMsg: NAPMessage = { date: new Date().toISOString(), id: UUID(), event: { type: NAPEventCatalogue.v1.PatientOpen, }, }; this.napSDK.sendMessage(napMsg); } public currentPatient$: Observable<NAPPatientInfo | undefined> = this.napSDK.incomming$.pipe( filterEvent(NAPEventCatalogue.v1.PatientOpen), map(message => FHIRValueGetter.getPatientInfo(message)) ); |
Session-error sendes, hvis der sker en uventet fejl i projektet skal dette sendes til værtssystemet og vice versa. Et eksempel på dette findes i appointment-service:
private appointmentEndPoint$ = this.configurationService.fetch( config => config.appointmentsEndpoint ); private serverUrl = this.configurationService.fetch(config => config.serverUrl); private createNapErrorMessage(error: GenericAppError): NAPMessage { return { date: new Date().toISOString(), id: UUID(), event: { type: NAPEventCatalogue.v1.SessionError, context: [ { resource: { resourceType: FHIRValueSetter.FHIRResourceType.Basic, code: { coding: [ { code: NAPEventCatalogue.v1.SessionError, system: FHIRValueSetter.FHIRSystem.NAP, }, ], }, identifier: [ { system: FHIRValueSetter.FHIRIdentifierSystem.NAPErrorMessage, value: error.innerError?.message ? error.innerError?.message : '', }, { system: FHIRValueSetter.FHIRIdentifierSystem.NAPErrorDescription, value: error.errorMessage, }, ], }, }, ], } } } public getAppointments(patientIdentifier: string | undefined): Observable<any[] | undefined> { return combineLatest( [ this.serverUrl, this.appointmentEndPoint$, this.serviceActivator ] ).pipe( switchMap(([serverUrl, endpointPath, _]) => this.http.get<any[]>(serverUrl + endpointPath + '/' + patientIdentifier)), catchError(error => { this.errorService.postError(error); this.napSDK.sendMessage(this.createNapErrorMessage(error)); // indicate to the host that something went wrong return of(undefined); }), ); } |
Nap-reference-facade er bygget med java 8 og fungerer som illustration på:
Brug af Dokumentdelingsservice (DDS)
Dependencies er hentet fra https://nexus.nspop.dk/nexus/content/groups/public og de dependencies, som stilles til rådighed af wildfly8 platformen er angivet med scope provided.
For at kunne kalde Dokumentdelingsservice (DDS) er følgende dependencies anvendt:
dk.sosi.seal | Java-bibliotek til understøttelse af "Den Gode Webservice" og validering af SAMLassertion, se http://digitaliser.dk/group/374971. |
dk.s4.hl7.builders | Dansk profileret XML converter af hl7 clinical documents |
org.openehealth.ipf.commons | Dansk profileret bibliotek til Cross Enterprise Document sharing. Bruges til at integrere Dokumentdelingsservice (DDS). Du kan læse mere på https://github.com/KvalitetsIT/aftaledeling/tree/master/dgws-eksempel/src/main/java/dk/sds/appointment. |
Alt konfiguration foregår ved at loade filer fra et selv-defineret et wildfly module ind i classpath under deployment.
Dette gør wildfly ved at modulet defineres i jboss-deployment-structure.xml.
Testene bliver eksekveret af maven-surefire-plugin med test frameworket junit. Test coverage bliver målt af Jacoco.
Kodedokumentationen overholder javadoc standarden således dette kan generes med et værktøj fra fx den IDE man bruger.
dk.sosi.seal bliver brugt til at verificere SAMLassertion.
/** * @param headers Map of request headers * @return Saml assertion if its valid or null in case of invalid SAML assertion * @throws AuthenticationException If ant authentication exception occure */ public OIOSAMLAssertion extractAndValidate(MultivaluedMap<String, String> headers) throws AuthenticationException { final List<String> authentication = headers.get(AUTHENTICATION_PROPERTY); try { String xml = new String(Base64.decode(authentication.get(0)), StandardCharsets.UTF_8); Document doc = parseXml(xml); Element encryptedAssertionElm = doc.getDocumentElement(); PrivateKey privateKeyForAudience = certificateVault.getSystemCredentialPair().getPrivateKey(); // decrypt the xml for the assertion and parse it final Element element = EncryptionUtil.decryptAndDetach(encryptedAssertionElm, privateKeyForAudience); OIOSAMLAssertion assertion = new OIOSAMLAssertion(element); log.debug("extracted: \n" + assertion.getUID()); validateAssertion(assertion); return assertion; } catch (IOException | ParserConfigurationException | SAXException e) { throw new AuthenticationException("Could not validate authentication header", e); } } |
Nap-reference-facade har 2 snitflader som bliver beskrevet i følgende.
Den eneste aftage af denne service er nap-reference-web.
Headers | |
---|---|
Key | Value |
Authentication | BASE64 encoded SAMLassertion |
X-OrganizationSor | Sor nummer (bruges af dokumentdelingsservicen) |
Bruges af loadbalanceren for at tjekke at servicen er deployet. Returnerer en html side med deployment info.
Da denne service ikke er afhængige af database eller andre interne services, returnere den altid statuskode 200, hvis aplikationen kører.
http://nap/web/reference/services/main/aftaler/124567890
{
"title": "Ekkokardiografi",
"orgName": "Skejby Sygehus",
"indication": "Har ondt i hjertet somme tider",
"date": 1591142400
}