Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/dynamic content #605

Merged
merged 20 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions configs/app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>
Greetings from the custom web app page!
</p>
14 changes: 14 additions & 0 deletions custom/about.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<p>
<b>This is a custom about page! It means you have configured 'custom_content_path: ./custom' in the application.yaml</b>
</p>
<p>
This server provides a complete implementation of the FHIR Specification
using a 100% open source software stack.
</p>
<p>
This server is built
from a number of modules of the
<a href="https://github.com/hapifhir/hapi-fhir/">HAPI FHIR</a>
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
implementation of the FHIR specification.
</p>
Binary file added custom/logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions custom/welcome.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<p>
<b>This is a custom welcome page! It means you have configured 'custom_content_path: ./custom' in the application.yaml</b>
</p>
<p>
This server provides a complete implementation of the FHIR Specification
using a 100% open source software stack.
</p>
<p>
This server is built
from a number of modules of the
<a href="https://github.com/hapifhir/hapi-fhir/">HAPI FHIR</a>
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
implementation of the FHIR specification.
</p>
41 changes: 21 additions & 20 deletions src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ public class AppProperties {
private Boolean install_transitive_ig_dependencies = true;
private Map<String, PackageInstallationSpec> implementationGuides = null;

private String staticLocation = null;

private String staticLocationPrefix = "/static";
private String custom_content_path = null;
private String app_content_path = null;

private Boolean lastn_enabled = false;
private boolean store_resource_in_lucene_index_enabled = false;
Expand All @@ -94,31 +93,16 @@ public class AppProperties {
private Integer bundle_batch_pool_max_size = 100;
private final Set<String> local_base_urls = new HashSet<>();
private final Set<String> logical_urls = new HashSet<>();

private final List<String> custom_interceptor_classes = new ArrayList<>();

public String getStaticLocationPrefix() {
return staticLocationPrefix;
}
private final List<String> custom_interceptor_classes = new ArrayList<>();

public void setStaticLocationPrefix(String staticLocationPrefix) {
this.staticLocationPrefix = staticLocationPrefix;
}


public List<String> getCustomInterceptorClasses() {
return custom_interceptor_classes;
}


public String getStaticLocation() {
return staticLocation;
}

public void setStaticLocation(String staticLocation) {
this.staticLocation = staticLocation;
}


public Boolean getOpenapi_enabled() {
return openapi_enabled;
Expand Down Expand Up @@ -575,7 +559,7 @@ public boolean getInstall_transitive_ig_dependencies() {
public void setInstall_transitive_ig_dependencies(boolean install_transitive_ig_dependencies) {
this.install_transitive_ig_dependencies = install_transitive_ig_dependencies;
}

public Integer getBundle_batch_pool_size() {
return this.bundle_batch_pool_size;
}
Expand All @@ -600,6 +584,7 @@ public Set<String> getLogical_urls() {
return logical_urls;
}


public Boolean getIg_runtime_upload_enabled() {
return ig_runtime_upload_enabled;
}
Expand All @@ -608,6 +593,22 @@ public void setIg_runtime_upload_enabled(Boolean ig_runtime_upload_enabled) {
this.ig_runtime_upload_enabled = ig_runtime_upload_enabled;
}

public String getCustom_content_path() {
return custom_content_path;
}

public void setCustom_content_path(String custom_content_path) {
this.custom_content_path = custom_content_path;
}

public String getApp_content_path() {
return app_content_path;
}

public void setApp_content_path(String app_content_path) {
this.app_content_path = app_content_path;
}

public static class Cors {
private Boolean allow_Credentials = true;
private List<String> allowed_origin = List.of("*");
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory;
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
import ca.uhn.fhir.jpa.starter.util.EnvironmentHelper;
import ca.uhn.fhir.jpa.starter.ig.IImplementationGuideOperationProvider;
import ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor;
import ca.uhn.fhir.jpa.util.ResourceCountCache;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
Expand Down Expand Up @@ -272,8 +273,7 @@ public RestfulServer restfulServer(
IPackageInstallerSvc packageInstallerSvc,
ThreadSafeResourceDeleterSvc theThreadSafeResourceDeleterSvc,
ApplicationContext appContext,
Optional<IpsOperationProvider> theIpsOperationProvider,
Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
Optional<IpsOperationProvider> theIpsOperationProvider, Optional<IImplementationGuideOperationProvider> implementationGuideOperationProvider) {
RestfulServer fhirServer = new RestfulServer(fhirSystemDao.getContext());

List<String> supportedResourceTypes = appProperties.getSupported_resource_types();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,10 @@
public interface IImplementationGuideOperationProvider {
static PackageInstallationSpec toPackageInstallationSpec(byte[] npmPackageAsByteArray) throws IOException {
NpmPackage npmPackage = NpmPackage.fromPackage(new ByteArrayInputStream(npmPackageAsByteArray));
return new PackageInstallationSpec()
.setName(npmPackage.name())
.setPackageContents(npmPackageAsByteArray)
.setVersion(npmPackage.version())
.setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL)
.setFetchDependencies(false);
return new PackageInstallationSpec().setName(npmPackage.name()).setPackageContents(npmPackageAsByteArray).setVersion(npmPackage.version()).setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL).setFetchDependencies(false);
}

// The following declaration is the one that counts but cannot be used across different versions as stating
// Base64BinaryType would bind to a separate version
// @Operation(name = "$install", typeName = "ImplementationGuide")

// The following declaration is the one that counts but cannot be used across different versions as stating Base64BinaryType would bind to a separate version
// Parameters install(@OperationParam(name = "npmContent",min = 1, max = 1) Base64BinaryType implementationGuide);

// Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) ;

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,21 @@ public ImplementationGuideR4OperationProvider(IPackageInstallerSvc packageInstal
}

@Operation(name = "$install", typeName = "ImplementationGuide")
public Parameters install(
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
try {

packageInstallerSvc.install(
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return new Parameters();
}

@Operation(name = "$uninstall", typeName = "ImplementationGuide")
public Parameters uninstall(
@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {
public Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {

packageInstallerSvc.uninstall(new PackageInstallationSpec().setName(name).setVersion(version));
return new Parameters();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,19 @@ public ImplementationGuideR5OperationProvider(IPackageInstallerSvc packageInstal
}

@Operation(name = "$install", typeName = "ImplementationGuide")
public Parameters install(
@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
public Parameters install(@OperationParam(name = "npmContent", min = 1, max = 1) Base64BinaryType implementationGuide) {
try {

packageInstallerSvc.install(
IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
packageInstallerSvc.install(IImplementationGuideOperationProvider.toPackageInstallationSpec(implementationGuide.getValue()));
} catch (IOException e) {
throw new RuntimeException(e);
}
return new Parameters();
}


@Operation(name = "$uninstall", typeName = "ImplementationGuide")
public org.hl7.fhir.r4.model.Parameters uninstall(
@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {
public org.hl7.fhir.r4.model.Parameters uninstall(@OperationParam(name = "name", min = 1, max = 1) String name, @OperationParam(name = "version", min = 1, max = 1) String version) {

packageInstallerSvc.uninstall(new PackageInstallationSpec().setName(name).setVersion(version));
return new org.hl7.fhir.r4.model.Parameters();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ca.uhn.fhir.jpa.starter.web;

import ca.uhn.fhir.jpa.starter.AppProperties;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileUrlResource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.net.MalformedURLException;

@Configuration
@ConditionalOnProperty(prefix = "hapi.fhir", name = "custom_content_path")
public class CustomContentFilesConfigurer implements WebMvcConfigurer {

public static final String CUSTOM_CONTENT = "/content";
private String customContentPath;


public CustomContentFilesConfigurer(AppProperties appProperties) {
customContentPath = appProperties.getCustom_content_path();
if (customContentPath.endsWith("/"))
customContentPath = customContentPath.substring(0, customContentPath.lastIndexOf('/'));

}


@Override
public void addResourceHandlers(@NotNull ResourceHandlerRegistry theRegistry) {
if (!theRegistry.hasMappingForPattern(CUSTOM_CONTENT + "/**")) {

try {
theRegistry.addResourceHandler(CUSTOM_CONTENT + "/**").addResourceLocations(new FileUrlResource(customContentPath));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ca.uhn.fhir.jpa.starter.web;

import ca.uhn.fhir.jpa.starter.AppProperties;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.FileUrlResource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.net.MalformedURLException;
import java.net.URI;

@Configuration
@ConditionalOnProperty(prefix = "hapi.fhir", name = "app_content_path")
public class WebAppFilesConfigurer implements WebMvcConfigurer {

public static final String WEB_CONTENT = "web";
private String appContentPath;


public WebAppFilesConfigurer(AppProperties appProperties) {
appContentPath = appProperties.getApp_content_path();
if (appContentPath.endsWith("/"))
appContentPath = appContentPath.substring(0, appContentPath.lastIndexOf('/'));

}


@Override
public void addResourceHandlers(@NotNull ResourceHandlerRegistry theRegistry) {
if (!theRegistry.hasMappingForPattern(WEB_CONTENT + "/**")) {
{
try {
theRegistry.addResourceHandler(WEB_CONTENT + "/**").addResourceLocations(new FileUrlResource(appContentPath));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
}

@Override
public void addViewControllers(@NotNull ViewControllerRegistry registry) {
String path = URI.create(appContentPath).getPath();
String lastSegment = path.substring(path.lastIndexOf('/') + 1);

registry.addViewController(WEB_CONTENT + "/" + lastSegment).setViewName("redirect:" + lastSegment + "/index.html");
registry.addViewController(WEB_CONTENT + "/" + lastSegment + "/").setViewName("redirect:index.html");

registry.setOrder(Ordered.HIGHEST_PRECEDENCE);

}
}
14 changes: 8 additions & 6 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ spring:
check-location: false
baselineOnMigrate: true
datasource:
url: 'jdbc:h2:file:./target/database/h2'
#url: jdbc:h2:mem:test_mem
#url: 'jdbc:h2:file:./target/database/h2'
url: jdbc:h2:mem:test_mem
username: sa
password: null
driverClassName: org.h2.Driver
Expand Down Expand Up @@ -76,10 +76,12 @@ hapi:
### forces the use of the https:// protocol for the returned server address.
### alternatively, it may be set using the X-Forwarded-Proto header.
# use_apache_address_strategy_https: false
### enables the server to host content like HTML, css, etc. under the url pattern of eg. /static/**
# staticLocationPrefix: /static
### the deepest folder level will be used. E.g. - if you put file:/foo/bar/bazz as value then the files are resolved under /static/bazz/**
#staticLocation: file:/foo/bar/bazz
### enables the server to overwrite defaults on HTML, css, etc. under the url pattern of eg. /content/custom **
### Folder with custom content MUST be named custom. If omitted then default content applies
#custom_content_path: ./custom
### enables the server host custom content. If e.g. the value ./configs/app is supplied then the content
### will be served under /web/app
#app_content_path: ./configs/app
### enable to set the Server URL
# server_address: http://hapi.fhir.org/baseR4
# defer_indexing_for_codesystems_of_size: 101
Expand Down
Loading
Loading