Skip to content

Commit 521ce2e

Browse files
committed
2 parents 9b06be4 + 00987b0 commit 521ce2e

28 files changed

+1203
-32
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
openmrs-module-smartonfhir
44
==========================
5-
[![Build Status](https://travis-ci.com/openmrs/openmrs-module-smartonfhir.svg?branch=master)](https://travis-ci.com/openmrs/openmrs-module-smartonfhir)
5+
[![Build Status](https://github.com/openmrs/openmrs-module-smartonfhir/actions/workflows/main.yml/badge.svg)](https://github.com/openmrs/openmrs-module-smartonfhir/actions/workflows/main.yml)
66
[![codecov](https://codecov.io/gh/openmrs/openmrs-module-smartonfhir/branch/master/graph/badge.svg)](https://codecov.io/gh/openmrs/openmrs-module-smartonfhir)
77

88
Description

omod/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@
7676
<version>${appuiVersion}</version>
7777
<scope>test</scope>
7878
</dependency>
79+
<dependency>
80+
<groupId>com.github.ben-manes.caffeine</groupId>
81+
<artifactId>caffeine</artifactId>
82+
<scope>provided</scope>
83+
</dependency>
84+
<dependency>
85+
<groupId>org.openmrs.module</groupId>
86+
<artifactId>fhir2-omod</artifactId>
87+
</dependency>
88+
<dependency>
89+
<groupId>org.openmrs.module</groupId>
90+
<artifactId>emrapi-api</artifactId>
91+
</dependency>
7992
</dependencies>
8093

8194
<build>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.model;
11+
12+
import lombok.Data;
13+
14+
@Data
15+
public class SmartSession {
16+
17+
private String visitUuid;
18+
19+
private String patientUuid;
20+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.page.controller;
11+
12+
import java.io.UnsupportedEncodingException;
13+
import java.net.URLEncoder;
14+
import java.nio.charset.StandardCharsets;
15+
import java.util.HashMap;
16+
import java.util.List;
17+
import java.util.Map;
18+
19+
import org.openmrs.Patient;
20+
import org.openmrs.Visit;
21+
import org.openmrs.VisitType;
22+
import org.openmrs.api.VisitService;
23+
import org.openmrs.api.context.Context;
24+
import org.openmrs.module.appframework.domain.AppDescriptor;
25+
import org.openmrs.module.appui.UiSessionContext;
26+
import org.openmrs.module.coreapps.CoreAppsConstants;
27+
import org.openmrs.module.coreapps.utils.VisitTypeHelper;
28+
import org.openmrs.module.emrapi.adt.AdtService;
29+
import org.openmrs.ui.framework.annotation.SpringBean;
30+
import org.openmrs.ui.framework.page.PageModel;
31+
import org.springframework.web.bind.annotation.RequestParam;
32+
33+
public class FindVisitPageController {
34+
35+
public String get(UiSessionContext sessionContext, PageModel model, @RequestParam("app") AppDescriptor app,
36+
@SpringBean AdtService service, @SpringBean("visitService") VisitService visitService,
37+
@RequestParam("patientId") String patientId, @RequestParam("token") String token,
38+
UiSessionContext uiSessionContext, @SpringBean("visitTypeHelper") VisitTypeHelper visitTypeHelper)
39+
throws UnsupportedEncodingException {
40+
41+
Patient patient = Context.getPatientService().getPatientByUuid(patientId);
42+
43+
List<Visit> activeVisits = Context.getVisitService().getVisitsByPatient(patient);
44+
model.addAttribute("visitSummaries", activeVisits);
45+
46+
model.addAttribute("canViewVisits", Context.hasPrivilege(CoreAppsConstants.PRIVILEGE_PATIENT_VISITS));
47+
48+
Map<Integer, Object> visitTypesWithAttr = new HashMap<Integer, Object>();
49+
50+
List<VisitType> allVisitTypes = visitService.getAllVisitTypes();
51+
for (VisitType type : allVisitTypes) {
52+
Map<String, Object> typeAttr = visitTypeHelper.getVisitTypeColorAndShortName(type);
53+
visitTypesWithAttr.put(type.getVisitTypeId(), typeAttr);
54+
}
55+
56+
model.addAttribute("visitTypesWithAttr", visitTypesWithAttr);
57+
58+
String afterSelectedUrl = app.getConfig().get("afterSelectedUrl").getTextValue();
59+
afterSelectedUrl = afterSelectedUrl.replace("{{patient.uuid}}", patientId).replace("{{token}}",
60+
URLEncoder.encode(token, StandardCharsets.UTF_8.name()));
61+
model.addAttribute("afterSelectedUrl", afterSelectedUrl);
62+
63+
return null;
64+
}
65+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.page.controller;
11+
12+
import org.openmrs.module.appframework.domain.AppDescriptor;
13+
import org.openmrs.ui.framework.page.Redirect;
14+
import org.springframework.web.bind.annotation.RequestParam;
15+
16+
public class SmartAppsRedirectPageController {
17+
18+
public Redirect get(@RequestParam(value = "app") AppDescriptor app,
19+
@RequestParam(required = false, value = "patientId") String patientId,
20+
@RequestParam(required = false, value = "visitId") String visitId) {
21+
22+
String launchUrl = app.getConfig().get("launchUrl").getTextValue();
23+
String launchType = app.getConfig().get("launchType").getTextValue();
24+
String launchContext = app.getConfig().get("launchContext").getTextValue();
25+
String fhirVersion = app.getConfig().get("fhirVersion").getTextValue();
26+
27+
// For EHR launch
28+
if (launchType.equals("EHR")) {
29+
return new Redirect("ms/smartEhrLaunchServlet?launchUrl=" + launchUrl + "&patientId=" + patientId + "&visitId="
30+
+ visitId + "&launchContext=" + launchContext + "&fhirVersion=" + fhirVersion);
31+
}
32+
33+
// For Standalone launch
34+
if (launchType.equals("standalone")) {
35+
return new Redirect("ms/smartAppSelectorServlet?launchUrl=" + launchUrl + "&fhirVersion=" + fhirVersion);
36+
}
37+
38+
return new Redirect("ms/smartAppSelectorServlet?launchUrl=");
39+
}
40+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.util;
11+
12+
import javax.servlet.http.HttpServletRequest;
13+
14+
import ca.uhn.fhir.rest.server.IServerAddressStrategy;
15+
import org.openmrs.api.context.Context;
16+
17+
public class FhirBaseAddressStrategy {
18+
19+
private static final String DEFAULT_FHIR_VERSION = "R4";
20+
21+
public String getBaseSmartLaunchAddress(HttpServletRequest request) {
22+
IServerAddressStrategy iServerAddressStrategy = Context.getRegisteredComponent("openmrsFhirAddressStrategy",
23+
IServerAddressStrategy.class);
24+
String baseURL = iServerAddressStrategy.determineServerBase(request.getServletContext(), request);
25+
String smartAppLaunchURL = request.getParameter("launchUrl");
26+
27+
if (!(baseURL.contains("R4") || baseURL.contains("R3"))) {
28+
String fhirVersion = request.getParameter("fhirVersion");
29+
if (fhirVersion == null) {
30+
fhirVersion = DEFAULT_FHIR_VERSION;
31+
}
32+
baseURL = baseURL + fhirVersion;
33+
}
34+
35+
String url = smartAppLaunchURL + "?iss=" + baseURL + "&launch=";
36+
37+
return url;
38+
}
39+
}

omod/src/main/java/org/openmrs/module/smartonfhir/util/SmartSecretKeyHolder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,17 @@ private static void loadSecretKey() {
6767
try (InputStream secretKeyStream = resource.getInputStream()) {
6868
secretKey = decoder
6969
.decode(objectMapper.readValue(secretKeyStream, SmartSecretKey.class).getSmartSharedSecretKey());
70+
return;
7071
}
7172
}
73+
74+
InputStream secretKeyStream = SmartSecretKeyHolder.class.getClassLoader()
75+
.getResourceAsStream("smart-secret-key.json");
76+
77+
if (secretKeyStream != null) {
78+
secretKey = decoder
79+
.decode(objectMapper.readValue(secretKeyStream, SmartSecretKey.class).getSmartSharedSecretKey());
80+
return;
81+
}
7282
}
7383
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.util;
11+
12+
import java.util.concurrent.TimeUnit;
13+
14+
import com.github.benmanes.caffeine.cache.Caffeine;
15+
import com.github.benmanes.caffeine.cache.LoadingCache;
16+
import org.openmrs.module.smartonfhir.model.SmartSession;
17+
18+
public class SmartSessionCache {
19+
20+
private static LoadingCache<String, SmartSession> cache;
21+
22+
public SmartSessionCache() {
23+
if (cache == null) {
24+
cache = Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).maximumSize(500).recordStats()
25+
.build(key -> null);
26+
}
27+
}
28+
29+
public boolean put(String key, SmartSession value) {
30+
cache.put(key, value);
31+
return Boolean.TRUE;
32+
}
33+
34+
public SmartSession get(String key) {
35+
try {
36+
return cache.get(key);
37+
}
38+
catch (Exception e) {
39+
return null;
40+
}
41+
}
42+
43+
public boolean clear(String key) {
44+
cache.invalidate(key);
45+
46+
return Boolean.TRUE;
47+
}
48+
}

omod/src/main/java/org/openmrs/module/smartonfhir/web/filter/SmartForwardingFilter.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,13 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
3838
return;
3939
}
4040

41-
if (request.getRequestURI().endsWith("/smartPatientSelected")) {
42-
req.getRequestDispatcher("/ms/smartPatientSelected").forward(req, res);
41+
if (request.getRequestURI().contains("/smartAccessConfirmation")) {
42+
req.getRequestDispatcher("/ms/smartAccessConfirmation").forward(req, res);
43+
return;
44+
}
45+
46+
if (request.getRequestURI().endsWith("/smartLaunchOptionSelected")) {
47+
req.getRequestDispatcher("/ms/smartLaunchOptionSelected").forward(req, res);
4348
return;
4449
}
4550

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.web.filter;
11+
12+
import javax.servlet.Filter;
13+
import javax.servlet.FilterChain;
14+
import javax.servlet.FilterConfig;
15+
import javax.servlet.ServletException;
16+
import javax.servlet.ServletRequest;
17+
import javax.servlet.ServletResponse;
18+
import javax.servlet.http.HttpServletRequest;
19+
20+
import java.io.IOException;
21+
22+
import lombok.extern.slf4j.Slf4j;
23+
import org.apache.http.client.methods.CloseableHttpResponse;
24+
import org.apache.http.client.methods.HttpGet;
25+
import org.apache.http.impl.client.CloseableHttpClient;
26+
import org.apache.http.impl.client.HttpClientBuilder;
27+
import org.keycloak.adapters.KeycloakDeploymentBuilder;
28+
import org.keycloak.common.util.KeycloakUriBuilder;
29+
import org.openmrs.module.smartonfhir.util.KeycloakConfigHolder;
30+
31+
@Slf4j
32+
public class SmartSessionLogoutFilter implements Filter {
33+
34+
private String logoutUrl = null;
35+
36+
@Override
37+
public void init(FilterConfig filterConfig) {
38+
final KeycloakUriBuilder keycloakUriBuilder = KeycloakDeploymentBuilder
39+
.build(KeycloakConfigHolder.getKeycloakConfig()).getLogoutUrl();
40+
41+
if (keycloakUriBuilder != null) {
42+
logoutUrl = keycloakUriBuilder.toTemplate();
43+
} else {
44+
log.error(
45+
"Could not find Keycloak configuration file. Please run keycloak server before openmrs to avoid this error");
46+
}
47+
}
48+
49+
@Override
50+
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
51+
throws IOException, ServletException {
52+
HttpServletRequest request = (HttpServletRequest) servletRequest;
53+
if (request.getRequestURI().contains("/logout")) {
54+
keycloakSessionLogout();
55+
}
56+
57+
filterChain.doFilter(servletRequest, servletResponse);
58+
}
59+
60+
@Override
61+
public void destroy() {
62+
63+
}
64+
65+
private void keycloakSessionLogout() throws IOException {
66+
CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().disableRedirectHandling().build();
67+
CloseableHttpResponse closeableHttpResponse = null;
68+
try {
69+
if (logoutUrl != null) {
70+
closeableHttpResponse = closeableHttpClient.execute(new HttpGet(logoutUrl));
71+
}
72+
}
73+
finally {
74+
if (closeableHttpResponse != null) {
75+
try {
76+
closeableHttpResponse.close();
77+
}
78+
finally {
79+
closeableHttpClient.close();
80+
}
81+
} else {
82+
closeableHttpClient.close();
83+
}
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)