├── requirements.txt ├── angular ├── src │ ├── app │ │ ├── patients │ │ │ └── patients.component.scss │ │ ├── settings │ │ │ ├── settings.component.scss │ │ │ ├── settings.component.html │ │ │ └── settings.component.ts │ │ ├── patient-detail │ │ │ ├── patient-detail.component.scss │ │ │ ├── patient-detail.component.html │ │ │ ├── patient-detail.component.ts │ │ │ └── patient-detail.component.spec.ts │ │ ├── capability-statement │ │ │ ├── capability-statement.component.scss │ │ │ ├── capability-statement.component.html │ │ │ └── capability-statement.component.ts │ │ ├── mag │ │ │ └── mag.component.scss │ │ ├── fhirpath.d.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ └── home.component.ts │ │ ├── app.component.scss │ │ ├── operation-outcome │ │ │ ├── operation-outcome.component.spec.ts │ │ │ ├── operation-outcome.component.html │ │ │ └── operation-outcome.component.scss │ │ ├── upload │ │ │ ├── upload.component.html │ │ │ ├── upload.component.scss │ │ │ └── upload.component.ts │ │ ├── fhirpath.service.ts │ │ ├── app.component.ts │ │ ├── app.component.spec.ts │ │ └── app.component.html │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── typing.d.ts │ ├── assets │ │ ├── favicon-100x100.png │ │ └── i18n │ │ │ ├── de.json │ │ │ └── en.json │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ ├── main.ts │ ├── index.html │ ├── test.ts │ ├── _variables.scss │ ├── styles.scss │ └── polyfills.ts ├── Dockerfile ├── .devcontainer │ ├── devcontainer.json │ └── Dockerfile ├── docker-entrypoint.sh ├── dist.sh ├── e2e │ ├── app.po.ts │ ├── tsconfig.e2e.json │ └── app.e2e-spec.ts ├── .editorconfig ├── .travis.yml ├── CONTRIBUTING.md ├── parameters.json ├── tsconfig.json ├── .gitignore ├── protractor.conf.js ├── .vscode │ └── launch.json ├── default.conf ├── karma.conf.js └── README.md ├── .DS_Store ├── src ├── main │ ├── resources │ │ ├── META-INF │ │ │ ├── cxf │ │ │ │ └── org.apache.cxf.logger │ │ │ └── services │ │ │ │ └── org │ │ │ │ └── apache │ │ │ │ └── camel │ │ │ │ ├── TypeConverterLoader │ │ │ │ └── component │ │ │ │ ├── mhd-pharm5 │ │ │ │ ├── pmir-iti104 │ │ │ │ ├── pmir-iti93 │ │ │ │ ├── mhd-iti65-v401 │ │ │ │ ├── mhd-iti66-v401 │ │ │ │ └── mhd-iti67-v401 │ │ ├── cacerts │ │ ├── keystore.jks │ │ ├── example-client-certificate.jks │ │ ├── example-server-certificate.p12 │ │ ├── static │ │ │ ├── assets │ │ │ │ ├── favicon-100x100.png │ │ │ │ └── i18n │ │ │ │ │ ├── de.json │ │ │ │ │ └── en.json │ │ │ └── runtime.b36ad241e7dd5c21.js │ │ └── application-metrics.yml │ └── java │ │ ├── ch │ │ └── bfh │ │ │ └── ti │ │ │ └── i4mi │ │ │ └── mag │ │ │ ├── TlsParameterTest.java │ │ │ ├── mhd │ │ │ ├── iti66 │ │ │ │ ├── Iti66Condition.java │ │ │ │ └── IdRequestConverter.java │ │ │ ├── pharm5 │ │ │ │ ├── Pharm5Endpoint.java │ │ │ │ ├── Pharm5Component.java │ │ │ │ ├── Pharm5Constants.java │ │ │ │ ├── Pharm5TransactionConfiguration.java │ │ │ │ └── Pharm5AuditStrategy.java │ │ │ ├── PHARM.java │ │ │ ├── iti67 │ │ │ │ └── Iti67FromIti57ResponseConverter.java │ │ │ └── iti68 │ │ │ │ └── Iti68RequestConverter.java │ │ │ ├── pmir │ │ │ ├── iti93 │ │ │ │ ├── Iti93Condition.java │ │ │ │ ├── Iti93Constants.java │ │ │ │ ├── Iti93Component.java │ │ │ │ ├── Iti93Endpoint.java │ │ │ │ ├── Iti93TransactionConfiguration.java │ │ │ │ ├── PMIR.java │ │ │ │ └── Iti93AuditDataset.java │ │ │ ├── BasePMIRResponseConverter.java │ │ │ ├── iti104 │ │ │ │ ├── Iti104Component.java │ │ │ │ ├── Iti104Endpoint.java │ │ │ │ ├── Iti104TransactionConfiguration.java │ │ │ │ ├── PMIR.java │ │ │ │ └── Iti104AuditDataset.java │ │ │ └── Test.java │ │ │ ├── xua │ │ │ ├── ErrorResponse.java │ │ │ ├── MySAMLBootstrap.java │ │ │ ├── OAuth2TokenResponse.java │ │ │ ├── AuthException.java │ │ │ ├── XuaUtils.java │ │ │ ├── AuthenticationRequest.java │ │ │ ├── IDPConfig.java │ │ │ ├── LoginAtnaLogger.java │ │ │ ├── IDPAssertionDetailsService.java │ │ │ ├── AssertionRequest.java │ │ │ ├── ClientValidationService.java │ │ │ ├── MySAMLContextProvider.java │ │ │ ├── ListIDPRouteBuilder.java │ │ │ └── TokenRenew.java │ │ │ ├── audit │ │ │ └── TLSCloseSocket.java │ │ │ ├── ppqm │ │ │ └── PpqmConfiguration.java │ │ │ ├── RequestIdFilter.java │ │ │ ├── FilterConfig.java │ │ │ ├── TraceHeaderLoggingFilter.java │ │ │ ├── LoggingSpanHandler.java │ │ │ ├── TracingConfiguration.java │ │ │ └── MagConstants.java │ │ └── org │ │ ├── husky │ │ └── communication │ │ │ └── ch │ │ │ └── camel │ │ │ ├── package-info.java │ │ │ └── chpharm1 │ │ │ ├── requests │ │ │ ├── package-info.java │ │ │ └── query │ │ │ │ └── package-info.java │ │ │ ├── transform │ │ │ └── requests │ │ │ │ └── query │ │ │ │ ├── ChFindDispensesQueryTransformer.java │ │ │ │ ├── ChFindPrescriptionsQueryTransformer.java │ │ │ │ ├── ChFindMedicationTreatmentPlansQueryTransformer.java │ │ │ │ ├── ChFindPrescriptionsForDispenseQueryTransformer.java │ │ │ │ ├── ChFindMedicationAdministrationsQueryTransformer.java │ │ │ │ └── ChFindPrescriptionsForValidationQueryTransformer.java │ │ │ ├── package-info.java │ │ │ └── ChPharm1Service.java │ │ └── openehealth │ │ └── ipf │ │ ├── commons │ │ └── ihe │ │ │ └── fhir │ │ │ ├── iti67_v401 │ │ │ ├── Iti67ClientRequestFactory.java │ │ │ ├── Iti67Options.java │ │ │ ├── Iti67OptionsProvider.java │ │ │ ├── Iti67AuditStrategy.java │ │ │ └── Iti67TransactionConfiguration.java │ │ │ ├── iti66_v401 │ │ │ ├── Iti66ClientRequestFactory.java │ │ │ ├── Iti66TransactionConfiguration.java │ │ │ └── Iti66AuditStrategy.java │ │ │ └── iti65_v401 │ │ │ ├── Iti65Constants.java │ │ │ ├── Iti65AuditDataset.java │ │ │ └── Iti65ServerAuditStrategy.java │ │ └── platform │ │ └── camel │ │ └── ihe │ │ └── fhir │ │ ├── iti65_v401 │ │ ├── Iti65Endpoint.java │ │ └── Iti65Component.java │ │ ├── iti66_v401 │ │ ├── Iti66Endpoint.java │ │ └── Iti66Component.java │ │ └── iti67_v401 │ │ ├── Iti67Endpoint.java │ │ └── Iti67Component.java └── test │ ├── resources │ ├── cacerts │ ├── keystore.jks │ ├── example-client-certificate.jks │ └── example-server-certificate.p12 │ └── java │ ├── ch.bfh.ti.i4mi.mag.ppqm │ ├── TestConstants.java │ └── PpqmTestBase.java │ └── ch │ └── bfh │ └── ti │ └── i4mi │ └── mag │ └── mhd │ ├── iti65 │ └── Iti65RequestConverterTest.java │ └── BaseQueryResponseConverterTest.java ├── docs ├── assets │ ├── auth.png │ ├── mag_logo.png │ ├── favicon-256x256.png │ └── auth.uml.txt ├── snippets │ ├── http_iti20.txt │ ├── http_getxua.txt │ └── http_iti104.txt ├── stylesheets │ └── extra.css ├── index.md ├── endpoints.md ├── docker.md └── changelog.md ├── example-config ├── client.jks ├── server.p12 └── kubernetes-config.yml ├── run.sh ├── .vscode ├── settings.json └── launch.json ├── .gitignore ├── .github └── workflows │ ├── angular_test.yml │ ├── documentation.yml │ ├── angular_build.yml │ ├── codeql_java.yml │ └── publish_docker.yml ├── Dockerfile ├── mkdocs.yml └── example-playground └── application.yml /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material~=9.1.6 2 | -------------------------------------------------------------------------------- /angular/src/app/patients/patients.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /angular/src/app/settings/settings.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /angular/src/app/patient-detail/patient-detail.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/.DS_Store -------------------------------------------------------------------------------- /src/main/resources/META-INF/cxf/org.apache.cxf.logger: -------------------------------------------------------------------------------- 1 | org.apache.cxf.common.logging.Log4jLogger -------------------------------------------------------------------------------- /docs/assets/auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/docs/assets/auth.png -------------------------------------------------------------------------------- /angular/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /docs/assets/mag_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/docs/assets/mag_logo.png -------------------------------------------------------------------------------- /angular/src/typing.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.json' { 2 | const value: any; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /example-config/client.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/example-config/client.jks -------------------------------------------------------------------------------- /example-config/server.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/example-config/server.p12 -------------------------------------------------------------------------------- /src/main/resources/cacerts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/main/resources/cacerts -------------------------------------------------------------------------------- /src/test/resources/cacerts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/test/resources/cacerts -------------------------------------------------------------------------------- /angular/src/app/capability-statement/capability-statement.component.scss: -------------------------------------------------------------------------------- 1 | .display { 2 | display: inline-block; 3 | } 4 | -------------------------------------------------------------------------------- /docs/assets/favicon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/docs/assets/favicon-256x256.png -------------------------------------------------------------------------------- /src/main/resources/keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/main/resources/keystore.jks -------------------------------------------------------------------------------- /src/test/resources/keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/test/resources/keystore.jks -------------------------------------------------------------------------------- /angular/src/assets/favicon-100x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/angular/src/assets/favicon-100x100.png -------------------------------------------------------------------------------- /angular/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | COPY ./default.conf /etc/nginx/templates/default.conf.template 3 | COPY ./dist /usr/share/nginx/html 4 | -------------------------------------------------------------------------------- /angular/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": {}, 4 | "exclude": ["test.ts", "**/*.spec.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/example-client-certificate.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/main/resources/example-client-certificate.jks -------------------------------------------------------------------------------- /src/main/resources/example-server-certificate.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/main/resources/example-server-certificate.p12 -------------------------------------------------------------------------------- /src/test/resources/example-client-certificate.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/test/resources/example-client-certificate.jks -------------------------------------------------------------------------------- /src/test/resources/example-server-certificate.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/test/resources/example-server-certificate.p12 -------------------------------------------------------------------------------- /src/main/resources/static/assets/favicon-100x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i4mi/MobileAccessGateway/HEAD/src/main/resources/static/assets/favicon-100x100.png -------------------------------------------------------------------------------- /angular/.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Angular remote sample", 3 | "dockerFile": "Dockerfile", 4 | "appPort": 4200, 5 | "postCreateCommand": "yarn install" 6 | } 7 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p secret 3 | cp $1/* secret 4 | mvn clean compile exec:java -Dspring.config.additional-location=file:$1/application.yml 5 | rm -f secret/* 6 | rmdir secret 7 | -------------------------------------------------------------------------------- /angular/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -eu 3 | 4 | envsubst '${MAG} ${MATCHBOX} ${DOMAIN}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf 5 | 6 | exec "$@" 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "automatic", 3 | "java.debug.settings.onBuildFailureProceed": true, 4 | "java.compile.nullAnalysis.mode": "automatic" 5 | } -------------------------------------------------------------------------------- /angular/src/app/patient-detail/patient-detail.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
{{ patient | json }}
4 |
5 |
6 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org/apache/camel/TypeConverterLoader: -------------------------------------------------------------------------------- 1 | # Generated by camel build tools - do NOT edit this file! 2 | org.husky.communication.ch.camel.chpharm1.transform.ChPharm1ConvertersLoader 3 | -------------------------------------------------------------------------------- /angular/src/app/mag/mag.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | .display { 7 | display: inline-block; 8 | margin-bottom: 10px; 9 | } 10 | 11 | .column50 { 12 | width: 40%; 13 | } 14 | -------------------------------------------------------------------------------- /docs/snippets/http_iti20.txt: -------------------------------------------------------------------------------- 1 | POST /ARR/fhir/AuditEvent HTTP/1.1 2 | Content-Type: application/fhir+xml 3 | 4 | 5 | 6 | ... 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /angular/src/assets/i18n/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": { 3 | "required": "Dieses Feld ist erforderlich.", 4 | "maxLength": "Dieses Feld darf maximal {{ maxLength }} Zeichen haben." 5 | }, 6 | "hint": { 7 | "supportLink": "Info" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /angular/src/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": { 3 | "required": "This field is required.", 4 | "maxLength": "This field has a maximum length of {{ maxLength }} characters." 5 | }, 6 | "hint": { 7 | "supportLink": "Info" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /angular/dist.sh: -------------------------------------------------------------------------------- 1 | ng build --configuration production 2 | cp -r ../MobileAccessGateway/src/main/resources/static/not-authenticated.html dist 3 | rm -rf ../MobileAccessGateway/src/main/resources/static/* 4 | cp -r dist/* ../MobileAccessGateway/src/main/resources/static 5 | -------------------------------------------------------------------------------- /angular/src/app/fhirpath.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'fhirpath' { 2 | export function evaluate( 3 | resource: any, 4 | path: string, 5 | context: any 6 | ): (resource: any) => any; 7 | export function compile(path: string, context: any): (resource: any) => any; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/static/assets/i18n/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": { 3 | "required": "Dieses Feld ist erforderlich.", 4 | "maxLength": "Dieses Feld darf maximal {{ maxLength }} Zeichen haben." 5 | }, 6 | "hint": { 7 | "supportLink": "Info" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/resources/static/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": { 3 | "required": "This field is required.", 4 | "maxLength": "This field has a maximum length of {{ maxLength }} characters." 5 | }, 6 | "hint": { 7 | "supportLink": "Info" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /angular/e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /angular/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["jasmine", "jasminewd2", "node"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /angular/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /angular/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "types": ["jasmine", "node"] 8 | }, 9 | "files": ["test.ts", "polyfills.ts"], 10 | "include": ["**/*.spec.ts", "**/*.d.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /angular/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('matchbox-formfiller App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('Welcome to app!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /angular/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: '12' 3 | 4 | before_install: 5 | - npm install 6 | 7 | script: 8 | - npm run-script build 9 | 10 | cache: 11 | directories: 12 | - ./node_modules 13 | 14 | deploy: 15 | provider: pages 16 | skip_cleanup: true 17 | github_token: $GITHUB_TOKEN 18 | target_branch: 'gh-pages' 19 | local_dir: 'dist' 20 | on: 21 | branch: master 22 | -------------------------------------------------------------------------------- /docs/snippets/http_getxua.txt: -------------------------------------------------------------------------------- 1 | POST /assertion HTTP/1.1 2 | Scope: person_id=761337610445502987^^^&2.16.756.5.30.1.127.3.10.3&ISO purpose_of_use=urn:oid:2.16.756.5.30.1.127.3.10.5|NORM subject_role=urn:oid:2.16.756.5.30.1.127.3.10.6|HCP 3 | Content-Type: application/xml 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | [data-md-color-scheme="mag"] { 2 | --md-primary-fg-color: #7e995f; 3 | --md-primary-fg-color--light: #7e995f; 4 | --md-primary-fg-color--dark: #7e995f; 5 | } 6 | .tabbed-content { 7 | border: 1px solid var(--md-default-fg-color--lightest); 8 | border-top: 0; 9 | padding: 0 1rem; 10 | box-shadow: var(--md-shadow-z1); 11 | } 12 | .md-typeset svg { 13 | vertical-align: sub; 14 | } 15 | -------------------------------------------------------------------------------- /angular/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch(err => console.log(err)); 14 | -------------------------------------------------------------------------------- /angular/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false, 8 | }; 9 | -------------------------------------------------------------------------------- /src/main/resources/application-metrics.yml: -------------------------------------------------------------------------------- 1 | # Specific configuration for the metrics endpoint 2 | 3 | spring: 4 | config: 5 | activate: 6 | on-profile: metrics 7 | 8 | # https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.exposing 9 | management: 10 | endpoint: 11 | health: 12 | probes: 13 | enabled: true 14 | endpoints: 15 | web: 16 | exposure: 17 | include: ["metrics","prometheus"] 18 | -------------------------------------------------------------------------------- /angular/src/app/patient-detail/patient-detail.component.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { Component, OnInit, Input } from '@angular/core'; 4 | 5 | @Component({ 6 | selector: 'app-patient-detail', 7 | templateUrl: './patient-detail.component.html', 8 | styleUrls: ['./patient-detail.component.scss'], 9 | }) 10 | export class PatientDetailComponent implements OnInit { 11 | @Input() patient: fhir.r4.Patient; 12 | 13 | constructor() {} 14 | 15 | ngOnInit() {} 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/ch.bfh.ti.i4mi.mag.ppqm/TestConstants.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.ppqm; 2 | 3 | import org.openehealth.ipf.commons.ihe.fhir.chppqm.ChPpqmConsentCreator; 4 | 5 | /** 6 | * @author Dmytro Rud 7 | */ 8 | public class TestConstants { 9 | 10 | public static final String KNOWN_POLICY_SET_ID = ChPpqmConsentCreator.createUuid(); 11 | public static final String FAILURE_POLICY_SET_ID = ChPpqmConsentCreator.createUuid(); 12 | 13 | public static final String EPR_SPID = "123456789012345678"; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /angular/src/app/home/home.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 12 | 13 |

version: {{ version }} contact

14 |
15 |
16 | -------------------------------------------------------------------------------- /angular/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to matchbox-formfiller 2 | 3 | ## Publish a new version to github pages 4 | 5 | To publish a new version to github pages follow these steps: 6 | 7 | ``` 8 | git checkout master (can also be done via pull request) 9 | yarn version 10 | # enter the new version for example 0.3.1 11 | git push && git push --tags 12 | ``` 13 | 14 | This will update the `package.json` of matchbox-formfiller and commit a git tag with the new version. 15 | If a git tag on the master branch is pushed a build to publish the application to github pages is triggered. 16 | -------------------------------------------------------------------------------- /angular/src/app/capability-statement/capability-statement.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ client.baseUrl }} 5 | 6 |
7 | 8 | 9 |
    10 |
  • 11 | {{ issue.diagnostics }} 12 |
  • 13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /angular/src/app/home/home.component.scss: -------------------------------------------------------------------------------- 1 | @import '../../variables'; 2 | 3 | $primary: map-get($theme, primary); 4 | 5 | .mat-card.primary { 6 | mat-card-header { 7 | display: flex; 8 | flex-direction: column; 9 | 10 | .mat-subheading-2 { 11 | margin: 1rem 0 0 0; 12 | } 13 | } 14 | 15 | mat-card-content { 16 | ::ng-deep mat-tab-body > div { 17 | box-shadow: 0 0 5px -3px black inset; 18 | } 19 | } 20 | 21 | mat-card-footer { 22 | padding: 0 1.5rem 1.5rem 1.5rem; 23 | 24 | p { 25 | padding-top: 1rem; 26 | margin: 0; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /angular/src/app/settings/settings.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 11 | 12 | {{ mag }} 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/TlsParameterTest.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.net.ssl.SSLContext; 6 | 7 | import org.apache.camel.support.jsse.SSLContextParameters; 8 | import org.openehealth.ipf.commons.audit.TlsParameters; 9 | 10 | public class TlsParameterTest implements TlsParameters { 11 | 12 | private SSLContextParameters source; 13 | 14 | public TlsParameterTest(SSLContextParameters in) { 15 | source = in; 16 | } 17 | 18 | @Override 19 | public SSLContext getSSLContext(boolean dummy) { 20 | try { 21 | return source.createSSLContext(source.getCamelContext()); 22 | } catch (Exception e) {} 23 | return null; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | logs 3 | configurations 4 | secret 5 | 6 | # Compiled class file 7 | *.class 8 | 9 | # Log file 10 | *.log 11 | 12 | # BlueJ files 13 | *.ctxt 14 | 15 | # Mobile Tools for Java (J2ME) 16 | .mtj.tmp/ 17 | 18 | # Package Files # 19 | *.jar 20 | *.war 21 | *.nar 22 | *.ear 23 | *.zip 24 | *.tar.gz 25 | *.rar 26 | 27 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 28 | hs_err_pid* 29 | .classpath 30 | .factorypath 31 | .project 32 | .settings/org.eclipse.core.resources.prefs 33 | .settings/org.eclipse.jdt.apt.core.prefs 34 | .settings/org.eclipse.jdt.core.prefs 35 | .settings/org.eclipse.m2e.core.prefs 36 | 37 | .idea 38 | 39 | src/main/resources/Dev_Support.pfx 40 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "java", 9 | "name": "Debug Mobile Access Gateway local", 10 | "request": "launch", 11 | "mainClass": "ch.bfh.ti.i4mi.mag.MobileAccessGateway", 12 | "projectName": "mobile-access-gateway", 13 | "vmArgs": "-Dspring.config.additional-location=file:example-config/application.yml", 14 | "cwd": "${workspaceFolder}" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /angular/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceType": "Parameters", 3 | "parameter": [ 4 | { 5 | "name": "targetIdentifier", 6 | "valueIdentifier": { 7 | "system": "urn:oid:2.16.756.5.30.1.191.1.0.2.1", 8 | "value": "713d79be-058e-4f55-82a8-e1f81f5e0047" 9 | } 10 | }, 11 | { 12 | "name": "targetId", 13 | "valueReference": { 14 | "reference": "http://test.ahdis.ch/mag-pmp/fhir/Patient/2.16.756.5.30.1.191.1.0.2.1-713d79be-058e-4f55-82a8-e1f81f5e0047" 15 | } 16 | }, 17 | { 18 | "name": "targetIdentifier", 19 | "valueIdentifier": { 20 | "system": "urn:oid:2.16.756.5.30.1.127.3.10.3", 21 | "value": "761337610435209810" 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /angular/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "importHelpers": true, 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "target": "ES2022", 12 | "baseUrl": ".", 13 | "module": "commonjs", 14 | "esModuleInterop": true, 15 | "resolveJsonModule": true, 16 | "allowSyntheticDefaultImports": true, 17 | "paths": { 18 | "*": ["node_modules/*", "src/types/*"] 19 | }, 20 | "lib": ["es2017", "dom"], 21 | "useDefineForClassFields": false 22 | }, 23 | "angularCompilerOptions": { 24 | "enableIvy": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /angular/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /backend/data 8 | 9 | # dependencies 10 | /node_modules 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | .vscode/* 23 | !.vscode/settings.json 24 | !.vscode/tasks.json 25 | !.vscode/launch.json 26 | !.vscode/extensions.json 27 | 28 | # misc 29 | /.angular/cache 30 | /.sass-cache 31 | /connect.lock 32 | /coverage 33 | /libpeerconnection.log 34 | npm-debug.log 35 | testem.log 36 | /typings 37 | 38 | # e2e 39 | /e2e/*.js 40 | /e2e/*.map 41 | 42 | # System Files 43 | .DS_Store 44 | Thumbs.db 45 | -------------------------------------------------------------------------------- /.github/workflows/angular_test.yml: -------------------------------------------------------------------------------- 1 | name: Test the Angular GUI build 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | branches: 7 | - master 8 | 9 | jobs: 10 | build-and-commit: 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | working-directory: ./angular 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v3 18 | 19 | - name: Setup Node.js 20 | uses: actions/setup-node@v3 21 | with: 22 | # https://github.com/actions/setup-node 23 | node-version: 18 24 | cache: "npm" 25 | cache-dependency-path: angular/package-lock.json 26 | 27 | - name: Install dependencies 28 | run: npm install 29 | 30 | - name: Test the build 31 | run: npm run build 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bellsoft/liberica-openjdk-alpine:latest 2 | MAINTAINER oliver egger 3 | EXPOSE 9090 4 | EXPOSE 9091 5 | VOLUME /tmp 6 | 7 | ARG JAR_FILE=target/mobile-access-gateway-1.0.0-spring-boot.jar 8 | 9 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8' 10 | 11 | COPY ${JAR_FILE} /app.jar 12 | 13 | ENTRYPOINT java -Xmx1G -jar /app.jar -Djavax.net.ssl.trustStore=cacerts -Djavax.net.ssl.trustStorePassword=changeit -Dspring.config.additional-location=optional:file:/config/application.yml 14 | 15 | 16 | # export PROJECT_ID="$(gcloud config get-value project -q)" 17 | # docker build -t eu.gcr.io/${PROJECT_ID}/mag:v016 . 18 | # docker push eu.gcr.io/${PROJECT_ID}/mag:v016 19 | # docker run -d --name mag -p 9090:9090 --memory="5G" --cpus="1" eu.gcr.io/fhir-ch/mag:v016 20 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/iti66/Iti66Condition.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.mhd.iti66; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class Iti66Condition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | boolean iti18 = context.getEnvironment().getProperty("mag.xds.iti-18.url") != null; 12 | boolean allowIti66 = context.getEnvironment().getProperty("mag.mhd.iti66.disable") == null || Boolean.parseBoolean(context.getEnvironment().getProperty("mag.mhd.iti66.disable"))==false; 13 | return iti18 && allowIti66; 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti93/Iti93Condition.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.pmir.iti93; 2 | 3 | import org.springframework.context.annotation.Condition; 4 | import org.springframework.context.annotation.ConditionContext; 5 | import org.springframework.core.type.AnnotatedTypeMetadata; 6 | 7 | public class Iti93Condition implements Condition { 8 | 9 | @Override 10 | public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 11 | boolean pix = context.getEnvironment().getProperty("mag.pix.iti-44.url") != null; 12 | boolean allowIti93 = context.getEnvironment().getProperty("mag.pmir.iti93.disable") == null || Boolean.parseBoolean(context.getEnvironment().getProperty("mag.pmir.iti93.disable"))==false; 13 | return pix && allowIti93; 14 | } 15 | } -------------------------------------------------------------------------------- /docs/snippets/http_iti104.txt: -------------------------------------------------------------------------------- 1 | PUT /Patient?identifier=urn:oid:2.16.756.5.30.1.196.3.2.1|MAGMED001 HTTP/1.1 2 | Content-Type: application/fhir+json 3 | 4 | { 5 | "active": true, 6 | "birthDate": "1987-10-08", 7 | "gender": "male", 8 | "id": "2.16.756.5.30.1.127.3.10.3-761337611735842172", 9 | "identifier": [ 10 | { 11 | "system": "urn:oid:2.16.756.5.30.1.196.3.2.1", 12 | "value": "MAGMED001" 13 | }, 14 | { 15 | "system": "urn:oid:2.999.42", 16 | "value": "new-identifier-value" 17 | } 18 | ], 19 | "name": [ 20 | { 21 | "family": "NEFF-WINGEIER", 22 | "given": [ 23 | "Trong Sang" 24 | ] 25 | } 26 | ], 27 | "resourceType": "Patient" 28 | } 29 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Mobile Access Gateway 2 | repo_url: https://github.com/i4mi/MobileAccessGateway 3 | theme: 4 | name: material 5 | logo: assets/mag_logo.png 6 | favicon: assets/favicon-256x256.png 7 | palette: 8 | scheme: mag 9 | features: 10 | - content.code.annotate 11 | extra_css: 12 | - stylesheets/extra.css 13 | nav: 14 | - Home: index.md 15 | - Features: features.md 16 | - Endpoints: endpoints.md 17 | - EPR Integration: integration-primary-system.md 18 | - Container: docker.md 19 | - Changelog: changelog.md 20 | markdown_extensions: 21 | - admonition 22 | - attr_list 23 | - md_in_html 24 | - pymdownx.highlight 25 | - pymdownx.superfences 26 | - pymdownx.snippets: 27 | base_path: ["docs/snippets"] 28 | - pymdownx.tabbed: 29 | alternate_style: true 30 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org/apache/camel/component/mhd-pharm5: -------------------------------------------------------------------------------- 1 | # Copyright 2015 the original author or authors. Licensed under the Apache 2 | # License, Version 2.0 (the "License"); you may not use this file except 3 | # in compliance with the License. You may obtain a copy of the License at 4 | # http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 5 | # law or agreed to in writing, software distributed under the License is 6 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 7 | # KIND, either express or implied. See the License for the specific 8 | # language governing permissions and limitations under the License. 9 | 10 | # Camel registration for the pharm5.Pharm5Componen 11 | 12 | class=ch.bfh.ti.i4mi.mag.mhd.pharm5.Pharm5Component 13 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org/apache/camel/component/pmir-iti104: -------------------------------------------------------------------------------- 1 | # Copyright 2015 the original author or authors. Licensed under the Apache 2 | # License, Version 2.0 (the "License"); you may not use this file except 3 | # in compliance with the License. You may obtain a copy of the License at 4 | # http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 5 | # law or agreed to in writing, software distributed under the License is 6 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 7 | # KIND, either express or implied. See the License for the specific 8 | # language governing permissions and limitations under the License. 9 | 10 | # Camel registration for the pmir-iti104 component 11 | 12 | class=ch.bfh.ti.i4mi.mag.pmir.iti104.Iti104Component 13 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org/apache/camel/component/pmir-iti93: -------------------------------------------------------------------------------- 1 | # Copyright 2015 the original author or authors. Licensed under the Apache 2 | # License, Version 2.0 (the "License"); you may not use this file except 3 | # in compliance with the License. You may obtain a copy of the License at 4 | # http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 5 | # law or agreed to in writing, software distributed under the License is 6 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 7 | # KIND, either express or implied. See the License for the specific 8 | # language governing permissions and limitations under the License. 9 | 10 | # Camel registration for the pmir-iti93 component 11 | 12 | class=ch.bfh.ti.i4mi.mag.pmir.iti93.Iti93Component 13 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org/apache/camel/component/mhd-iti65-v401: -------------------------------------------------------------------------------- 1 | # Copyright 2015 the original author or authors. Licensed under the Apache 2 | # License, Version 2.0 (the "License"); you may not use this file except 3 | # in compliance with the License. You may obtain a copy of the License at 4 | # http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 5 | # law or agreed to in writing, software distributed under the License is 6 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 7 | # KIND, either express or implied. See the License for the specific 8 | # language governing permissions and limitations under the License. 9 | 10 | # Camel registration for the ITI-66 transaction 11 | 12 | class=org.openehealth.ipf.platform.camel.ihe.fhir.iti65_v401.Iti65Component -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org/apache/camel/component/mhd-iti66-v401: -------------------------------------------------------------------------------- 1 | # Copyright 2015 the original author or authors. Licensed under the Apache 2 | # License, Version 2.0 (the "License"); you may not use this file except 3 | # in compliance with the License. You may obtain a copy of the License at 4 | # http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 5 | # law or agreed to in writing, software distributed under the License is 6 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 7 | # KIND, either express or implied. See the License for the specific 8 | # language governing permissions and limitations under the License. 9 | 10 | # Camel registration for the ITI-66 transaction 11 | 12 | class=org.openehealth.ipf.platform.camel.ihe.fhir.iti66_v401.Iti66Component -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/org/apache/camel/component/mhd-iti67-v401: -------------------------------------------------------------------------------- 1 | # Copyright 2015 the original author or authors. Licensed under the Apache 2 | # License, Version 2.0 (the "License"); you may not use this file except 3 | # in compliance with the License. You may obtain a copy of the License at 4 | # http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 5 | # law or agreed to in writing, software distributed under the License is 6 | # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 7 | # KIND, either express or implied. See the License for the specific 8 | # language governing permissions and limitations under the License. 9 | 10 | # Camel registration for the ITI-67 transaction 11 | 12 | class=org.openehealth.ipf.platform.camel.ihe.fhir.iti67_v401.Iti67Component -------------------------------------------------------------------------------- /angular/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .example-fill-remaining-space { 2 | /* This fills the remaining space, by using flexbox. 3 | Every toolbar row uses a flexbox row layout. */ 4 | flex: 1 1 auto; 5 | } 6 | 7 | mat-toolbar { 8 | padding-left: 0; 9 | 10 | .home-link { 11 | height: 100%; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | cursor: pointer; 16 | } 17 | 18 | .logo-container { 19 | display: flex; 20 | height: 100%; 21 | width: 160px; 22 | justify-content: center; 23 | align-items: center; 24 | 25 | img { 26 | height: calc(100% - 1.2em); 27 | } 28 | } 29 | } 30 | 31 | main { 32 | width: 100%; 33 | margin: 0 auto; 34 | 35 | @media screen and (min-width: 1020px) { 36 | padding: 3rem 0; 37 | width: 1000px; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /angular/src/app/operation-outcome/operation-outcome.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { OperationOutcomeComponent } from './operation-outcome.component'; 4 | 5 | describe('OperationOutcomeComponent', () => { 6 | let component: OperationOutcomeComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [OperationOutcomeComponent], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(OperationOutcomeComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /angular/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mobile Access Gateway 6 | 7 | 8 | 9 | 13 | 17 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /angular/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: ['./e2e/**/*.e2e-spec.ts'], 9 | capabilities: { 10 | browserName: 'chrome', 11 | }, 12 | directConnect: true, 13 | baseUrl: 'http://localhost:4200/', 14 | framework: 'jasmine', 15 | jasmineNodeOpts: { 16 | showColors: true, 17 | defaultTimeoutInterval: 30000, 18 | print: function() {}, 19 | }, 20 | onPrepare() { 21 | require('ts-node').register({ 22 | project: 'e2e/tsconfig.e2e.json', 23 | }); 24 | jasmine 25 | .getEnv() 26 | .addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Mobile Access Gateway 2 | 3 | The [Mobile Access Gateway](https://www.mobileaccessgateway.ch/) is an implementation based on the [CH EPR mHealth](https://fhir.ch/ig/ch-epr-mhealth/index.html) 4 | implementation guide. It provides a FHIR Gateway supporting the mobile IHE server actors and translates them to the IHE XDS/HL7v3 transactions. 5 | 6 | It uses [IPF](https://oehf.github.io/ipf/) and [HAPI-FHIR](https://hapifhir.io/). 7 | 8 | You can read more [about the features](features.md), [the endpoints](endpoints.md) or [the changes](changelog.md). 9 | A more complete description of the [transactions needed for the EPR integration of primary systems](integration-primary-system.md) 10 | is also available. 11 | 12 | See also the [website](https://www.mobileaccessgateway.ch/) or [github repo](https://github.com/i4mi/MobileAccessGateway) for further information. 13 | -------------------------------------------------------------------------------- /angular/src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { MatLegacyTabChangeEvent } from '@angular/material/legacy-tabs'; 4 | import packageJson from '../../../package.json'; 5 | 6 | @Component({ 7 | selector: 'app-home', 8 | templateUrl: './home.component.html', 9 | styleUrls: ['./home.component.scss'], 10 | }) 11 | export class HomeComponent implements OnInit { 12 | public version: string = packageJson.version; 13 | 14 | constructor(private router: Router) {} 15 | 16 | update(index): void {} 17 | 18 | tabChanged(tabChangeEvent: MatLegacyTabChangeEvent): void { 19 | console.log('tabChangeEvent => ', tabChangeEvent); 20 | console.log('index => ', tabChangeEvent.index); 21 | this.update(tabChangeEvent.index); 22 | } 23 | 24 | async ngOnInit() { 25 | this.update(0); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | name: Publish documentation 2 | on: 3 | workflow_dispatch: # On manual trigger 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - "docs/**" 9 | - "mkdocs.yml" 10 | - "requirements.txt" 11 | 12 | jobs: 13 | build: 14 | name: Deploy docs 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout master 18 | uses: actions/checkout@v3 19 | 20 | - name: Install Python 3 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: "3.x" 24 | cache: "pip" 25 | cache-dependency-path: "requirements.txt" 26 | 27 | - name: Install mkdocs 28 | run: pip install -r requirements.txt 29 | 30 | - name: Build static documentation and deploy 31 | run: mkdocs gh-deploy --force 32 | # https://www.mkdocs.org/user-guide/deploying-your-docs/#github-pages 33 | -------------------------------------------------------------------------------- /angular/src/app/patient-detail/patient-detail.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { NO_ERRORS_SCHEMA } from '@angular/core'; 2 | import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; 3 | import { PatientDetailComponent } from './patient-detail.component'; 4 | 5 | describe('PatientDetailComponent', () => { 6 | let component: PatientDetailComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach( 10 | waitForAsync(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [PatientDetailComponent], 13 | schemas: [NO_ERRORS_SCHEMA], 14 | }).compileComponents(); 15 | }) 16 | ); 17 | 18 | beforeEach(() => { 19 | fixture = TestBed.createComponent(PatientDetailComponent); 20 | component = fixture.componentInstance; 21 | fixture.detectChanges(); 22 | }); 23 | 24 | it('should create', () => { 25 | expect(component).toBeTruthy(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /angular/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Chrome", 6 | "request": "launch", 7 | "type": "pwa-chrome", 8 | "url": "http://localhost:4200", 9 | "webRoot": "${workspaceFolder}" 10 | }, 11 | { 12 | "name": "ng serve", 13 | "type": "node", 14 | "request": "launch", 15 | "url": "http://localhost:4200/#", 16 | "webRoot": "${workspaceRoot}" 17 | }, 18 | { 19 | "name": "ng test", 20 | "type": "node", 21 | "request": "launch", 22 | "url": "http://localhost:9876/debug.html", 23 | "webRoot": "${workspaceRoot}" 24 | }, 25 | { 26 | "name": "ng e2e", 27 | "type": "node", 28 | "request": "launch", 29 | "program": "${workspaceRoot}/node_modules/protractor/bin/protractor", 30 | "protocol": "inspector", 31 | "args": ["${workspaceRoot}/protractor.conf.js"] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /angular/src/app/upload/upload.component.html: -------------------------------------------------------------------------------- 1 |
2 |
10 | cloud_upload 16 |
21 | Drop file here 22 |
23 |
or
24 | 32 |
33 |
34 | 35 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.xua; 18 | 19 | import lombok.Data; 20 | 21 | /** 22 | * OAuth2 error response (JSON) 23 | * @author alexander kreutz 24 | * 25 | */ 26 | @Data 27 | public class ErrorResponse { 28 | 29 | private String error; 30 | 31 | private String error_description; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/audit/TLSCloseSocket.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.audit; 2 | 3 | import org.openehealth.ipf.commons.audit.AuditContext; 4 | import org.openehealth.ipf.commons.audit.AuditMetadataProvider; 5 | import org.openehealth.ipf.commons.audit.TlsParameters; 6 | import org.openehealth.ipf.commons.audit.protocol.TLSSyslogSenderImpl; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class TLSCloseSocket extends TLSSyslogSenderImpl { 11 | 12 | private static final Logger log = LoggerFactory.getLogger(TLSCloseSocket.class); 13 | 14 | @Override 15 | public void send(AuditContext auditContext, AuditMetadataProvider auditMetadataProvider, String auditMessage) throws Exception { 16 | log.info("Auditing: "+auditMessage); 17 | super.send(auditContext, auditMetadataProvider, auditMessage); 18 | shutdown(); 19 | } 20 | 21 | public TLSCloseSocket(TlsParameters tlsParameters) { 22 | super(tlsParameters); 23 | // TODO Auto-generated constructor stub 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/BasePMIRResponseConverter.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.pmir; 2 | 3 | import org.hl7.fhir.r4.model.OperationOutcome; 4 | import org.hl7.fhir.r4.model.OperationOutcome.IssueType; 5 | import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent; 6 | 7 | import net.ihe.gazelle.hl7v3.datatypes.ED; 8 | 9 | public class BasePMIRResponseConverter { 10 | 11 | public OperationOutcome error(IssueType type, String diagnostics) { 12 | OperationOutcome result = new OperationOutcome(); 13 | 14 | OperationOutcomeIssueComponent issue = result.addIssue(); 15 | issue.setSeverity(OperationOutcome.IssueSeverity.ERROR); 16 | issue.setCode(type); 17 | issue.setDiagnostics(diagnostics); 18 | return result; 19 | } 20 | 21 | public String toText(ED in) { 22 | StringBuffer result = new StringBuffer(); 23 | for (java.io.Serializable obj : in.getMixed()) { 24 | if (obj instanceof String) { 25 | result.append((String) obj); 26 | } 27 | } 28 | return result.toString(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /angular/default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | root /usr/share/nginx/html; 4 | client_max_body_size 100m; 5 | 6 | location = / { 7 | return 301 ${DOMAIN}/matchbox-formfiller; 8 | } 9 | 10 | location /matchbox-formfiller { 11 | alias /usr/share/nginx/html; 12 | try_files $uri /index.html; 13 | } 14 | 15 | location /matchbox { 16 | proxy_set_header X-Real-IP $remote_addr; 17 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 18 | proxy_set_header X-NginX-Proxy true; 19 | proxy_pass ${MATCHBOX}; 20 | proxy_ssl_session_reuse off; 21 | proxy_set_header Host $http_host; 22 | proxy_cache_bypass $http_upgrade; 23 | proxy_redirect off; 24 | } 25 | 26 | location /mag-pmp { 27 | proxy_set_header X-Real-IP $remote_addr; 28 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 29 | proxy_set_header X-NginX-Proxy true; 30 | proxy_pass ${MAG}; 31 | proxy_ssl_session_reuse off; 32 | proxy_set_header Host $http_host; 33 | proxy_cache_bypass $http_upgrade; 34 | proxy_redirect off; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /angular/src/app/operation-outcome/operation-outcome.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} 5 | 6 |
7 |
8 | {{ getLineFromExtension(issue) }}: {{ getLocation(issue) }}:
11 | 12 | {{ issue.diagnostics }} 13 | 14 | 15 |
    16 |
  1. 17 | {{ sliceInfo }} 18 |
  2. 19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | 12 | /** 13 | * Implementation of Swiss transactions for Camel. 14 | * 15 | * @author Quentin Ligier 16 | **/ 17 | @DefaultQualifier(value = NonNull.class, locations = {TypeUseLocation.PARAMETER, TypeUseLocation.RETURN, 18 | TypeUseLocation.FIELD}) 19 | package org.husky.communication.ch.camel; 20 | 21 | import org.checkerframework.checker.nullness.qual.NonNull; 22 | import org.checkerframework.framework.qual.DefaultQualifier; 23 | import org.checkerframework.framework.qual.TypeUseLocation; -------------------------------------------------------------------------------- /angular/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting, 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | 18 | // Prevent Karma from running prematurely. 19 | __karma__.loaded = function () {}; 20 | 21 | // First, initialize the Angular testing environment. 22 | getTestBed().initTestEnvironment( 23 | BrowserDynamicTestingModule, 24 | platformBrowserDynamicTesting(), 25 | { 26 | teardown: { destroyAfterEach: false }, 27 | } 28 | ); 29 | // Finally, start Karma to run the tests. 30 | __karma__.start(); 31 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/MySAMLBootstrap.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.xua; 2 | 3 | import org.opensaml.Configuration; 4 | import org.opensaml.xml.security.BasicSecurityConfiguration; 5 | import org.opensaml.xml.signature.SignatureConstants; 6 | import org.springframework.beans.BeansException; 7 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 8 | import org.springframework.security.saml.SAMLBootstrap; 9 | 10 | public class MySAMLBootstrap extends SAMLBootstrap { 11 | 12 | @Override 13 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 14 | super.postProcessBeanFactory(beanFactory); 15 | BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration(); 16 | config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); 17 | config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256); 18 | //config.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/ppqm/PpqmConfiguration.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.ppqm; 2 | 3 | import ch.bfh.ti.i4mi.mag.Config; 4 | import org.openehealth.ipf.commons.ihe.fhir.chppqm.translation.FhirToXacmlTranslator; 5 | import org.openehealth.ipf.commons.ihe.xacml20.ChPpqMessageCreator; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | /** 10 | * @author Dmytro Rud 11 | */ 12 | @Configuration 13 | public class PpqmConfiguration { 14 | 15 | @Bean 16 | public ChPpqMessageCreator ppqMessageCreator(Config config) { 17 | String homeCommunityId = config.getHomeCommunity(); 18 | if (!homeCommunityId.startsWith("urn:oid:")) { 19 | homeCommunityId = "urn:oid:" + homeCommunityId; 20 | } 21 | return new ChPpqMessageCreator(homeCommunityId); 22 | } 23 | 24 | @Bean 25 | public FhirToXacmlTranslator fhirToXacmlTranslator(ChPpqMessageCreator ppqMessageCreator) { 26 | return new FhirToXacmlTranslator(ppqMessageCreator); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/requests/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | @XmlSchema( 12 | namespace = "http://www.openehealth.org/ipf/xds", 13 | elementFormDefault = XmlNsForm.QUALIFIED, 14 | attributeFormDefault = XmlNsForm.UNQUALIFIED, 15 | xmlns = { 16 | @XmlNs(prefix = "xds", namespaceURI = "http://www.openehealth.org/ipf/xds")}) 17 | package org.husky.communication.ch.camel.chpharm1.requests; 18 | 19 | import javax.xml.bind.annotation.XmlNs; 20 | import javax.xml.bind.annotation.XmlNsForm; 21 | import javax.xml.bind.annotation.XmlSchema; 22 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/requests/query/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | @XmlSchema( 12 | namespace = "http://www.openehealth.org/ipf/xds", 13 | elementFormDefault = XmlNsForm.UNQUALIFIED, 14 | attributeFormDefault = XmlNsForm.UNQUALIFIED, 15 | xmlns = { 16 | @XmlNs(prefix = "xds", namespaceURI = "http://www.openehealth.org/ipf/xds")}) 17 | package org.husky.communication.ch.camel.chpharm1.requests.query; 18 | 19 | import javax.xml.bind.annotation.XmlNs; 20 | import javax.xml.bind.annotation.XmlNsForm; 21 | import javax.xml.bind.annotation.XmlSchema; 22 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti93/Iti93Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.pmir.iti93; 18 | 19 | import java.util.Arrays; 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | 23 | /** 24 | * @author Oliver Egger 25 | */ 26 | public interface Iti93Constants { 27 | 28 | Set ITI93_PARAMETERS = new HashSet<>(Arrays.asList( 29 | "content", 30 | "async", 31 | "url")); 32 | 33 | String PMIR_OPERATION_NAME = "$process-message"; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/transform/requests/query/ChFindDispensesQueryTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | package org.husky.communication.ch.camel.chpharm1.transform.requests.query; 12 | 13 | import org.husky.communication.ch.camel.chpharm1.requests.query.ChFindDispensesQuery; 14 | import org.openehealth.ipf.commons.ihe.xds.core.ebxml.EbXMLAdhocQueryRequest; 15 | 16 | /** 17 | * Transforms between {@link ChFindDispensesQuery} and {@link EbXMLAdhocQueryRequest}. 18 | * 19 | * @author Quentin Ligier 20 | **/ 21 | public class ChFindDispensesQueryTransformer extends ChPharmacyStableDocumentsQueryTransformer { 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/OAuth2TokenResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package ch.bfh.ti.i4mi.mag.xua; 19 | 20 | import lombok.Data; 21 | 22 | /** 23 | * Data used as response for OAuth2 token exchange 24 | * @author alexander kreutz 25 | * 26 | */ 27 | @Data 28 | public class OAuth2TokenResponse { 29 | 30 | private String access_token; 31 | 32 | private String refresh_token; 33 | 34 | private String token_type; 35 | 36 | private long expires_in; 37 | 38 | private String scope; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/transform/requests/query/ChFindPrescriptionsQueryTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | package org.husky.communication.ch.camel.chpharm1.transform.requests.query; 12 | 13 | import org.husky.communication.ch.camel.chpharm1.requests.query.ChFindPrescriptionsQuery; 14 | import org.openehealth.ipf.commons.ihe.xds.core.ebxml.EbXMLAdhocQueryRequest; 15 | 16 | /** 17 | * Transforms between {@link ChFindPrescriptionsQuery} and {@link EbXMLAdhocQueryRequest}. 18 | * 19 | * @author Quentin Ligier 20 | **/ 21 | public class ChFindPrescriptionsQueryTransformer extends ChPharmacyStableDocumentsQueryTransformer { 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/static/runtime.b36ad241e7dd5c21.js: -------------------------------------------------------------------------------- 1 | (()=>{"use strict";var e,s={},v={};function a(e){var o=v[e];if(void 0!==o)return o.exports;var r=v[e]={exports:{}};return s[e].call(r.exports,r,r.exports,a),r.exports}a.m=s,e=[],a.O=(o,r,t,n)=>{if(!r){var c=1/0;for(l=0;l=n)&&Object.keys(a.O).every(p=>a.O[p](r[f]))?r.splice(f--,1):(i=!1,n0&&e[l-1][2]>n;l--)e[l]=e[l-1];e[l]=[r,t,n]},a.d=(e,o)=>{for(var r in o)a.o(o,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},a.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),a.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e={666:0};a.O.j=t=>0===e[t];var o=(t,n)=>{var f,u,[l,c,i]=n,b=0;if(l.some(_=>0!==e[_])){for(f in c)a.o(c,f)&&(a.m[f]=c[f]);if(i)var d=i(a)}for(t&&t(n);b { 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/transform/requests/query/ChFindPrescriptionsForDispenseQueryTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | package org.husky.communication.ch.camel.chpharm1.transform.requests.query; 12 | 13 | import org.husky.communication.ch.camel.chpharm1.requests.query.ChFindPrescriptionsForDispenseQuery; 14 | import org.openehealth.ipf.commons.ihe.xds.core.ebxml.EbXMLAdhocQueryRequest; 15 | 16 | /** 17 | * Transforms between {@link ChFindPrescriptionsForDispenseQuery} and {@link EbXMLAdhocQueryRequest}. 18 | * 19 | * @author Quentin Ligier 20 | **/ 21 | public class ChFindPrescriptionsForDispenseQueryTransformer extends ChPharmacyStableDocumentsQueryTransformer { 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/transform/requests/query/ChFindMedicationAdministrationsQueryTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | package org.husky.communication.ch.camel.chpharm1.transform.requests.query; 12 | 13 | import org.husky.communication.ch.camel.chpharm1.requests.query.ChFindMedicationAdministrationsQuery; 14 | import org.openehealth.ipf.commons.ihe.xds.core.ebxml.EbXMLAdhocQueryRequest; 15 | 16 | /** 17 | * Transforms between {@link ChFindMedicationAdministrationsQuery} and {@link EbXMLAdhocQueryRequest}. 18 | * 19 | * @author Quentin Ligier 20 | **/ 21 | public class ChFindMedicationAdministrationsQueryTransformer extends ChPharmacyStableDocumentsQueryTransformer { 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/transform/requests/query/ChFindPrescriptionsForValidationQueryTransformer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | package org.husky.communication.ch.camel.chpharm1.transform.requests.query; 12 | 13 | import org.husky.communication.ch.camel.chpharm1.requests.query.ChFindPrescriptionsForValidationQuery; 14 | import org.openehealth.ipf.commons.ihe.xds.core.ebxml.EbXMLAdhocQueryRequest; 15 | 16 | /** 17 | * Transforms between {@link ChFindPrescriptionsForValidationQuery} and {@link EbXMLAdhocQueryRequest}. 18 | * 19 | * @author Quentin Ligier 20 | **/ 21 | public class ChFindPrescriptionsForValidationQueryTransformer extends ChPharmacyStableDocumentsQueryTransformer { 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/angular_build.yml: -------------------------------------------------------------------------------- 1 | name: Build the Angular GUI and commit 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | paths: 9 | - "angular/**" 10 | 11 | jobs: 12 | build-and-commit: 13 | runs-on: ubuntu-latest 14 | permissions: 15 | # Give the default GITHUB_TOKEN write permission to commit and push the 16 | # added or changed files to the repository. 17 | contents: write 18 | defaults: 19 | run: 20 | working-directory: ./angular 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v3 24 | 25 | - name: Setup Node.js 26 | uses: actions/setup-node@v3 27 | with: 28 | # https://github.com/actions/setup-node 29 | node-version: 18 30 | cache: "npm" 31 | cache-dependency-path: angular/package-lock.json 32 | 33 | - name: Install dependencies 34 | run: npm install 35 | 36 | - name: Build 37 | run: npm run build-mag 38 | 39 | - name: Commit 40 | if: success() 41 | uses: stefanzweifel/git-auto-commit-action@v4 42 | with: 43 | commit_message: "Rebuild the Angular GUI resources" 44 | file_pattern: "src/main/resources/static" 45 | -------------------------------------------------------------------------------- /angular/src/app/capability-statement/capability-statement.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FhirConfigService } from '../fhirConfig.service'; 3 | import FhirClient from 'fhir-kit-client'; 4 | 5 | @Component({ 6 | selector: 'app-capability-statement', 7 | templateUrl: './capability-statement.component.html', 8 | styleUrls: ['./capability-statement.component.scss'], 9 | }) 10 | export class CapabilityStatementComponent implements OnInit { 11 | capabilitystatement: fhir.r4.CapabilityStatement; 12 | operationOutcome: fhir.r4.OperationOutcome; 13 | client: FhirClient; 14 | 15 | constructor(private data: FhirConfigService) { 16 | this.client = data.getMobileAccessGatewayClient(); 17 | this.client 18 | .capabilityStatement() 19 | .then((data: fhir.r4.CapabilityStatement) => { 20 | this.operationOutcome = undefined; 21 | this.capabilitystatement = data; 22 | }) 23 | .catch((error) => { 24 | this.capabilitystatement = undefined; 25 | this.operationOutcome = error.response.data; 26 | }); 27 | } 28 | 29 | getJson(): string { 30 | return JSON.stringify(this.capabilitystatement, null, 2); 31 | } 32 | 33 | ngOnInit() {} 34 | 35 | ngOnDestroy() {} 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/XuaUtils.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.xua; 2 | 3 | import org.apache.camel.Body; 4 | import org.apache.cxf.staxutils.StaxUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.w3c.dom.Node; 8 | import org.w3c.dom.NodeList; 9 | 10 | import javax.xml.soap.SOAPBody; 11 | import javax.xml.soap.SOAPException; 12 | import javax.xml.soap.SOAPMessage; 13 | 14 | import static org.opensaml.common.xml.SAMLConstants.SAML20_NS; 15 | 16 | /** 17 | * MobileAccessGateway 18 | * 19 | * @author Quentin Ligier 20 | **/ 21 | public class XuaUtils { 22 | private static final Logger log = LoggerFactory.getLogger(XuaUtils.class); 23 | 24 | public static final String OASIS_WSSECURITY_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 25 | 26 | public String extractAssertionAsString(final @Body SOAPMessage in) throws SOAPException { 27 | log.debug("INPUT: {}", in); 28 | SOAPBody body = in.getSOAPBody(); 29 | NodeList lst = body.getElementsByTagNameNS(SAML20_NS, "Assertion"); 30 | Node node = lst.item(0); 31 | log.debug("NODE: {}", node); 32 | // TODO: omit xml declaration? 33 | return StaxUtils.toString(node); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | */ 10 | 11 | /** 12 | * This is the definition of the CH:PHARM-1 transaction, an extension of IHE PHARM-1. 13 | * 14 | *

The Camel components are not redefined, those from the PHARM-1 transaction shall be used. The response models are 15 | * not redefined either, only the query models. 16 | * 17 | * @see org.openehealth.ipf.commons.ihe.xds.pharm1.Pharm1PortType 18 | * @see org.openehealth.ipf.platform.camel.ihe.xds.pharm1.Pharm1Service 19 | * @see org.openehealth.ipf.platform.camel.ihe.xds.pharm1.Pharm1Component 20 | * @see org.openehealth.ipf.commons.ihe.xds.core.responses.QueryResponse 21 | * 22 | * @author Quentin Ligier 23 | **/ 24 | package org.husky.communication.ch.camel.chpharm1; -------------------------------------------------------------------------------- /angular/src/app/operation-outcome/operation-outcome.component.scss: -------------------------------------------------------------------------------- 1 | .card-maps { 2 | margin-bottom: 10px; 3 | } 4 | 5 | .app-ace-editor { 6 | border: 2px solid #f8f9fa; 7 | box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); 8 | } 9 | 10 | .issue { 11 | border: 2px solid #f8f9fa; 12 | padding: 2px; 13 | } 14 | 15 | .fatal { 16 | background: #cc3300; /* color */ 17 | } 18 | 19 | .error { 20 | background: #ff9966; /* color */ 21 | } 22 | 23 | .warning { 24 | background: #ffe69e; /* color */ 25 | } 26 | 27 | .information { 28 | background: #cde8a5; /* color */ 29 | } 30 | 31 | ::ng-deep .ace-highlight-fatal { 32 | position: absolute; /* without this positions will be erong */ 33 | background: #cc3300; /* color */ 34 | opacity: 0.4; 35 | } 36 | 37 | ::ng-deep .ace-highlight-error { 38 | position: absolute; /* without this positions will be erong */ 39 | background: #ff9966; /* color */ 40 | opacity: 0.4; 41 | } 42 | 43 | ::ng-deep .ace-highlight-warning { 44 | position: absolute; /* without this positions will be erong */ 45 | background: #ffcc00; /* color */ 46 | opacity: 0.4; 47 | } 48 | 49 | ::ng-deep .ace-highlight-information { 50 | position: absolute; /* without this positions will be erong */ 51 | background: #99cc33; /* color */ 52 | opacity: 0.4; 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/AuthenticationRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package ch.bfh.ti.i4mi.mag.xua; 19 | 20 | import lombok.Data; 21 | 22 | /** 23 | * Data required during OAuth2 authentication 24 | * @author alexander kreutz 25 | * 26 | */ 27 | @Data 28 | public class AuthenticationRequest { 29 | 30 | private String scope; 31 | 32 | private String redirect_uri; 33 | 34 | private String client_id; 35 | 36 | private String state; 37 | 38 | private String token_type; 39 | 40 | private String assertion; 41 | 42 | private String idpAssertion; 43 | 44 | private String code_challenge; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /angular/src/app/fhirpath.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { evaluate } from 'fhirpath'; 3 | 4 | @Injectable({ 5 | providedIn: 'root', 6 | }) 7 | export class FhirPathService { 8 | public evaluate(fhir: any, fhirPath: string): any { 9 | return evaluate(fhir, fhirPath, null); 10 | } 11 | 12 | public evaluateToString(fhir: any, fhirPath: string): string { 13 | const result = this.evaluate(fhir, fhirPath); 14 | if ( 15 | result && 16 | result instanceof Array && 17 | (result as Array).length === 1 18 | ) { 19 | return (result as Array)[0]; 20 | } 21 | return null; 22 | } 23 | 24 | getOauthUriToken(capabilityStatement: any): string { 25 | return this.evaluateToString( 26 | capabilityStatement, 27 | "rest.security.extension.where(url='http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris').extension.where(url='token').valueUri" 28 | ); 29 | } 30 | 31 | getOauthUriAuthorize(capabilityStatement: any): string { 32 | return this.evaluateToString( 33 | capabilityStatement, 34 | "rest.security.extension.where(url='http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris').extension.where(url='authorize').valueUri" 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /angular/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma'), 14 | ], 15 | client: { 16 | clearContext: false, // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, 'coverage'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true, 22 | }, 23 | 24 | reporters: ['progress', 'kjhtml'], 25 | port: 9876, 26 | colors: true, 27 | logLevel: config.LOG_INFO, 28 | autoWatch: true, 29 | browsers: ['Chrome'], 30 | customLaunchers: { 31 | ChromeHeadlessNoSandbox: { 32 | base: 'ChromeHeadless', 33 | flags: ['--no-sandbox'], 34 | }, 35 | }, 36 | singleRun: false, 37 | webpack: { node: { fs: 'empty' } }, 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/FilterConfig.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag; 2 | 3 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import io.micrometer.tracing.Tracer; 7 | 8 | @Configuration 9 | public class FilterConfig { 10 | 11 | private final Tracer tracer; 12 | 13 | public FilterConfig(Tracer tracer) { 14 | this.tracer = tracer; 15 | } 16 | 17 | @Bean 18 | public FilterRegistrationBean loggingFilter() { 19 | FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); 20 | registrationBean.setFilter(new TraceHeaderLoggingFilter(tracer)); 21 | registrationBean.addUrlPatterns("/*"); 22 | registrationBean.setOrder(1); 23 | return registrationBean; 24 | } 25 | 26 | @Bean 27 | public FilterRegistrationBean requestIdFilter() { 28 | FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); 29 | registrationBean.setFilter(new RequestIdFilter()); 30 | registrationBean.addUrlPatterns("/*"); 31 | registrationBean.setOrder(2); 32 | return registrationBean; 33 | } 34 | } -------------------------------------------------------------------------------- /src/test/java/ch/bfh/ti/i4mi/mag/mhd/iti65/Iti65RequestConverterTest.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.mhd.iti65; 2 | 3 | import org.hl7.fhir.r4.model.Organization; 4 | import org.junit.jupiter.api.Test; 5 | import org.openehealth.ipf.commons.ihe.xds.core.metadata.Hl7v2Based; 6 | 7 | import static org.junit.jupiter.api.Assertions.*; 8 | 9 | /** 10 | * Tests for {@link Iti65RequestConverter}. 11 | * 12 | * @author Quentin Ligier 13 | **/ 14 | class Iti65RequestConverterTest { 15 | 16 | @Test 17 | void testTransformOrganization() { 18 | final var iti65RequestConverter = new Iti65RequestConverter(); 19 | 20 | final var org = new Organization(); 21 | org.setName("Test"); 22 | org.addIdentifier().setValue("1234"); 23 | 24 | var xon = iti65RequestConverter.transform(org); 25 | assertEquals("Test^^^^^^^^^1234", Hl7v2Based.render(xon)); 26 | 27 | org.getIdentifierFirstRep().setSystem("urn:oid:1.2.3"); 28 | xon = iti65RequestConverter.transform(org); 29 | assertEquals("Test^^^^^&1.2.3&ISO^^^^1234", Hl7v2Based.render(xon)); 30 | 31 | org.getIdentifierFirstRep().setValue("urn:oid:1.2.3").setSystem("urn:ietf:rfc:3986"); 32 | xon = iti65RequestConverter.transform(org); 33 | assertEquals("Test^^^^^^^^^1.2.3", Hl7v2Based.render(xon)); 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/IDPConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.xua; 18 | 19 | import lombok.Data; 20 | 21 | /** 22 | * Configuration data for one IDP 23 | * 24 | * @author alexander kreutz 25 | */ 26 | @Data 27 | public class IDPConfig { 28 | 29 | private String name; 30 | 31 | private String metadataUrl; 32 | 33 | private String renewUrl; 34 | 35 | private String keyAlias; 36 | 37 | private String tlsKeyAlias; 38 | 39 | private String signKeyAlias; 40 | 41 | private String keyPassword; 42 | 43 | private String tlsKeyPassword; 44 | 45 | private String signKeyPassword; 46 | 47 | private boolean noArtifactResolution; 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti67_v401/Iti67ClientRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.commons.ihe.fhir.iti67_v401; 18 | 19 | import org.hl7.fhir.r4.model.Bundle; 20 | import org.hl7.fhir.r4.model.DocumentReference; 21 | import org.openehealth.ipf.commons.ihe.fhir.QueryClientRequestFactory; 22 | 23 | /** 24 | * Request Factory for ITI-67 requests returning a bundle of document references 25 | * 26 | * @author Christian Ohr 27 | * @since 3.6 28 | */ 29 | public class Iti67ClientRequestFactory extends QueryClientRequestFactory { 30 | 31 | public Iti67ClientRequestFactory() { 32 | super(DocumentReference.class, Bundle.class); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /angular/src/app/upload/upload.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | .attachment-field { 7 | $radius: 5px; 8 | border-radius: $radius; 9 | background: #e6e7e1; 10 | 11 | .attachment-entry { 12 | border-bottom: 1px solid #dedede; 13 | display: flex; 14 | align-items: center; 15 | height: 40px; 16 | 17 | .attachment-name { 18 | flex: 1; 19 | padding: 0 1rem; 20 | white-space: nowrap; 21 | overflow: hidden; 22 | text-overflow: ellipsis; 23 | } 24 | 25 | .attachment-size:last-child { 26 | margin-right: 1rem; 27 | } 28 | 29 | .mat-icon-button { 30 | display: flex; 31 | align-items: center; 32 | justify-content: center; 33 | line-height: inherit; 34 | } 35 | } 36 | 37 | .drop-zone { 38 | text-align: center; 39 | padding: 2rem; 40 | border-bottom-left-radius: $radius; 41 | border-bottom-right-radius: $radius; 42 | 43 | &:first-child { 44 | border-top-left-radius: $radius; 45 | border-top-right-radius: $radius; 46 | } 47 | 48 | &.file-over { 49 | background: darken(#e6e7e1, 5%); 50 | outline: solid #32a1ce; 51 | } 52 | 53 | .spacer { 54 | line-height: 3rem; 55 | } 56 | 57 | .bold-text { 58 | font-weight: bold; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /angular/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FhirConfigService } from './fhirConfig.service'; 3 | import { TranslateService } from '@ngx-translate/core'; 4 | import { Router } from '@angular/router'; 5 | 6 | @Component({ 7 | selector: 'app-root', 8 | templateUrl: './app.component.html', 9 | styleUrls: ['./app.component.scss'], 10 | }) 11 | export class AppComponent { 12 | constructor( 13 | translateService: TranslateService, 14 | fhirConfigService: FhirConfigService, 15 | router: Router, 16 | ) { 17 | translateService.setDefaultLang('de'); 18 | translateService.use(translateService.getBrowserLang()); 19 | 20 | // When the user loads the front page and there is an OAuth token in the URL, redirect to the Mag page 21 | const urlParams = new URLSearchParams(window.location.search); 22 | if (urlParams.has('code') && urlParams.has('state')) { 23 | router.navigate(['/mag'], { 24 | queryParams: { 25 | code: urlParams.get('code'), 26 | state: urlParams.get('state'), 27 | }, 28 | }); 29 | } 30 | 31 | let base = location.origin + location.pathname; 32 | if (base.endsWith('/')) { 33 | base += 'fhir'; 34 | } else { 35 | base += '/fhir'; 36 | } 37 | console.log('note: using fhir base ' + base); 38 | fhirConfigService.changeMagMicroService(base); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti66_v401/Iti66ClientRequestFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.commons.ihe.fhir.iti66_v401; 18 | 19 | import org.hl7.fhir.r4.model.Bundle; 20 | import org.hl7.fhir.r4.model.DocumentManifest; 21 | import org.hl7.fhir.r4.model.ListResource; 22 | import org.openehealth.ipf.commons.ihe.fhir.QueryClientRequestFactory; 23 | 24 | /** 25 | * Request Factory for ITI-66 requests returning a bundle of list resources 26 | * 27 | * @author Alexander Kreutz, Christian Ohr 28 | * @since 3.6 29 | */ 30 | public class Iti66ClientRequestFactory extends QueryClientRequestFactory { 31 | 32 | public Iti66ClientRequestFactory() { 33 | super(ListResource.class, Bundle.class); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /angular/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { HttpClientTestingModule } from '@angular/common/http/testing'; 2 | import { NO_ERRORS_SCHEMA } from '@angular/core'; 3 | import { TestBed, waitForAsync } from '@angular/core/testing'; 4 | import { RouterModule, Routes } from '@angular/router'; 5 | import { AppComponent } from './app.component'; 6 | import { MatLegacyMenuModule as MatMenuModule } from '@angular/material/legacy-menu'; 7 | import { TranslateModule } from '@ngx-translate/core'; 8 | 9 | export const FHIR_JS_CONFIG: FhirConfig = { 10 | baseUrl: 'http://localhost:8080/r4', 11 | credentials: 'same-origin', 12 | }; 13 | 14 | const routes: Routes = []; 15 | 16 | describe('AppComponent', () => { 17 | beforeEach( 18 | waitForAsync(() => { 19 | TestBed.configureTestingModule({ 20 | declarations: [AppComponent], 21 | imports: [ 22 | MatMenuModule, 23 | TranslateModule.forRoot(), 24 | HttpClientTestingModule, 25 | RouterModule.forRoot(routes, { 26 | useHash: true, 27 | }), 28 | ], 29 | schemas: [NO_ERRORS_SCHEMA], 30 | }).compileComponents(); 31 | }) 32 | ); 33 | it( 34 | 'should create the app', 35 | waitForAsync(() => { 36 | const fixture = TestBed.createComponent(AppComponent); 37 | const app = fixture.debugElement.componentInstance; 38 | expect(app).toBeTruthy(); 39 | }) 40 | ); 41 | }); 42 | -------------------------------------------------------------------------------- /angular/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |

7 | 8 | 9 | 10 | 13 | 14 | 18 | 22 | 26 | 30 | 34 | 35 | 36 | 37 |
38 | 39 |
40 | -------------------------------------------------------------------------------- /docs/endpoints.md: -------------------------------------------------------------------------------- 1 | Here are the endpoints exposed by the Mobile Access Gateway. 2 | 3 | | Transaction | URL | 4 | |----------------------|-------------------------------------------------------| 5 | | ITI-65 | _instance_/fhir/ | 6 | | ITI-66 | _instance_/fhir/List | 7 | | ITI-67 | _instance_/fhir/DocumentReference | 8 | | ITI-68 | _instance_/camel/xdsretrieve | 9 | | ITI-71 | _instance_/camel/authorize | 10 | | ITI-71 | _instance_/camel/token | 11 | | ITI-78 | _instance_/fhir/Patient | 12 | | ITI-83 | _instance_/fhir/Patient/$ihe-pix | 13 | | ITI-93 | | 14 | | ITI-104 | _instance_/fhir/Patient | 15 | | CH:PHARM-5 | _instance_/fhir/DocumentReference/$_{operation-name}_ | 16 | | Get X-User Assertion | _instance_/camel/assertion | 17 | | CH:PPQ3 | _instance_/fhir | 18 | | CH:PPQ4 | _instance_/fhir | 19 | | CH:PPQ5 | _instance_/fhir | 20 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/pharm5/Pharm5Endpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.mhd.pharm5; 18 | 19 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 20 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpoint; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 22 | 23 | /** 24 | * @author Oliver Egger 25 | */ 26 | public class Pharm5Endpoint extends FhirEndpoint { 27 | 28 | public Pharm5Endpoint(String uri, Pharm5Component fhirComponent, FhirEndpointConfiguration config) { 29 | super(uri, fhirComponent, config); 30 | } 31 | 32 | @Override 33 | protected String createEndpointUri() { 34 | return "mhd-pharm5:" + "not-implemented yet"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/LoginAtnaLogger.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.xua; 2 | 3 | import org.apache.camel.Body; 4 | import org.apache.camel.Header; 5 | import org.openehealth.ipf.commons.audit.AuditContext; 6 | import org.openehealth.ipf.commons.audit.codes.EventOutcomeIndicator; 7 | import org.openehealth.ipf.commons.audit.event.UserAuthenticationBuilder; 8 | import org.openehealth.ipf.commons.audit.types.PurposeOfUse; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | 11 | public class LoginAtnaLogger { 12 | 13 | @Autowired 14 | private AuditContext myAuditContext; 15 | 16 | public void loginSuccess(@Header("oauthrequest") AuthenticationRequest request) { 17 | EventOutcomeIndicator outcome = EventOutcomeIndicator.Success; 18 | atnaLog(outcome, null, PurposeOfUse.of("NORM", "2.16.756.5.30.1.127.3.10.5", "Normal Access")); 19 | } 20 | 21 | public void loginFail(@Header("oauthrequest") AuthenticationRequest request, @Body Exception fault) { 22 | EventOutcomeIndicator outcome = EventOutcomeIndicator.MinorFailure; 23 | atnaLog(outcome, fault.toString(), PurposeOfUse.of("NORM", "2.16.756.5.30.1.127.3.10.5", "Normal Access")); 24 | } 25 | 26 | public void atnaLog(EventOutcomeIndicator outcome, String description, PurposeOfUse purposeOfUse) { 27 | 28 | myAuditContext.audit( 29 | new UserAuthenticationBuilder.Login(outcome, description, purposeOfUse) 30 | .setAuditSource(myAuditContext) 31 | 32 | .getMessage() 33 | ); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/husky/communication/ch/camel/chpharm1/ChPharm1Service.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This code is made available under the terms of the Eclipse Public License v1.0 3 | * in the github project https://github.com/project-husky/husky there you also 4 | * find a list of the contributors and the license information. 5 | * 6 | * This project has been developed further and modified by the joined working group Husky 7 | * on the basis of the eHealth Connector opensource project from June 28, 2021, 8 | * whereas medshare GmbH is the initial and main contributor/author of the eHealth Connector. 9 | * 10 | */ 11 | package org.husky.communication.ch.camel.chpharm1; 12 | 13 | import org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.query.AdhocQueryRequest; 14 | import org.openehealth.ipf.commons.ihe.xds.core.stub.ebrs30.query.AdhocQueryResponse; 15 | import org.openehealth.ipf.platform.camel.ihe.xds.XdsAdhocQueryService; 16 | 17 | /** 18 | * Service implementation for the CH:PHARM-1 transaction (Query Pharmacy Documents). 19 | *

20 | * This implementation delegates to a Camel consumer by creating an exchange. 21 | * 22 | * @author Quentin Ligier 23 | **/ 24 | public class ChPharm1Service extends XdsAdhocQueryService implements ChPharm1PortType { 25 | 26 | public ChPharm1Service() { 27 | super(null); 28 | } 29 | 30 | @Override 31 | public AdhocQueryResponse communityPharmacyManagerQueryPharmacyDocuments(final AdhocQueryRequest body) { 32 | return this.processRequest(body); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/platform/camel/ihe/fhir/iti65_v401/Iti65Endpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.platform.camel.ihe.fhir.iti65_v401; 18 | 19 | import org.openehealth.ipf.commons.ihe.fhir.iti65_v401.Iti65AuditDataset; 20 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpoint; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 22 | 23 | /** 24 | * @author Christian Ohr 25 | * @since 3.6 26 | */ 27 | public class Iti65Endpoint extends FhirEndpoint { 28 | 29 | public Iti65Endpoint(String uri, Iti65Component fhirComponent, FhirEndpointConfiguration config) { 30 | super(uri, fhirComponent, config); 31 | } 32 | 33 | @Override 34 | protected String createEndpointUri() { 35 | return "mhd-iti65-v401:" + "not-implemented yet"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/platform/camel/ihe/fhir/iti66_v401/Iti66Endpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.platform.camel.ihe.fhir.iti66_v401; 18 | 19 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 20 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpoint; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 22 | 23 | /** 24 | * @author Christian Ohr 25 | * @since 3.6 26 | */ 27 | public class Iti66Endpoint extends FhirEndpoint { 28 | 29 | public Iti66Endpoint(String uri, Iti66Component fhirComponent, FhirEndpointConfiguration config) { 30 | super(uri, fhirComponent, config); 31 | } 32 | 33 | @Override 34 | protected String createEndpointUri() { 35 | return "mhd-iti66-v401:" + "not-implemented yet"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/platform/camel/ihe/fhir/iti67_v401/Iti67Endpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.platform.camel.ihe.fhir.iti67_v401; 18 | 19 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 20 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpoint; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 22 | 23 | /** 24 | * @author Christian Ohr 25 | * @since 3.6 26 | */ 27 | public class Iti67Endpoint extends FhirEndpoint { 28 | 29 | public Iti67Endpoint(String uri, Iti67Component fhirComponent, FhirEndpointConfiguration config) { 30 | super(uri, fhirComponent, config); 31 | } 32 | 33 | @Override 34 | protected String createEndpointUri() { 35 | return "mhd-iti67-v401:" + "not-implemented yet"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /angular/.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------------------- 2 | # Copyright (c) Microsoft Corporation. All rights reserved. 3 | # Licensed under the MIT License. See LICENSE in the project root for license information. 4 | #----------------------------------------------------------------------------------------- 5 | 6 | FROM node:lts 7 | 8 | # Configure apt 9 | ENV DEBIAN_FRONTEND=noninteractive 10 | RUN apt-get update \ 11 | && apt-get -y install --no-install-recommends apt-utils 2>&1 12 | 13 | # Verify git and process tools are installed 14 | RUN apt-get install -y git procps 15 | 16 | # Remove outdated yarn from /opt and install via package 17 | # so it can be easily updated via apt-get upgrade yarn 18 | RUN rm -rf /opt/yarn-* \ 19 | && rm -f /usr/local/bin/yarn \ 20 | && rm -f /usr/local/bin/yarnpkg \ 21 | && apt-get install -y curl apt-transport-https lsb-release \ 22 | && curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \ 23 | && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ 24 | && apt-get update \ 25 | && apt-get -y install --no-install-recommends yarn 26 | 27 | # Install eslint 28 | RUN npm install -g eslint 29 | 30 | # Install angular (added by oliver) 31 | RUN npm install -g @angular/cli 32 | 33 | # Clean up 34 | RUN apt-get autoremove -y \ 35 | && apt-get clean -y \ 36 | && rm -rf /var/lib/apt/lists/* 37 | ENV DEBIAN_FRONTEND=dialog 38 | -------------------------------------------------------------------------------- /docs/docker.md: -------------------------------------------------------------------------------- 1 | # mobile access container 2 | 3 | you can download the mobile access gateway as a docker container: 4 | 5 | ``` 6 | docker pull europe-west6-docker.pkg.dev/ahdis-ch/ahdis/mag:v062 7 | ``` 8 | 9 | ## Configurable base image: 10 | 11 | run from the cloned [mobile access gateway](https://github.com/i4mi/MobileAccessGateway): 12 | 13 | ```bash 14 | docker run -d -it --name mag -p 9090:9090 -v /Users/oegger/Documents/github/MobileAccessGateway/example-playground:/config/ europe-west6-docker.pkg.dev/ahdis-ch/ahdis/mag:v062 15 | docker logs --follow mag 16 | ``` 17 | 18 | Server endpoint will then be accessible at http://localhost:9090/mag/fhir/metadata 19 | 20 | You can check for example a PIXm query against the EPD playground: 21 | 22 | ```http 23 | http://localhost:9090/mag/fhir/Patient/$ihe-pix?sourceIdentifier=urn%3Aoid%3A2.16.756.5.30.1.127.3.10.3%7C761337615395845832&targetSystem=urn%3Aoid%3A1.1.1.99.1&targetSystem=urn%3Aoid%3A2.16.756.5.30.1.127.3.10.3 24 | ``` 25 | 26 | The mobile access gateway supports also a GUI which is accessible at http://localhost:9090/mag/#/. 27 | 28 | ## Live and Readiness checks 29 | 30 | To check if the container is live and ready you can check the health: 31 | 32 | ```http 33 | GET http://localhost:9090/mag/actuator/health HTTP/1.1 34 | Accept: application/vnd.spring-boot.actuator.v3+json 35 | 36 | HTTP/1.1 200 37 | Content-Type: application/vnd.spring-boot.actuator.v3+json 38 | Transfer-Encoding: chunked 39 | Date: Thu, 02 Feb 2023 15:55:12 GMT 40 | Via: 1.1 google 41 | Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 42 | Connection: close 43 | 44 | { 45 | "status": "UP" 46 | } 47 | ``` -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti93/Iti93Component.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.pmir.iti93; 18 | 19 | import static ch.bfh.ti.i4mi.mag.pmir.iti93.PMIR.Interactions.ITI_93; 20 | 21 | import org.apache.camel.CamelContext; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 23 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirComponent; 24 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 25 | 26 | /** 27 | * Component for PMIR(ITI-93) 28 | * 29 | */ 30 | public class Iti93Component extends FhirComponent { 31 | 32 | 33 | public Iti93Component() { 34 | super(ITI_93); 35 | } 36 | 37 | public Iti93Component(CamelContext context) { 38 | super(context, ITI_93); 39 | } 40 | 41 | @Override 42 | protected Iti93Endpoint doCreateEndpoint(String uri, FhirEndpointConfiguration config) { 43 | return new Iti93Endpoint(uri, this, config); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/pharm5/Pharm5Component.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.mhd.pharm5; 18 | 19 | import static ch.bfh.ti.i4mi.mag.mhd.PHARM.Interactions.PHARM5; 20 | 21 | import org.apache.camel.CamelContext; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 23 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirComponent; 24 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 25 | 26 | /** 27 | * Component for PHARM5 28 | * 29 | */ 30 | public class Pharm5Component extends FhirComponent { 31 | 32 | 33 | public Pharm5Component() { 34 | super(PHARM5); 35 | } 36 | 37 | public Pharm5Component(CamelContext context) { 38 | super(context, PHARM5); 39 | } 40 | 41 | @Override 42 | protected Pharm5Endpoint doCreateEndpoint(String uri, FhirEndpointConfiguration config) { 43 | return new Pharm5Endpoint(uri, this, config); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/TraceHeaderLoggingFilter.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag; 2 | 3 | import io.micrometer.tracing.Tracer; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.slf4j.MDC; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.servlet.*; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | @Component 15 | public class TraceHeaderLoggingFilter implements Filter { 16 | private static final Logger logger = LoggerFactory.getLogger(TraceHeaderLoggingFilter.class); 17 | 18 | private final Tracer tracer; 19 | 20 | public TraceHeaderLoggingFilter(Tracer tracer) { 21 | this.tracer = tracer; 22 | } 23 | 24 | @Override 25 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 26 | HttpServletRequest request = (HttpServletRequest) servletRequest; 27 | HttpServletResponse response = (HttpServletResponse) servletResponse; 28 | 29 | String traceparent = request.getHeader("traceparent"); 30 | String tracestate = request.getHeader("tracestate"); 31 | String b3 = request.getHeader("b3"); 32 | 33 | logger.info("Trace headers: traceparent={}, tracestate={}, b3={}", traceparent, tracestate, b3); 34 | 35 | MDC.put("traceparent", traceparent); 36 | MDC.put("tracestate", tracestate); 37 | MDC.put("b3", b3); 38 | 39 | try { 40 | filterChain.doFilter(request, response); 41 | } finally { 42 | MDC.clear(); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti104/Iti104Component.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.pmir.iti104; 18 | 19 | import static ch.bfh.ti.i4mi.mag.pmir.iti104.PMIR.Interactions.ITI_104; 20 | 21 | import org.apache.camel.CamelContext; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 23 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirComponent; 24 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 25 | 26 | /** 27 | * Component for PMIR(ITI-104) 28 | * 29 | */ 30 | public class Iti104Component extends FhirComponent { 31 | 32 | 33 | public Iti104Component() { 34 | super(ITI_104); 35 | } 36 | 37 | public Iti104Component(CamelContext context) { 38 | super(context, ITI_104); 39 | } 40 | 41 | @Override 42 | protected Iti104Endpoint doCreateEndpoint(String uri, FhirEndpointConfiguration config) { 43 | return new Iti104Endpoint(uri, this, config); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti93/Iti93Endpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.pmir.iti93; 18 | 19 | import org.apache.camel.spi.UriEndpoint; 20 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirConsumer; 22 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpoint; 23 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 24 | 25 | /** 26 | * PMIR Mobile Patient Identity Feed endpoint (ITI-93) 27 | * 28 | */ 29 | @UriEndpoint(scheme = "pmir-iti93", title = "ITI-93 PMIR", syntax = "pmir-iti93:host:port", consumerClass = FhirConsumer.class, label = "http") 30 | public class Iti93Endpoint extends FhirEndpoint { 31 | 32 | public Iti93Endpoint(String uri, Iti93Component fhirComponent, FhirEndpointConfiguration config) { 33 | super(uri, fhirComponent, config); 34 | } 35 | 36 | @Override 37 | protected String createEndpointUri() { 38 | return "pmir-iti93:" + "not-implemented yet"; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti104/Iti104Endpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.pmir.iti104; 18 | 19 | import org.apache.camel.spi.UriEndpoint; 20 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirConsumer; 22 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpoint; 23 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 24 | 25 | /** 26 | * Patient Identity Feed FHIR endpoint (ITI-104) 27 | * 28 | */ 29 | @UriEndpoint(scheme = "pmir-iti104", title = "ITI-104 PMIR", syntax = "pmir-iti104:host:port", consumerClass = FhirConsumer.class, label = "http") 30 | public class Iti104Endpoint extends FhirEndpoint { 31 | 32 | public Iti104Endpoint(String uri, Iti104Component fhirComponent, FhirEndpointConfiguration config) { 33 | super(uri, fhirComponent, config); 34 | } 35 | 36 | @Override 37 | protected String createEndpointUri() { 38 | return "pmir-iti104:" + "not-implemented yet"; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /angular/src/_variables.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | $md-mcgpalette0: ( 3 | 50: #e8ebee, 4 | 100: #c5ced5, 5 | 200: #9eaeb9, 6 | 300: #778d9d, 7 | 400: #5a7488, 8 | 500: #6a844d, 9 | 600: #37546b, 10 | 700: #2f4a60, 11 | 800: #274156, 12 | 900: #1a3043, 13 | A100: #84c3ff, 14 | A200: #51aaff, 15 | A400: #1e91ff, 16 | A700: #0485ff, 17 | contrast: ( 18 | 50: #000000, 19 | 100: #000000, 20 | 200: #000000, 21 | 300: #000000, 22 | 400: #ffffff, 23 | 500: #ffffff, 24 | 600: #ffffff, 25 | 700: #ffffff, 26 | 800: #ffffff, 27 | 900: #ffffff, 28 | A100: #000000, 29 | A200: #000000, 30 | A400: #ffffff, 31 | A700: #ffffff, 32 | ), 33 | ); 34 | 35 | $my-primary: mat.define-palette($md-mcgpalette0, 500, 50, 300); 36 | $my-accent: mat.define-palette($md-mcgpalette0, A400); 37 | 38 | @function my-mat-light-theme-foreground($color) { 39 | @return ( 40 | base: $color, 41 | divider: rgba(black, 0.12), 42 | dividers: rgba(black, 0.12), 43 | disabled: rgba($color, 0.38), 44 | disabled-button: rgba($color, 0.38), 45 | disabled-text: rgba($color, 0.38), 46 | hint-text: rgba($color, 0.38), 47 | secondary-text: rgba($color, 0.54), 48 | icon: rgba($color, 0.54), 49 | icons: rgba($color, 0.54), 50 | text: rgba($color, 0.87), 51 | slider-off: rgba($color, 0.26), 52 | slider-off-active: rgba($color, 0.38) 53 | ); 54 | } 55 | 56 | $theme: map-merge( 57 | mat.define-light-theme( 58 | ( 59 | color: ( 60 | primary: $my-primary, 61 | accent: $my-accent, 62 | ), 63 | typography: mat.define-typography-config(), 64 | density: 0, 65 | ) 66 | ), 67 | ( 68 | foreground: my-mat-light-theme-foreground(darken(#113549, 5%)), 69 | ) 70 | ); 71 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti67_v401/Iti67Options.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.openehealth.ipf.commons.ihe.fhir.iti67_v401; 17 | 18 | import org.openehealth.ipf.commons.ihe.fhir.FhirProvider; 19 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionOptions; 20 | import org.openehealth.ipf.commons.ihe.fhir.iti67_v401.Iti67ResourceProvider; 21 | import org.openehealth.ipf.commons.ihe.fhir.iti67_v401.Iti67StrictResourceProvider; 22 | 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | /** 27 | * @since 4.1 28 | */ 29 | public enum Iti67Options implements FhirTransactionOptions { 30 | 31 | STRICT(Iti67StrictResourceProvider.class), 32 | LENIENT(Iti67ResourceProvider.class); 33 | 34 | private final List> resourceProviders; 35 | 36 | @SafeVarargs 37 | Iti67Options(Class... resourceProviders) { 38 | this.resourceProviders = Arrays.asList(resourceProviders); 39 | } 40 | 41 | @Override 42 | public List> getSupportedThings() { 43 | return resourceProviders; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/ch.bfh.ti.i4mi.mag.ppqm/PpqmTestBase.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.ppqm; 2 | 3 | import ch.bfh.ti.i4mi.mag.MobileAccessGateway; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.camel.CamelContext; 6 | import org.apache.camel.ProducerTemplate; 7 | import org.junit.jupiter.api.BeforeAll; 8 | import org.openehealth.ipf.commons.ihe.xacml20.Xacml20Utils; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.context.annotation.Import; 13 | import org.springframework.test.context.ActiveProfiles; 14 | 15 | import java.util.Locale; 16 | 17 | /** 18 | * @author Dmytro Rud 19 | */ 20 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 21 | @Import(MobileAccessGateway.class) 22 | @ActiveProfiles("test") 23 | @Slf4j 24 | abstract public class PpqmTestBase { 25 | 26 | @Autowired 27 | protected CamelContext camelContext; 28 | 29 | @Autowired 30 | protected ProducerTemplate producerTemplate; 31 | 32 | @Value("${server.port}") 33 | protected Integer serverPort; 34 | 35 | @BeforeAll 36 | public static void beforeAll() { 37 | Xacml20Utils.initializeHerasaf(); 38 | Locale.setDefault(Locale.ENGLISH); 39 | 40 | // System.setProperty("javax.net.ssl.keyStore", "src/main/resources/example-server-certificate.p12"); 41 | // System.setProperty("javax.net.ssl.keyStorePassword", "a1b2c3"); 42 | // System.setProperty("javax.net.ssl.trustStore", "src/main/resources/example-server-certificate.p12"); 43 | // System.setProperty("javax.net.ssl.trustStorePassword", "a1b2c3"); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /angular/src/app/settings/settings.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FhirConfigService } from '../fhirConfig.service'; 3 | import { Subscription } from 'rxjs'; 4 | import debug from 'debug'; 5 | import Client from 'fhir-kit-client'; 6 | import { Router } from '@angular/router'; 7 | 8 | @Component({ 9 | selector: 'app-settings', 10 | templateUrl: './settings.component.html', 11 | styleUrls: ['./settings.component.scss'], 12 | }) 13 | export class SettingsComponent implements OnInit { 14 | mobileAccessGateways = [ 15 | 'https://test.ahdis.ch/mag-cara/fhir', 16 | 'https://test.ahdis.ch/eprik-proxy-cara/camel/mag-cara/fhir', 17 | 'https://test.ahdis.ch/mag-pmp2/fhir', 18 | 'https://test.ahdis.ch/eprik-proxy-cara/camel/mag-pmp/fhir', 19 | 'https://test.ahdis.ch/mag-bfh/fhir', 20 | 'https://test.ahdis.ch/mag-test/fhir', 21 | 'https://test.ahdis.ch/mag-test-emedo/fhir', 22 | 'http://localhost:8080/matchbox/fhir', 23 | 'http://localhost:9090/mag-pmp2/fhir', 24 | 'http://localhost:9090/mag-cara/fhir', 25 | 'http://localhost:18002/eprik-proxy-cara/camel/mag-pmp/fhir', 26 | ]; 27 | 28 | subscriptionFhir: Subscription; 29 | baseUrlFhir: string; 30 | subscriptionMag: Subscription; 31 | baseUrlMag: string; 32 | 33 | client: Client; 34 | 35 | constructor(private data: FhirConfigService, private router: Router) { 36 | this.client = data.getMobileAccessGatewayClient(); 37 | } 38 | 39 | ngOnInit() { 40 | this.baseUrlMag = this.data.getMobileAccessGatewayService(); 41 | } 42 | 43 | getMagSelectedValue(): string { 44 | return this.baseUrlMag; 45 | } 46 | 47 | setMagSelectedValue(value: string) { 48 | debug('setting new server to ' + value); 49 | this.data.changeMagMicroService(value); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/IDPAssertionDetailsService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | 18 | package ch.bfh.ti.i4mi.mag.xua; 19 | 20 | import org.opensaml.ws.message.encoder.MessageEncodingException; 21 | import org.opensaml.xml.util.XMLHelper; 22 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 23 | import org.springframework.security.saml.SAMLCredential; 24 | import org.springframework.security.saml.userdetails.SAMLUserDetailsService; 25 | import org.springframework.security.saml.util.SAMLUtil; 26 | 27 | /** 28 | * Use full assertion as identification of user 29 | * @author alexander kreutz 30 | * 31 | */ 32 | public class IDPAssertionDetailsService implements SAMLUserDetailsService { 33 | 34 | @Override 35 | public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException { 36 | 37 | try { 38 | //return XMLHelper.nodeToString(SAMLUtil.marshallMessage(credential.getAuthenticationAssertion())); 39 | return SAMLUtil.marshallMessage(credential.getAuthenticationAssertion()); 40 | 41 | } catch (MessageEncodingException e) { 42 | 43 | } 44 | return null; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/platform/camel/ihe/fhir/iti65_v401/Iti65Component.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.platform.camel.ihe.fhir.iti65_v401; 18 | 19 | import org.apache.camel.CamelContext; 20 | import org.openehealth.ipf.commons.ihe.fhir.iti65_v401.Iti65AuditDataset; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirComponent; 22 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 23 | 24 | import static org.openehealth.ipf.commons.ihe.fhir.mhd_v401.MHD.SubmitInteractions.ITI_65; 25 | 26 | /** 27 | * Component for MHD Register Document (ITI-65) 28 | * 29 | * @author Christian Ohr 30 | * @since 3.6 31 | */ 32 | public class Iti65Component extends FhirComponent { 33 | 34 | 35 | public Iti65Component() { 36 | super(ITI_65); 37 | } 38 | 39 | public Iti65Component(CamelContext context) { 40 | super(context, ITI_65); 41 | } 42 | 43 | @Override 44 | protected Iti65Endpoint doCreateEndpoint(String uri, FhirEndpointConfiguration config) { 45 | return new Iti65Endpoint(uri, this, config); 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/pharm5/Pharm5Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.mhd.pharm5; 18 | 19 | import java.util.Arrays; 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | 23 | /** 24 | * @author Oliver Egger 25 | */ 26 | public interface Pharm5Constants { 27 | 28 | final String PHARM5_OPERATION_NAME = "$find-medication-list"; 29 | final String PHARM5_STATUS = "status"; 30 | final String PHARM5_PATIENT_IDENTIFIER = "patient.identifier"; 31 | final String PHARM5_FORMAT = "format"; 32 | final String PHARM5_SERVICE_START_FROM = "serviceStartFrom"; 33 | final String PHARM5_SERVICE_START_TO = "serviceStartTo"; 34 | final String PHARM5_SERVICE_END_FROM = "serviceEndFrom"; 35 | final String PHARM5_SERVICE_END_TO = "serviceEndTo"; 36 | 37 | // needs to be extended 38 | Set PHARM5_PARAMETERS = new HashSet<>(Arrays.asList( 39 | PHARM5_STATUS, 40 | PHARM5_PATIENT_IDENTIFIER, 41 | PHARM5_FORMAT, 42 | PHARM5_SERVICE_START_FROM, 43 | PHARM5_SERVICE_START_TO, 44 | PHARM5_SERVICE_END_FROM, 45 | PHARM5_SERVICE_END_TO)); 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/platform/camel/ihe/fhir/iti66_v401/Iti66Component.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.platform.camel.ihe.fhir.iti66_v401; 18 | 19 | import org.apache.camel.CamelContext; 20 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirComponent; 22 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 23 | 24 | import static org.openehealth.ipf.commons.ihe.fhir.mhd_v401.MHD.QueryInteractions.ITI_66; 25 | 26 | /** 27 | * Component for MHD Retrieve Document Manifest (ITI-66) 28 | * 29 | * @author Christian Ohr 30 | * @since 3.6 31 | */ 32 | public class Iti66Component extends FhirComponent { 33 | 34 | 35 | public Iti66Component() { 36 | super(ITI_66); 37 | } 38 | 39 | public Iti66Component(CamelContext context) { 40 | super(context, ITI_66); 41 | } 42 | 43 | @Override 44 | protected Iti66Endpoint doCreateEndpoint(String uri, FhirEndpointConfiguration config) { 45 | return new Iti66Endpoint(uri, this, config); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/platform/camel/ihe/fhir/iti67_v401/Iti67Component.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.platform.camel.ihe.fhir.iti67_v401; 18 | 19 | import org.apache.camel.CamelContext; 20 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 21 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirComponent; 22 | import org.openehealth.ipf.platform.camel.ihe.fhir.core.FhirEndpointConfiguration; 23 | 24 | import static org.openehealth.ipf.commons.ihe.fhir.mhd_v401.MHD.QueryInteractions.ITI_67; 25 | 26 | /** 27 | * Component for MHD Retrieve Document Manifest (ITI-66) 28 | * 29 | * @author Christian Ohr 30 | * @since 3.6 31 | */ 32 | public class Iti67Component extends FhirComponent { 33 | 34 | 35 | public Iti67Component() { 36 | super(ITI_67); 37 | } 38 | 39 | public Iti67Component(CamelContext context) { 40 | super(context, ITI_67); 41 | } 42 | 43 | @Override 44 | protected Iti67Endpoint doCreateEndpoint(String uri, FhirEndpointConfiguration config) { 45 | return new Iti67Endpoint(uri, this, config); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti67_v401/Iti67OptionsProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.commons.ihe.fhir.iti67_v401; 18 | 19 | import org.openehealth.ipf.commons.ihe.core.atna.AuditStrategy; 20 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionOptionsProvider; 21 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 22 | import org.openehealth.ipf.commons.ihe.fhir.iti67_v401.Iti67AuditStrategy; 23 | import org.openehealth.ipf.commons.ihe.fhir.iti67_v401.Iti67Options; 24 | 25 | /** 26 | * @author Christian Ohr 27 | * @since 4.1 28 | */ 29 | public class Iti67OptionsProvider implements FhirTransactionOptionsProvider { 30 | 31 | @Override 32 | public Class getTransactionOptionsType() { 33 | return Iti67Options.class; 34 | } 35 | 36 | @Override 37 | public Iti67Options getDefaultOption() { 38 | return Iti67Options.LENIENT; 39 | } 40 | 41 | @Override 42 | public AuditStrategy getAuditStrategy(boolean serverSide) { 43 | return new Iti67AuditStrategy(serverSide); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /docs/changelog.md: -------------------------------------------------------------------------------- 1 | ## 2024/11/26 v1.0.0 2 | 3 | - Fixed an NPE in the assertion route 4 | - Improved mapping between XDS XON and FHIR Organization [165](https://github.com/i4mi/MobileAccessGateway/issues/165) 5 | - Capability statement validation issues [#177](https://github.com/i4mi/MobileAccessGateway/issues/177) 6 | - Add CH PIXm ITI-83 constraints for sourceIdentifier and targetSystem [#170](https://github.com/i4mi/MobileAccessGateway/issues/170) 7 | - Add support for 401 error code [#182](https://github.com/i4mi/MobileAccessGateway/issues/182) 8 | - Allow using the EPR-SPID as Patient id 9 | 10 | ## 2024/05/15 v070 11 | - support for multiple IDP's [128](https://github.com/i4mi/MobileAccessGateway/issues/128) 12 | - reenable $find-medication-list 13 | - use IdP also for patient access in web app 14 | 15 | ## 2024/05/08 v064 16 | 17 | - Added OAuth URLs to the CapabilityStatement [#135](https://github.com/i4mi/MobileAccessGateway/issues/135) 18 | - Implemented PPQm routes [#126](https://github.com/i4mi/MobileAccessGateway/issues/126) 19 | - Upgraded to IPF 4.8.0 20 | - Removed dependency on IHE-Europe STS simulator 21 | - Support for email in real case scenario with invalid contact infos [#138](https://github.com/i4mi/MobileAccessGateway/pull/138) 22 | - Added missing document entry attributes 23 | - Certificate can be injected by environment variables 24 | - Fixed coding system OIDs of document author and uploader role codes 25 | 26 | 27 | ## 2024/02/08 v062 28 | 29 | - `docker pull europe-west6-docker.pkg.dev/ahdis-ch/ahdis/mag:v062` 30 | - Updated documentation on [https://i4mi.github.io/MobileAccessGateway/](https://i4mi.github.io/MobileAccessGateway/) 31 | for containers [#132](https://github.com/i4mi/MobileAccessGateway/issues/132) 32 | 33 | ## Older releases 34 | 35 | For older releases see github [tags](https://github.com/i4mi/MobileAccessGateway/tags) 36 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/LoggingSpanHandler.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag; 2 | 3 | import brave.handler.MutableSpan; 4 | import brave.handler.SpanHandler; 5 | import brave.propagation.TraceContext; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class LoggingSpanHandler extends SpanHandler { 10 | private static final Logger logger = LoggerFactory.getLogger(LoggingSpanHandler.class); 11 | 12 | public LoggingSpanHandler() { 13 | logger.info("LoggingSpanHandler constructed"); 14 | } 15 | 16 | @Override 17 | public boolean begin(TraceContext context, MutableSpan span, TraceContext parent) { 18 | logger.info("begin method called"); 19 | if (context != null) { 20 | logger.info("Span started: traceId={}, spanId={}, parentId={}, name={}", 21 | context.traceIdString(), 22 | context.spanIdString(), 23 | parent != null ? parent.spanIdString() : "none", 24 | span != null ? span.name() : "null"); 25 | } else { 26 | logger.info("Span started: context is null"); 27 | } 28 | return true; 29 | } 30 | 31 | @Override 32 | public boolean end(TraceContext context, MutableSpan span, Cause cause) { 33 | logger.info("end method called"); 34 | if (context != null && span != null) { 35 | logger.info("Span completed: traceId={}, spanId={}, name={}, duration={}ms, tags={}", 36 | context.traceIdString(), 37 | context.spanIdString(), 38 | span.name(), 39 | span.finishTimestamp() - span.startTimestamp(), 40 | span.tags()); 41 | } else { 42 | logger.info("Span completed: context or span is null"); 43 | } 44 | return true; 45 | } 46 | } -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti93/Iti93TransactionConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package ch.bfh.ti.i4mi.mag.pmir.iti93; 17 | 18 | import ca.uhn.fhir.context.FhirVersionEnum; 19 | 20 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 21 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionValidator; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 23 | 24 | /** 25 | * Standard Configuration for Iti93Component. Lazy-loading of results is by default not supported. 26 | * 27 | */ 28 | public class Iti93TransactionConfiguration extends FhirTransactionConfiguration { 29 | 30 | public Iti93TransactionConfiguration() { 31 | super( 32 | "pmir-iti93", 33 | "PMIR Mobile Patient Identity Feed", 34 | false, 35 | new Iti93AuditStrategy(false), 36 | new Iti93AuditStrategy(true), 37 | FhirVersionEnum.R4, 38 | new Iti93ResourceProvider(), // Consumer side. accept $ihe-pix operation 39 | null, 40 | FhirTransactionValidator.NO_VALIDATION); 41 | setSupportsLazyLoading(false); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /example-config/kubernetes-config.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: mobile-access-gateway 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: mobile-access-gateway 10 | template: 11 | metadata: 12 | labels: 13 | app: mobile-access-gateway 14 | spec: 15 | volumes: 16 | - name: mobile-access-gateway-config-volume 17 | configMap: 18 | name: mobile-access-gateway-configmap 19 | - name: mobile-access-gateway-secret-volume 20 | secret: 21 | secretName: mobile-access-gateway-secret 22 | containers: 23 | - name: mobile-access-gateway 24 | image: europe-west6-docker.pkg.dev/ahdis-ch/ahdis/mag:v070 25 | resources: 26 | requests: 27 | memory: "0.6Gi" 28 | ports: 29 | - containerPort: 9090 30 | - containerPort: 9091 31 | volumeMounts: 32 | - name: mobile-access-gateway-config-volume 33 | mountPath: /config 34 | - name: mobile-access-gateway-secret-volume 35 | mountPath: /secret 36 | livenessProbe: 37 | httpGet: 38 | path: /actuator/health 39 | port: 9090 40 | initialDelaySeconds: 20 41 | periodSeconds: 2 42 | readinessProbe: 43 | httpGet: 44 | path: /actuator/health 45 | port: 9090 46 | initialDelaySeconds: 20 47 | periodSeconds: 2 48 | --- 49 | apiVersion: v1 50 | kind: Service 51 | metadata: 52 | name: mobile-access-gateway-service 53 | spec: 54 | type: NodePort 55 | ports: 56 | - port: 9090 57 | name: http 58 | targetPort: 9090 59 | nodePort: 30090 60 | - port: 9091 61 | name: https 62 | targetPort: 9091 63 | nodePort: 30091 64 | selector: 65 | app: mobile-access-gateway 66 | --- -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti104/Iti104TransactionConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package ch.bfh.ti.i4mi.mag.pmir.iti104; 17 | 18 | import ca.uhn.fhir.context.FhirVersionEnum; 19 | 20 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 21 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionValidator; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 23 | 24 | /** 25 | * Standard Configuration for Iti104Component. Lazy-loading of results is by default not supported. 26 | * 27 | */ 28 | public class Iti104TransactionConfiguration extends FhirTransactionConfiguration { 29 | 30 | public Iti104TransactionConfiguration() { 31 | super( 32 | "pmir-iti104", 33 | "Patient Identity Feed FHIR", 34 | false, 35 | new Iti104AuditStrategy(false), 36 | new Iti104AuditStrategy(true), 37 | FhirVersionEnum.R4, 38 | new Iti104ResourceProvider(), // Consumer side. accept $ihe-pix operation 39 | null, 40 | FhirTransactionValidator.NO_VALIDATION); 41 | setSupportsLazyLoading(false); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/pharm5/Pharm5TransactionConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package ch.bfh.ti.i4mi.mag.mhd.pharm5; 17 | 18 | import ca.uhn.fhir.context.FhirVersionEnum; 19 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 20 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionValidator; 21 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 22 | 23 | /** 24 | * Standard Configuration for Iti83Component. Lazy-loading of results is by default not supported. 25 | * 26 | * @author Christian Ohr 27 | * @since 3.6 28 | */ 29 | public class Pharm5TransactionConfiguration extends FhirTransactionConfiguration { 30 | 31 | public Pharm5TransactionConfiguration() { 32 | super( 33 | "mhd-pharm5", 34 | "FindMedicationList", 35 | true, 36 | new Pharm5AuditStrategy(false), 37 | new Pharm5AuditStrategy(true), 38 | FhirVersionEnum.R4, 39 | new Pharm5ResourceProvider(), 40 | new Pharm5ClientRequestFactory(), 41 | FhirTransactionValidator.NO_VALIDATION); 42 | setSupportsLazyLoading(false); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/AssertionRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.xua; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import lombok.Getter; 23 | import lombok.Setter; 24 | 25 | /** 26 | * Information for a Get-X-User Assertion Request 27 | * @author alexander kreutz 28 | * 29 | */ 30 | public class AssertionRequest { 31 | 32 | @Getter @Setter 33 | private String purposeOfUse; 34 | 35 | @Getter @Setter 36 | private String role; 37 | 38 | @Getter @Setter 39 | private String resourceId; 40 | 41 | @Getter @Setter 42 | private String principalID; 43 | 44 | @Getter @Setter 45 | private String principalName; 46 | 47 | @Getter @Setter 48 | private List organizationID; 49 | 50 | @Getter @Setter 51 | private List organizationName; 52 | 53 | @Getter @Setter 54 | private Object samlToken; 55 | 56 | public void addOrganizationID(String orgId) { 57 | if (organizationID==null) organizationID = new ArrayList(); 58 | organizationID.add(orgId); 59 | } 60 | 61 | public void addOrganizationName(String orgName) { 62 | if (organizationName==null) organizationName = new ArrayList(); 63 | organizationName.add(orgName); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti93/PMIR.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package ch.bfh.ti.i4mi.mag.pmir.iti93; 17 | 18 | import java.util.Arrays; 19 | import java.util.List; 20 | 21 | import org.openehealth.ipf.commons.ihe.core.IntegrationProfile; 22 | import org.openehealth.ipf.commons.ihe.core.InteractionId; 23 | import org.openehealth.ipf.commons.ihe.fhir.FhirInteractionId; 24 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 25 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 26 | 27 | import lombok.AllArgsConstructor; 28 | import lombok.Getter; 29 | 30 | /** 31 | * @author Oliver Egger 32 | */ 33 | public class PMIR implements IntegrationProfile { 34 | 35 | @AllArgsConstructor 36 | public enum Interactions implements FhirInteractionId { 37 | 38 | ITI_93(ITI_93_CONFIG); 39 | 40 | @Getter 41 | FhirTransactionConfiguration fhirTransactionConfiguration; 42 | } 43 | 44 | @Override 45 | public List getInteractionIds() { 46 | return Arrays.asList(Interactions.values()); 47 | } 48 | 49 | private static final Iti93TransactionConfiguration ITI_93_CONFIG = new Iti93TransactionConfiguration(); 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/ch/bfh/ti/i4mi/mag/mhd/BaseQueryResponseConverterTest.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.mhd; 2 | 3 | import ch.bfh.ti.i4mi.mag.Config; 4 | import ch.bfh.ti.i4mi.mag.mhd.iti67.Iti67ResponseConverter; 5 | import org.junit.jupiter.api.Test; 6 | import org.openehealth.ipf.commons.ihe.xds.core.metadata.Hl7v2Based; 7 | import org.openehealth.ipf.commons.ihe.xds.core.metadata.Organization; 8 | 9 | import static org.junit.jupiter.api.Assertions.*; 10 | 11 | /** 12 | * Tests for {@link BaseQueryResponseConverter}. 13 | * 14 | * @author Quentin Ligier 15 | **/ 16 | class BaseQueryResponseConverterTest { 17 | 18 | @Test 19 | void testTransformOrganization() { 20 | final var converter = new Iti67ResponseConverter(new Config()); 21 | 22 | var fhirOrg = converter.transform(Hl7v2Based.parse("Test^^^^^^^^^1234", Organization.class)); 23 | assertEquals("Test", fhirOrg.getName()); 24 | assertEquals(1, fhirOrg.getIdentifier().size()); 25 | assertEquals("1234", fhirOrg.getIdentifierFirstRep().getValue()); 26 | assertFalse(fhirOrg.getIdentifierFirstRep().hasSystem()); 27 | 28 | fhirOrg = converter.transform(Hl7v2Based.parse("Test^^^^^&1.2.3&ISO^^^^1234", Organization.class)); 29 | assertEquals("Test", fhirOrg.getName()); 30 | assertEquals(1, fhirOrg.getIdentifier().size()); 31 | assertEquals("1234", fhirOrg.getIdentifierFirstRep().getValue()); 32 | assertEquals("urn:oid:1.2.3", fhirOrg.getIdentifierFirstRep().getSystem()); 33 | 34 | fhirOrg = converter.transform(Hl7v2Based.parse("Test^^^^^^^^^1.2.3", Organization.class)); 35 | assertEquals("Test", fhirOrg.getName()); 36 | assertEquals(1, fhirOrg.getIdentifier().size()); 37 | assertEquals("urn:oid:1.2.3", fhirOrg.getIdentifierFirstRep().getValue()); 38 | assertEquals("urn:ietf:rfc:3986", fhirOrg.getIdentifierFirstRep().getSystem()); 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti104/PMIR.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package ch.bfh.ti.i4mi.mag.pmir.iti104; 17 | 18 | import java.util.Arrays; 19 | import java.util.List; 20 | 21 | import org.openehealth.ipf.commons.ihe.core.IntegrationProfile; 22 | import org.openehealth.ipf.commons.ihe.core.InteractionId; 23 | import org.openehealth.ipf.commons.ihe.fhir.FhirInteractionId; 24 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 25 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 26 | 27 | import lombok.AllArgsConstructor; 28 | import lombok.Getter; 29 | 30 | /** 31 | * @author Oliver Egger 32 | */ 33 | public class PMIR implements IntegrationProfile { 34 | 35 | @AllArgsConstructor 36 | public enum Interactions implements FhirInteractionId { 37 | 38 | ITI_104(ITI_104_CONFIG); 39 | 40 | @Getter 41 | FhirTransactionConfiguration fhirTransactionConfiguration; 42 | } 43 | 44 | @Override 45 | public List getInteractionIds() { 46 | return Arrays.asList(Interactions.values()); 47 | } 48 | 49 | private static final Iti104TransactionConfiguration ITI_104_CONFIG = new Iti104TransactionConfiguration(); 50 | } 51 | -------------------------------------------------------------------------------- /example-playground/application.yml: -------------------------------------------------------------------------------- 1 | # General configuration of the IPF application. 2 | mag: 3 | baseurl: http://localhost:8080/mag 4 | client-ssl: 5 | enabled: false 6 | xds: 7 | https: true 8 | iti-18: 9 | url: epdplayground.i4mi.bfh.ch:7443/Registry/services/RegistryService 10 | iti-43: 11 | url: epdplayground.i4mi.bfh.ch:6443/Repository/services/RepositoryService 12 | iti-41: 13 | url: epdplayground.i4mi.bfh.ch:6443/Repository/services/RepositoryService 14 | retrieve: 15 | url: http://localhost:8080/mag/camel/xdsretrieve 16 | repositoryUniqueId: 1.1.1.2.31 17 | pix: 18 | https: true 19 | iti-45: 20 | url: epdplayground.i4mi.bfh.ch:7443/PIXPDQ/services/PIXPDQV3ManagerService 21 | iti-44: 22 | url: epdplayground.i4mi.bfh.ch:7443/PIXPDQ/services/PIXPDQV3ManagerService 23 | # url: epdplayground.i4mi.bfh.ch:7443/UPIProxy/services/PIXPDQV3ManagerService 24 | iti-47: 25 | url: epdplayground.i4mi.bfh.ch:7443/PIXPDQ/services/PIXPDQV3ManagerService 26 | oids: 27 | sender: 2.16.756.5.30.1.178.1.1 28 | mpi-pid: 1.1.1.99.1 29 | receiver: 1.3.6.1.4.1.21367.2017.2.4.98 30 | query: 1.3.6.1.4.1.21367.2017.2.1.104 31 | audit: 32 | audit-enabled: true 33 | audit-tls-enabled: false 34 | # in productive system audit-source-id must be same as audit-enterprise-site-id 35 | audit-source-id: CCC_BFH_MAG 36 | audit-enterprise-site-id: 1.3.6.1.4.1.21367.2017.2.7.109 37 | audit-repository-host: 147.87.117.70 38 | audit-repository-port: 5234 39 | audit-repository-transport: TLS 40 | iua: 41 | idp: 42 | name: idp-ehealthsuisse 43 | metadata-url: https://ehealthsuisse.ihe-europe.net/metadata/idp-metadata.xml 44 | server: 45 | servlet: 46 | context-path: /mag 47 | spring: 48 | application: 49 | name: mag 50 | -------------------------------------------------------------------------------- /angular/README.md: -------------------------------------------------------------------------------- 1 | # client frontend to mag 2 | 3 | # development setup 4 | 5 | if you are not using the devcontainer from this project with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/containers) extension you need to have angular cli and [yarn](https://yarnpkg.com/en/) installed: 6 | 7 | ``` 8 | npm install -g @angular/cli 9 | npm install 10 | ng build --configuration development 11 | ``` 12 | 13 | and then 14 | 15 | ng serve --configuration development 16 | 17 | ## usage 18 | 19 | Run `ng serve --configuration development` to start the app, app will be at [http://localhost:4200](http://localhost:4200/). 20 | If you use the Visual Code functionality with Remote containers: Open Folder in container option, you need to start it with `ng serve --host 0.0.0.0`. 21 | 22 | if you use localhost and have cross site blocking issues within chrome start chrome directly from command line (osx) 23 | 24 | /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating 25 | 26 | ## running unit tests 27 | 28 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 29 | 30 | ## frontend for matchbox 31 | 32 | this angular app is directly provided with matchbox 33 | 34 | ``` 35 | ng build --configuration production 36 | rm -rf ../src/main/resources/static/* 37 | cp -r dist/* ../src/main/resources/static 38 | ``` 39 | 40 | ## Contributing 41 | 42 | Have a look at [contributing](CONTRIBUTING.md). 43 | 44 | ## setup fhir-kit-client 45 | 46 | ``` 47 | yarn add fhir-kit-client 48 | yarn add @types/fhir-kit-client --dev 49 | yarn add debug 50 | yarn add @types/debug --dev 51 | 52 | ``` 53 | 54 | see also https://github.com/visionmedia/debug/issues/305 55 | enter in chrome console for debugging the following: 56 | localStorage.debug = 'fhir-kit-client:\*'; 57 | 58 | localStorage.debug = 'fhir-kit-client:_,app:_'; 59 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti65_v401/Iti65Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.commons.ihe.fhir.iti65_v401; 18 | 19 | /** 20 | * @author Christian Ohr 21 | * @since 3.6 22 | */ 23 | public interface Iti65Constants { 24 | 25 | String ITI65_LEGACY_METADATA_PROFILE = "https://ihe.net/fhir/tag/iti-65"; 26 | String ITI65_COMPREHENSIVE_METADATA_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Comprehensive.ProvideBundle"; 27 | String ITI65_MINIMAL_METADATA_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Minimal.ProvideBundle"; 28 | 29 | String ITI65_LEGACY_METADATA_PROFILE_HTTP = "http://ihe.net/fhir/tag/iti-65"; 30 | String ITI65_COMPREHENSIVE_METADATA_PROFILE_HTTP = "http://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Comprehensive.ProvideBundle"; 31 | String ITI65_MINIMAL_METADATA_PROFILE_HTTP = "http://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Minimal.ProvideBundle"; 32 | 33 | 34 | String ITI65_MINIMAL_DOCUMENT_MANIFEST_PROFILE = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/IHE.MHD.Minimal.SubmissionSet"; 35 | String ITI65_MINIMAL_DOCUMENT_REFERENCE_PROFILE = "https://ihe.net/fhir/StructureDefinition/IHE_MHD_Provide_Minimal_DocumentReference"; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/PHARM.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package ch.bfh.ti.i4mi.mag.mhd; 17 | 18 | import java.util.Arrays; 19 | import java.util.List; 20 | 21 | import org.openehealth.ipf.commons.ihe.core.IntegrationProfile; 22 | import org.openehealth.ipf.commons.ihe.core.InteractionId; 23 | import org.openehealth.ipf.commons.ihe.fhir.FhirInteractionId; 24 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 25 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 26 | 27 | import ch.bfh.ti.i4mi.mag.mhd.pharm5.Pharm5TransactionConfiguration; 28 | import lombok.AllArgsConstructor; 29 | import lombok.Getter; 30 | 31 | /** 32 | * @author Oliver Egger 33 | */ 34 | public class PHARM implements IntegrationProfile { 35 | 36 | @AllArgsConstructor 37 | public enum Interactions implements FhirInteractionId { 38 | 39 | PHARM5(PHARM5_CONFIG); 40 | 41 | @Getter 42 | FhirTransactionConfiguration fhirTransactionConfiguration; 43 | } 44 | 45 | @Override 46 | public List getInteractionIds() { 47 | return Arrays.asList(Interactions.values()); 48 | } 49 | 50 | private static final Pharm5TransactionConfiguration PHARM5_CONFIG = new Pharm5TransactionConfiguration(); 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/codeql_java.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: CodeQL Java 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | schedule: 12 | - cron: '0 8 * * 1' 13 | 14 | jobs: 15 | build: 16 | name: Analyze the Java code 17 | runs-on: ubuntu-latest 18 | permissions: 19 | actions: read 20 | contents: read 21 | security-events: write 22 | 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | language: [ 'java' ] 27 | 28 | steps: 29 | - name: Checkout the repository 30 | uses: actions/checkout@v3 31 | 32 | - name: Setup Java 11 33 | uses: actions/setup-java@v3 34 | with: 35 | java-version: '11' 36 | distribution: 'adopt' 37 | cache: maven 38 | 39 | # Initializes the CodeQL tools for scanning. 40 | - name: Initialize CodeQL 41 | uses: github/codeql-action/init@v2 42 | with: 43 | languages: 'java' 44 | # If you wish to specify custom queries, you can do so here or in a config file. 45 | # By default, queries listed here will override any specified in a config file. 46 | # Prefix the list here with "+" to use these queries and those in the config file. 47 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 48 | 49 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 50 | # If this step fails, then you should remove it and run the build manually (see below) 51 | - name: Autobuild code 52 | uses: github/codeql-action/autobuild@v2 53 | 54 | - name: Perform CodeQL Analysis 55 | uses: github/codeql-action/analyze@v2 56 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti66_v401/Iti66TransactionConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.openehealth.ipf.commons.ihe.fhir.iti66_v401; 17 | 18 | import ca.uhn.fhir.context.FhirVersionEnum; 19 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 20 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionValidator; 21 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 22 | 23 | /** 24 | * Standard Configuration for Iti66Component. Supports lazy-loading by default. 25 | * 26 | * @author Alexander Kreutz, Christian Ohr 27 | * @since 3.6 28 | */ 29 | public class Iti66TransactionConfiguration extends FhirTransactionConfiguration { 30 | 31 | public Iti66TransactionConfiguration() { 32 | super("mhd-iti66-v401", 33 | "Find Document Lists", 34 | true, 35 | new Iti66AuditStrategy(false), 36 | new Iti66AuditStrategy(true), 37 | FhirVersionEnum.R4, 38 | new Iti66ResourceProvider(), // Consumer side. accept registrations 39 | new Iti66ClientRequestFactory(), 40 | FhirTransactionValidator.NO_VALIDATION); // Formulate requests 41 | setSupportsLazyLoading(true); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/TracingConfiguration.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag; 2 | 3 | import brave.Tracing; 4 | import brave.handler.SpanHandler; 5 | import brave.propagation.ThreadLocalCurrentTraceContext; 6 | import brave.sampler.Sampler; 7 | import io.micrometer.tracing.Tracer; 8 | import io.micrometer.tracing.brave.bridge.BraveBaggageManager; 9 | import io.micrometer.tracing.brave.bridge.BraveCurrentTraceContext; 10 | import io.micrometer.tracing.brave.bridge.BraveTracer; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | @Configuration 17 | public class TracingConfiguration { 18 | private static final Logger logger = LoggerFactory.getLogger(TracingConfiguration.class); 19 | 20 | @Bean 21 | public Tracer tracer(Tracing braveTracing) { 22 | logger.info("Creating BraveTracer"); 23 | return new BraveTracer(braveTracing.tracer(), 24 | new BraveCurrentTraceContext(braveTracing.currentTraceContext()), 25 | new BraveBaggageManager()); 26 | } 27 | 28 | @Bean 29 | public Tracing braveTracing(SpanHandler spanHandler) { 30 | logger.info("Creating Tracing with SpanHandler: {}", spanHandler.getClass().getName()); 31 | return Tracing.newBuilder() 32 | .localServiceName("mobile-access-gateway") 33 | .supportsJoin(false) 34 | .traceId128Bit(true) 35 | .sampler(Sampler.ALWAYS_SAMPLE) 36 | .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder().build()) 37 | .propagationFactory(new CustomPropagationFactory()) 38 | .addSpanHandler(spanHandler) 39 | .build(); 40 | } 41 | 42 | @Bean 43 | public SpanHandler loggingSpanHandler() { 44 | logger.info("Creating LoggingSpanHandler"); 45 | return new LoggingSpanHandler(); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti65_v401/Iti65AuditDataset.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.commons.ihe.fhir.iti65_v401; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | import org.hl7.fhir.r4.model.DocumentManifest; 22 | import org.hl7.fhir.r4.model.ListResource; 23 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirAuditDataset; 24 | 25 | /** 26 | * @author Christian Ohr 27 | * @since 3.6 28 | */ 29 | public class Iti65AuditDataset extends FhirAuditDataset { 30 | 31 | // Document manifest unique ID 32 | @Getter @Setter 33 | private String documentManifestUuid; 34 | 35 | public Iti65AuditDataset(boolean serverSide) { 36 | super(serverSide); 37 | } 38 | 39 | 40 | public void enrichDatasetFromDocumentManifest(ListResource documentManifest) { 41 | var reference = documentManifest.getSubject(); 42 | getPatientIds().add(reference.getResource() != null ? 43 | reference.getResource().getIdElement().getValue() : 44 | reference.getReference()); 45 | // If available, use the documentManifest identifier as documentManifestUuid 46 | if (!documentManifest.getIdentifier().isEmpty()) { 47 | this.documentManifestUuid = documentManifest.getIdentifier().get(0).getValue(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docs/assets/auth.uml.txt: -------------------------------------------------------------------------------- 1 | @startuml 2 | title Current login workflow 3 | 4 | participant App 5 | participant WebView 6 | participant MAG 7 | participant IDP 8 | participant STS 9 | 10 | App-[#green]>WebView: Open webview 11 | activate WebView 12 | 13 | group OAuth/IUA flow 14 | WebView-[#red]>MAG: **Step 1**\n**[ITI-71]** GET /authorize\nextended access request 15 | note right 16 | The IUA callback url and client secret must 17 | be registered in the MAG 18 | end note 19 | end 20 | 21 | group SAML 2 artifact binding 22 | MAG-->WebView: Redirect to the IDP 23 | WebView->IDP: **[AuthnRequest]** POST with SAMLRequest 24 | note right 25 | The MAG generates and signes the 26 | AuthnRequest with its private key 27 | end note 28 | 29 | IDP-->WebView: Show login form 30 | App-[#green]>IDP: Sends login info 31 | 32 | note over IDP: The SAML callback URL, entity ID, public key and\nclient TLS certificate must be registered with the IDP 33 | IDP-->WebView: Redirect to /SSO (SAML callback URL)\nWith the SAML Artifact 34 | 35 | WebView->MAG: Get SAML Artifact 36 | activate MAG 37 | 38 | MAG->IDP: **[ArtifactResolve]** POST 39 | note right 40 | The MAG uses its client TLS certificate 41 | end note 42 | IDP-->MAG: Returns the IDP Assertion 43 | 44 | MAG-->WebView: Redirect to /authorize 45 | deactivate MAG 46 | end 47 | 48 | WebView->MAG: GET /authorize 49 | activate MAG 50 | MAG->STS: **[ITI-40]** Get X-User Assertion 51 | STS-->MAG: Returns the XUA 52 | 53 | 54 | group OAuth/IUA flow 55 | MAG--[#red]>WebView: **Step 2**\nRedirect to IUA callback URL\nWith the code 56 | deactivate MAG 57 | App<--WebView: Close webview 58 | note right 59 | The app can monitor the webview URL, or use 60 | deep-linking to detect this specific redirect, 61 | extract the code and close the webview 62 | end note 63 | deactivate WebView 64 | 65 | App-[#red]>MAG: **Step 3**\n**[ITI-71]** POST /token\nwith the code 66 | MAG-->App: access_token is the XUA 67 | end 68 | @enduml 69 | -------------------------------------------------------------------------------- /angular/src/styles.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | @import 'variables'; 3 | @import '~highlight.js/styles/github.css'; 4 | 5 | // TODO(v15): As of v15 mat.legacy-core no longer includes default typography styles. 6 | // The following line adds: 7 | // 1. Default typography styles for all components 8 | // 2. Styles for typography hierarchy classes (e.g. .mat-headline-1) 9 | // If you specify typography styles for the components you use elsewhere, you should delete this line. 10 | // If you don't need the default component typographies but still want the hierarchy styles, 11 | // you can delete this line and instead use: 12 | // `@include mat.legacy-typography-hierarchy(mat.define-legacy-typography-config());` 13 | @include mat.all-legacy-component-typographies(); 14 | @include mat.legacy-core(); 15 | @include mat.all-legacy-component-themes($theme); 16 | 17 | body { 18 | background: #eff0e7; 19 | 20 | &, 21 | html { 22 | margin: 0; 23 | width: 100%; 24 | height: 100%; 25 | font-family: Roboto, Arial, sans-serif; 26 | } 27 | } 28 | 29 | $primary: map-get($theme, primary); 30 | $outer-space: 1.5rem; 31 | 32 | .mat-card.primary { 33 | padding: $outer-space; 34 | 35 | .primary-card-header { 36 | margin: -$outer-space; 37 | margin-bottom: 0; 38 | padding-top: $outer-space; 39 | padding-left: $outer-space; 40 | padding-right: $outer-space; 41 | 42 | h1 { 43 | margin-bottom: 0; 44 | } 45 | 46 | .mat-card-header-text { 47 | display: none; 48 | } 49 | 50 | @media screen and (min-width: 1020px) { 51 | background-color: mat.get-color-from-palette($primary); 52 | color: white; 53 | border-radius: 4px 4px 0 0; 54 | padding-bottom: $outer-space; 55 | } 56 | } 57 | 58 | .mat-card-content { 59 | padding-top: $outer-space; 60 | } 61 | } 62 | 63 | .mat-toolbar.mat-primary { 64 | background: #d7e355; 65 | color: #fff; 66 | } 67 | 68 | mat-toolbar .logo-container img { 69 | height: 100% !important; 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/ClientValidationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.xua; 18 | 19 | import java.util.Map; 20 | 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.beans.factory.annotation.Qualifier; 23 | import org.springframework.stereotype.Component; 24 | 25 | import lombok.Data; 26 | 27 | /** 28 | * OAuth 2 Client validator 29 | * Check validity of client_id, client_secret, redirect_uri 30 | * @author alexander kreutz 31 | * 32 | */ 33 | @Component 34 | public class ClientValidationService { 35 | 36 | @Data 37 | public static class ClientDefinition { 38 | private String secret; 39 | 40 | private String redirect; 41 | } 42 | 43 | @Autowired 44 | @Qualifier(value = "clients") 45 | private Map clients; 46 | 47 | 48 | 49 | public boolean isValidClientId(String clientId) { 50 | return clients.containsKey(clientId); 51 | } 52 | 53 | public boolean isValidSecret(String clientId, String clientSecret) { 54 | ClientDefinition def = clients.get(clientId); 55 | return def != null && def.getSecret().equals(clientSecret); 56 | } 57 | 58 | public boolean isValidRedirectUri(String clientId, String redirectUri) { 59 | ClientDefinition def = clients.get(clientId); 60 | return def != null && redirectUri.startsWith(def.getRedirect()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/iti67/Iti67FromIti57ResponseConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.mhd.iti67; 18 | 19 | import ca.uhn.fhir.rest.api.MethodOutcome; 20 | import ch.bfh.ti.i4mi.mag.Config; 21 | import ch.bfh.ti.i4mi.mag.mhd.BaseResponseConverter; 22 | import org.openehealth.ipf.commons.ihe.fhir.translation.ToFhirTranslator; 23 | import org.openehealth.ipf.commons.ihe.xds.core.responses.Response; 24 | import org.openehealth.ipf.commons.ihe.xds.core.responses.Status; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.stereotype.Component; 27 | 28 | import java.util.Map; 29 | 30 | @Component 31 | public class Iti67FromIti57ResponseConverter extends BaseResponseConverter implements ToFhirTranslator { 32 | 33 | private Config config; 34 | 35 | @Autowired 36 | public Iti67FromIti57ResponseConverter(final Config config) { 37 | this.config = config; 38 | } 39 | 40 | /** 41 | * convert ITI-57 response to ITI-67 response 42 | */ 43 | @Override 44 | public Object translateToFhir(Response input, Map parameters) { 45 | if (input.getStatus().equals(Status.SUCCESS)) { 46 | MethodOutcome methodOutcome = new MethodOutcome(); 47 | methodOutcome.setResponseStatusCode(200); 48 | return methodOutcome; 49 | } else { 50 | processError(input); 51 | return null; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti93/Iti93AuditDataset.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.pmir.iti93; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import org.hl7.fhir.r4.model.Identifier; 23 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirAuditDataset; 24 | 25 | import lombok.Getter; 26 | import lombok.Setter; 27 | 28 | /** 29 | * Audit dataset for ITI-93 transaction 30 | * @author alexander kreutz 31 | * 32 | */ 33 | public class Iti93AuditDataset extends FhirAuditDataset { 34 | 35 | // Document manifest unique ID 36 | @Getter @Setter 37 | private String eventUri; 38 | 39 | @Getter @Setter 40 | private String messageHeaderId; 41 | 42 | @Getter 43 | private List patients = new ArrayList(); 44 | 45 | public Iti93AuditDataset() { 46 | super(true); 47 | } 48 | 49 | 50 | // public void enrichDatasetFromDocumentManifest(DocumentManifest documentManifest) { 51 | /*var reference = documentManifest.getSubject(); 52 | getPatientIds().add(reference.getResource() != null ? 53 | reference.getResource().getIdElement().getValue() : 54 | reference.getReference()); 55 | 56 | if (!documentManifest.getIdentifier().isEmpty()) { 57 | this.documentManifestUuid = documentManifest.getIdentifier().get(0).getValue(); 58 | }*/ 59 | //} 60 | } -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/iti104/Iti104AuditDataset.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.pmir.iti104; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import org.hl7.fhir.r4.model.Identifier; 23 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirAuditDataset; 24 | 25 | import lombok.Getter; 26 | import lombok.Setter; 27 | 28 | /** 29 | * Audit dataset for ITI-104 transaction 30 | * @author alexander kreutz 31 | * 32 | */ 33 | public class Iti104AuditDataset extends FhirAuditDataset { 34 | 35 | // Document manifest unique ID 36 | @Getter @Setter 37 | private String eventUri; 38 | 39 | @Getter @Setter 40 | private String messageHeaderId; 41 | 42 | @Getter 43 | private List patients = new ArrayList(); 44 | 45 | public Iti104AuditDataset() { 46 | super(true); 47 | } 48 | 49 | 50 | // public void enrichDatasetFromDocumentManifest(DocumentManifest documentManifest) { 51 | /*var reference = documentManifest.getSubject(); 52 | getPatientIds().add(reference.getResource() != null ? 53 | reference.getResource().getIdElement().getValue() : 54 | reference.getReference()); 55 | 56 | if (!documentManifest.getIdentifier().isEmpty()) { 57 | this.documentManifestUuid = documentManifest.getIdentifier().get(0).getValue(); 58 | }*/ 59 | //} 60 | } -------------------------------------------------------------------------------- /angular/src/app/upload/upload.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ChangeDetectionStrategy, 3 | Component, 4 | EventEmitter, 5 | Output, 6 | } from '@angular/core'; 7 | 8 | export interface IDroppedBlob { 9 | blob: Blob; 10 | name: string; 11 | contentType: string; 12 | } 13 | 14 | @Component({ 15 | selector: 'app-upload', 16 | templateUrl: './upload.component.html', 17 | styleUrls: ['./upload.component.scss'], 18 | changeDetection: ChangeDetectionStrategy.OnPush, 19 | }) 20 | export class UploadComponent { 21 | @Output() addFiles = new EventEmitter(); 22 | 23 | dragCounter = 0; 24 | 25 | checkStatus(response): boolean { 26 | if (!response.ok) { 27 | throw new Error(`HTTP ${response.status} - ${response.statusText}`); 28 | } 29 | return response; 30 | } 31 | 32 | onDrop(ev) { 33 | // Prevent default behavior (Prevent file from being opened) 34 | ev.preventDefault(); 35 | this.dragCounter = 0; 36 | const files = ev.target.files || ev.dataTransfer.items; 37 | if (files) { 38 | for (let i = 0; i < files.length; i++) { 39 | // If dropped items aren't files, reject them 40 | if (files[i].kind === undefined || files[i].kind === 'file') { 41 | const file = files[i].getAsFile ? files[i].getAsFile() : files[i]; 42 | this.addFiles.emit({ name: file.name, contentType: '', blob: file }); 43 | } 44 | if (files[i].kind === 'string' || files[i].kind === 'text/uri-list') { 45 | var url = ev.dataTransfer.getData('URL'); 46 | this.fetchData(url); 47 | } 48 | } 49 | } 50 | } 51 | 52 | async fetchData(url: string) { 53 | const res = await fetch(url, { cache: 'no-store' }); 54 | const contentType = res.headers.get('Content-Type'); 55 | const blob = await res.blob(); 56 | this.addFiles.emit({ name: url, contentType, blob }); 57 | } 58 | 59 | onDragOver(ev: DragEvent) { 60 | ev.preventDefault(); 61 | } 62 | 63 | onDragEnter() { 64 | this.dragCounter++; 65 | } 66 | 67 | onDragLeave() { 68 | this.dragCounter--; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/MySAMLContextProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.xua; 18 | 19 | import org.opensaml.saml2.metadata.IDPSSODescriptor; 20 | import org.opensaml.saml2.metadata.provider.MetadataProviderException; 21 | import org.springframework.security.saml.context.SAMLContextProviderLB; 22 | import org.springframework.security.saml.context.SAMLMessageContext; 23 | 24 | public class MySAMLContextProvider extends SAMLContextProviderLB { 25 | 26 | public MySAMLContextProvider(final String serverName, final String contextPath) { 27 | this.setScheme("https"); 28 | this.setServerName(serverName); 29 | this.setContextPath(contextPath); 30 | } 31 | 32 | protected void populatePeerEntityId(final SAMLMessageContext context) throws MetadataProviderException { 33 | String localEntityId = context.getLocalEntityId(); 34 | 35 | if (localEntityId != null && localEntityId.contains("/alias/")) { 36 | localEntityId = localEntityId.substring(localEntityId.lastIndexOf("/alias/") + 7); 37 | } 38 | String peerEntityId = this.metadata.getEntityIdForAlias(localEntityId + "idp"); 39 | if (peerEntityId == null) { 40 | peerEntityId = this.metadata.getEntityIdForAlias(this.metadata.getDefaultIDP()); 41 | } 42 | 43 | context.setPeerEntityId(peerEntityId); 44 | context.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/iti68/Iti68RequestConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.mhd.iti68; 18 | 19 | import java.util.Map; 20 | 21 | import org.apache.camel.Headers; 22 | import org.openehealth.ipf.commons.ihe.xds.core.metadata.DocumentEntry; 23 | import org.openehealth.ipf.commons.ihe.xds.core.requests.RetrieveDocumentSet; 24 | 25 | import ch.bfh.ti.i4mi.mag.BaseRequestConverter; 26 | 27 | /** 28 | * ITI-68 to ITI-43 request converter 29 | * @author alexander kreutz 30 | * 31 | */ 32 | public class Iti68RequestConverter extends BaseRequestConverter { 33 | 34 | 35 | public static RetrieveDocumentSet queryParameterToRetrieveDocumentSet(@Headers Map parameters) { 36 | 37 | RetrieveDocumentSet retrieveDocumentSet = new RetrieveDocumentSet(); 38 | DocumentEntry documentEntry = new DocumentEntry(); 39 | if (parameters.containsKey("repositoryUniqueId")) { 40 | documentEntry.setRepositoryUniqueId(parameters.getOrDefault("repositoryUniqueId", "").toString()); 41 | } 42 | if (parameters.containsKey("uniqueId")) { 43 | documentEntry.setUniqueId(parameters.getOrDefault("uniqueId", "").toString()); 44 | } 45 | // documentEntry.setHomeCommunityId(""); 46 | retrieveDocumentSet.addReferenceTo(documentEntry); 47 | 48 | return retrieveDocumentSet; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/ListIDPRouteBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.xua; 18 | 19 | import java.util.Map; 20 | 21 | import org.apache.camel.Exchange; 22 | import org.apache.camel.builder.RouteBuilder; 23 | import org.apache.camel.util.json.JsonArray; 24 | import org.apache.camel.util.json.JsonObject; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.beans.factory.annotation.Qualifier; 27 | import org.springframework.stereotype.Component; 28 | 29 | @Component 30 | public class ListIDPRouteBuilder extends RouteBuilder { 31 | 32 | @Override 33 | public void configure() throws Exception { 34 | from("servlet://idps?httpMethodRestrict=GET").routeId("get-idps") 35 | .bean(ListIDPRouteBuilder.class, "listIDPs") 36 | .setHeader("Cache-Control", constant("no-store")) 37 | .setHeader("Pragma", constant("no-cache")) 38 | .marshal().json(); 39 | } 40 | 41 | @Autowired 42 | @Qualifier("idps") 43 | Map idps; 44 | 45 | public JsonArray listIDPs() { 46 | JsonArray result = new JsonArray(); 47 | 48 | for (Map.Entry idpDef : idps.entrySet()) { 49 | JsonObject idp = new JsonObject(); 50 | idp.put("id", idpDef.getKey()); 51 | String name = idpDef.getValue().getName(); 52 | if (name == null) name = idpDef.getKey(); 53 | idp.put("name", name); 54 | result.add(idp); 55 | } 56 | 57 | return result; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /angular/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for the Reflect API. */ 38 | // import 'core-js/es6/reflect'; 39 | 40 | /** Evergreen browsers require these. **/ 41 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 42 | 43 | /*************************************************************************************************** 44 | * Zone JS is required by default for Angular itself. 45 | */ 46 | import 'zone.js/dist/zone'; // Included with Angular CLI. 47 | 48 | /*************************************************************************************************** 49 | * APPLICATION IMPORTS 50 | */ 51 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti67_v401/Iti67AuditStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.openehealth.ipf.commons.ihe.fhir.iti67_v401; 17 | 18 | import org.openehealth.ipf.commons.audit.AuditContext; 19 | import org.openehealth.ipf.commons.audit.model.AuditMessage; 20 | import org.openehealth.ipf.commons.ihe.core.atna.event.QueryInformationBuilder; 21 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditStrategy; 23 | import org.openehealth.ipf.commons.ihe.fhir.audit.codes.FhirEventTypeCode; 24 | import org.openehealth.ipf.commons.ihe.fhir.audit.codes.FhirParticipantObjectIdTypeCode; 25 | 26 | /** 27 | * @author Christian Ohr 28 | * @since 3.6 29 | */ 30 | public class Iti67AuditStrategy extends FhirQueryAuditStrategy { 31 | 32 | public Iti67AuditStrategy(boolean serverSide) { 33 | super(serverSide); 34 | } 35 | 36 | @Override 37 | public AuditMessage[] makeAuditMessage(AuditContext auditContext, FhirQueryAuditDataset auditDataset) { 38 | return new QueryInformationBuilder(auditContext, auditDataset, FhirEventTypeCode.MobileDocumentReferenceQuery) 39 | .addPatients(auditDataset.getPatientIds()) 40 | .setQueryParameters("MobileDocumentReferenceQuery", 41 | FhirParticipantObjectIdTypeCode.MobileDocumentReferenceQuery, 42 | auditDataset.getQueryString()) 43 | .getMessages(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti65_v401/Iti65ServerAuditStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.openehealth.ipf.commons.ihe.fhir.iti65_v401; 18 | 19 | import org.openehealth.ipf.commons.audit.AuditContext; 20 | import org.openehealth.ipf.commons.audit.codes.ParticipantObjectIdTypeCode; 21 | import org.openehealth.ipf.commons.audit.codes.ParticipantObjectTypeCodeRole; 22 | import org.openehealth.ipf.commons.audit.model.AuditMessage; 23 | import org.openehealth.ipf.commons.ihe.core.atna.event.PHIImportBuilder; 24 | import org.openehealth.ipf.commons.ihe.fhir.audit.codes.FhirEventTypeCode; 25 | 26 | import java.util.Collections; 27 | 28 | /** 29 | * @author Christian Ohr 30 | * @since 3.6 31 | */ 32 | public class Iti65ServerAuditStrategy extends Iti65AuditStrategy { 33 | 34 | public Iti65ServerAuditStrategy() { 35 | super(true); 36 | } 37 | 38 | @Override 39 | public AuditMessage[] makeAuditMessage(AuditContext auditContext, Iti65AuditDataset auditDataset) { 40 | return new PHIImportBuilder<>(auditContext, auditDataset, FhirEventTypeCode.ProvideDocumentBundle) 41 | .setPatient(auditDataset.getPatientId()) 42 | .addImportedEntity( 43 | auditDataset.getDocumentManifestUuid(), 44 | ParticipantObjectIdTypeCode.XdsMetadata, 45 | ParticipantObjectTypeCodeRole.Job, 46 | Collections.emptyList()) 47 | .getMessages(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti66_v401/Iti66AuditStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.openehealth.ipf.commons.ihe.fhir.iti66_v401; 17 | 18 | import org.openehealth.ipf.commons.audit.AuditContext; 19 | import org.openehealth.ipf.commons.audit.model.AuditMessage; 20 | import org.openehealth.ipf.commons.ihe.core.atna.event.QueryInformationBuilder; 21 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditStrategy; 23 | import org.openehealth.ipf.commons.ihe.fhir.audit.codes.FhirEventTypeCode; 24 | import org.openehealth.ipf.commons.ihe.fhir.audit.codes.FhirParticipantObjectIdTypeCode; 25 | 26 | 27 | /** 28 | * @author Christian Ohr 29 | * @since 3.6 30 | */ 31 | public class Iti66AuditStrategy extends FhirQueryAuditStrategy { 32 | 33 | public Iti66AuditStrategy(boolean serverSide) { 34 | super(serverSide); 35 | } 36 | 37 | 38 | @Override 39 | public AuditMessage[] makeAuditMessage(AuditContext auditContext, FhirQueryAuditDataset auditDataset) { 40 | return new QueryInformationBuilder<>(auditContext, auditDataset, FhirEventTypeCode.MobileDocumentManifestQuery) 41 | .addPatients(auditDataset.getPatientIds()) 42 | .setQueryParameters("MobileDocumentManifestQuery", 43 | FhirParticipantObjectIdTypeCode.MobileDocumentManifestQuery, 44 | auditDataset.getQueryString()) 45 | .getMessages(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/openehealth/ipf/commons/ihe/fhir/iti67_v401/Iti67TransactionConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.openehealth.ipf.commons.ihe.fhir.iti67_v401; 17 | 18 | import ca.uhn.fhir.context.FhirVersionEnum; 19 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionConfiguration; 20 | import org.openehealth.ipf.commons.ihe.fhir.FhirTransactionValidator; 21 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 22 | import org.openehealth.ipf.commons.ihe.fhir.iti67_v401.Iti67AuditStrategy; 23 | import org.openehealth.ipf.commons.ihe.fhir.iti67_v401.Iti67ClientRequestFactory; 24 | import org.openehealth.ipf.commons.ihe.fhir.iti67_v401.Iti67ResourceProvider; 25 | 26 | /** 27 | * Standard Configuration for Iti67Component. Supports lazy-loading by default. 28 | * 29 | * @author Christian Ohr 30 | * @since 3.6 31 | */ 32 | public class Iti67TransactionConfiguration extends FhirTransactionConfiguration { 33 | 34 | public Iti67TransactionConfiguration() { 35 | super("mhd-iti67-v401", 36 | "Find Document References", 37 | true, 38 | new Iti67AuditStrategy(false), 39 | new Iti67AuditStrategy(true), 40 | FhirVersionEnum.R4, 41 | new Iti67ResourceProvider(), // Consumer side. accept registrations 42 | new Iti67ClientRequestFactory(), 43 | FhirTransactionValidator.NO_VALIDATION); 44 | setSupportsLazyLoading(true); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/MagConstants.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag; 2 | 3 | import lombok.experimental.UtilityClass; 4 | 5 | @UtilityClass 6 | public class MagConstants { 7 | 8 | @UtilityClass 9 | public static class FhirExtensionUrls { 10 | private static final String MHD_PREFIX = "https://profiles.ihe.net/ITI/MHD/StructureDefinition/"; 11 | private static final String CH_PREFIX = "http://fhir.ch/ig/ch-epr-fhir/"; 12 | 13 | // standard MHD extensions 14 | public static final String REPOSITORY_UNIQUE_ID = MHD_PREFIX + "ihe-repositoryUniqueId"; 15 | public static final String DOCUMENT_ENTRY_VERSION = MHD_PREFIX + "ihe-version"; 16 | public static final String DOCUMENT_AVAILABILITY = MHD_PREFIX + "ihe-documentAvailability"; 17 | 18 | // Swiss EPR specific extensions 19 | public static final String CH_AUTHOR_ROLE = CH_PREFIX + "ch-ext-author-authorrole"; 20 | public static final String CH_DELETION_STATUS = CH_PREFIX + "ch-ext-deletionstatus"; 21 | } 22 | 23 | @UtilityClass 24 | public static class XdsExtraMetadataSlotNames { 25 | // Swiss EPR specific extra XDS metadata 26 | public static final String CH_ORIGINAL_PROVIDER_ROLE = "urn:e-health-suisse:2020:originalProviderRole"; 27 | public static final String CH_DELETION_STATUS = "urn:e-health-suisse:2019:deletionStatus"; 28 | } 29 | 30 | // TODO: Move further string literals here 31 | @UtilityClass 32 | public static class FhirCodingSystemIds { 33 | public static final String RFC_3986 = "urn:ietf:rfc:3986"; 34 | public static final String MHD_DOCUMENT_ID_TYPE = "https://profiles.ihe.net/ITI/MHD/CodeSystem/DocumentIdentifierTypes"; 35 | } 36 | 37 | @UtilityClass 38 | public static class DeletionStatuses { 39 | private static final String PREFIX = "urn:e-health-suisse:2019:deletionStatus:"; 40 | public static final String NOT_REQUESTED = PREFIX + "deletionNotRequested"; 41 | public static final String REQUESTED = PREFIX + "deletionRequested"; 42 | public static final String PROHIBITED = PREFIX + "deletionProhibited"; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /.github/workflows/publish_docker.yml: -------------------------------------------------------------------------------- 1 | name: Build and Upload to Google Artifact registry 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "*" 8 | 9 | env: 10 | PROJECT_ID: ahdis-ch 11 | GAR_LOCATION: europe-west6 12 | REPOSITORY: ahdis 13 | IMAGE: mag 14 | 15 | jobs: 16 | setup-build-publish-deploy: 17 | name: Setup, Build, Publish, and Deploy 18 | runs-on: ubuntu-latest 19 | environment: production 20 | 21 | permissions: 22 | contents: "read" 23 | id-token: "write" 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Build Java 30 | uses: actions/setup-java@v3 31 | with: 32 | java-version: "17" 33 | distribution: "adopt" 34 | cache: "maven" 35 | - run: mvn --batch-mode --update-snapshots verify 36 | 37 | - name: Set up QEMU 38 | uses: docker/setup-qemu-action@v1 39 | 40 | - name: Set up Docker Buildx 41 | uses: docker/setup-buildx-action@v1 42 | 43 | # Configure Workload Identity Federation and generate an access token. 44 | - id: "auth" 45 | name: "Authenticate to Google Cloud" 46 | uses: "google-github-actions/auth@v1" 47 | with: 48 | token_format: "access_token" 49 | workload_identity_provider: "projects/1022310475153/locations/global/workloadIdentityPools/github-wif-pool/providers/oidc-github-provider" 50 | service_account: "github@ahdis-ch.iam.gserviceaccount.com" 51 | 52 | - name: Docker configuration 53 | run: |- 54 | echo ${{steps.auth.outputs.access_token}} | docker login -u oauth2accesstoken --password-stdin https://$GAR_LOCATION-docker.pkg.dev 55 | 56 | # Build the Docker image for arm and amd 57 | - name: Build 58 | run: |- 59 | docker buildx build \ 60 | --tag "$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE:$GITHUB_REF_NAME" \ 61 | --build-arg GITHUB_SHA="$GITHUB_SHA" \ 62 | --build-arg GITHUB_REF="$GITHUB_REF" \ 63 | --push \ 64 | --platform=linux/arm64,linux/amd64 \ 65 | -f Dockerfile \ 66 | . 67 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/xua/TokenRenew.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.xua; 18 | 19 | import org.apache.camel.Body; 20 | import org.apache.camel.ExchangeProperty; 21 | import org.apache.camel.Header; 22 | import org.opensaml.xml.util.XMLHelper; 23 | import org.springframework.stereotype.Component; 24 | import org.w3c.dom.Node; 25 | 26 | import lombok.extern.slf4j.Slf4j; 27 | 28 | @Component 29 | @Slf4j 30 | public class TokenRenew { 31 | 32 | public AssertionRequest buildAssertionRequest(final @Header("assertionRequest") AssertionRequest assertionRequest, 33 | final @Body String renewedIdpAssertion) { 34 | assertionRequest.setSamlToken(renewedIdpAssertion); 35 | return assertionRequest; 36 | } 37 | 38 | public AuthenticationRequest emptyAuthRequest() { 39 | return new AuthenticationRequest(); 40 | } 41 | 42 | public AssertionRequest keepIdpAssertion(final @ExchangeProperty("oauthrequest") AuthenticationRequest authRequest, 43 | final @Body AssertionRequest assertionRequest) { 44 | final String idpAssertion; 45 | if (assertionRequest.getSamlToken() instanceof String) { 46 | idpAssertion = (String) assertionRequest.getSamlToken(); 47 | } else { 48 | idpAssertion = XMLHelper.nodeToString((Node) assertionRequest.getSamlToken()); 49 | } 50 | authRequest.setIdpAssertion(idpAssertion); 51 | return assertionRequest; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/pharm5/Pharm5AuditStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package ch.bfh.ti.i4mi.mag.mhd.pharm5; 17 | 18 | import org.openehealth.ipf.commons.audit.AuditContext; 19 | import org.openehealth.ipf.commons.audit.model.AuditMessage; 20 | import org.openehealth.ipf.commons.ihe.core.atna.event.QueryInformationBuilder; 21 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditDataset; 22 | import org.openehealth.ipf.commons.ihe.fhir.audit.FhirQueryAuditStrategy; 23 | import org.openehealth.ipf.commons.ihe.fhir.audit.codes.FhirEventTypeCode; 24 | import org.openehealth.ipf.commons.ihe.fhir.audit.codes.FhirParticipantObjectIdTypeCode; 25 | 26 | /** 27 | * Strategy for auditing Pharm5AuditStrategy 28 | * TODO: not specified yet by spec 29 | * 30 | * @author Oliver Eggrer 31 | */ 32 | public class Pharm5AuditStrategy extends FhirQueryAuditStrategy { 33 | 34 | public Pharm5AuditStrategy(boolean serverSide) { 35 | super(serverSide); 36 | } 37 | 38 | @Override 39 | public AuditMessage[] makeAuditMessage(AuditContext auditContext, FhirQueryAuditDataset auditDataset) { 40 | return new QueryInformationBuilder<>(auditContext, auditDataset, FhirEventTypeCode.MobilePatientIdentifierCrossReferenceQuery) 41 | .addPatients(auditDataset.getPatientIds()) 42 | .setQueryParameters( 43 | "find-medication-list", 44 | FhirParticipantObjectIdTypeCode.MobileDocumentReferenceQuery, 45 | auditDataset.getQueryString()) 46 | 47 | .getMessages(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/mhd/iti66/IdRequestConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ch.bfh.ti.i4mi.mag.mhd.iti66; 18 | 19 | import org.apache.camel.Header; 20 | import org.openehealth.ipf.commons.ihe.xds.core.requests.QueryRegistry; 21 | import org.openehealth.ipf.commons.ihe.xds.core.requests.query.GetSubmissionSetAndContentsQuery; 22 | import org.openehealth.ipf.commons.ihe.xds.core.requests.query.QueryReturnType; 23 | 24 | import ch.bfh.ti.i4mi.mag.BaseRequestConverter; 25 | 26 | /** 27 | * DocumentManifest id to GetSubmissionSetAndContentsQuery converter 28 | * 29 | * @author oliver egger 30 | * 31 | */ 32 | public class IdRequestConverter extends BaseRequestConverter { 33 | 34 | /** 35 | * convert DocumentManifest id to GetSubmissionSetAndContentsQuery converter 36 | * 37 | * @param fhirHttpUri MAG defines uniqueId as FHIR id 38 | * @return 39 | */ 40 | public QueryRegistry idToGetDocumentsQuery(@Header(value = "FhirHttpUri") String fhirHttpUri) { 41 | 42 | if (fhirHttpUri != null && fhirHttpUri.contains("/")) { 43 | boolean getLeafClass = true; 44 | String uuid = fhirHttpUri.substring(fhirHttpUri.lastIndexOf("/") + 1); 45 | GetSubmissionSetAndContentsQuery query = new GetSubmissionSetAndContentsQuery(); 46 | final QueryRegistry queryRegistry = new QueryRegistry(query); 47 | query.setUuid(uuid); 48 | queryRegistry.setReturnType((getLeafClass) ? QueryReturnType.LEAF_CLASS : QueryReturnType.OBJECT_REF); 49 | return queryRegistry; 50 | } 51 | return null; 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/java/ch/bfh/ti/i4mi/mag/pmir/Test.java: -------------------------------------------------------------------------------- 1 | package ch.bfh.ti.i4mi.mag.pmir; 2 | 3 | import org.apache.camel.Body; 4 | 5 | public class Test { 6 | 7 | public String getTest(@Body Object test) { 8 | 9 | return "\n" + 10 | "\n" + 11 | " \n" + 12 | " \n" + 13 | " \n" + 14 | " \n" + 15 | " \n" + 16 | " \n" + 17 | " \n" + 18 | " \n" + 19 | " \n" + 20 | " \n" + 21 | " \n" + 22 | " \n" + 23 | " \n" + 24 | " \n" + 25 | " \n" + 26 | " \n" + 27 | " \n" + 28 | " \n" + 29 | " \n" + 30 | " \n" + 31 | " \n" + 32 | " \n" + 33 | " \n" + 34 | " \n" + 35 | " \n" + 36 | " \n" + 37 | " Patient.id\n" + 38 | " \n" + 39 | " \n" + 40 | " \n" + 41 | " \n" + 42 | ""; 43 | 44 | 45 | } 46 | } 47 | --------------------------------------------------------------------------------