diff --git a/.gitignore b/.gitignore index cbd4fe33eaa..8170948c4af 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,7 @@ web/src/main/webapp/data/ web/src/main/webapp/doc/en web/src/main/webapp/doc/fr web/src/main/webapp/WEB-INF/data/data/resources/schemapublication + +# geonetwork-ui git project +web/src/main/geonetwork-ui/ +web/node/ diff --git a/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java b/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java index d4482cdcd7a..d991745de92 100644 --- a/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java +++ b/core/src/main/java/org/fao/geonet/kernel/setting/Settings.java @@ -161,6 +161,9 @@ public class Settings { public static final String MICROSERVICES_ENABLED = "microservices/enabled"; + public static final String GEONETWORK_UI_DATAHUB_CONFIGURATION = "geonetwork-ui/datahub/configuration"; + public static final String GEONETWORK_UI_DATAHUB_ENABLED = "geonetwork-ui/datahub/enabled"; + public static class GNSetting { private String name; private boolean nullable; diff --git a/core/src/main/java/org/fao/geonet/web/DatahubFilter.java b/core/src/main/java/org/fao/geonet/web/DatahubFilter.java new file mode 100644 index 00000000000..6c44cc63603 --- /dev/null +++ b/core/src/main/java/org/fao/geonet/web/DatahubFilter.java @@ -0,0 +1,159 @@ +package org.fao.geonet.web; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHeaders; +import org.apache.log4j.Logger; +import org.fao.geonet.ApplicationContextHolder; +import org.fao.geonet.NodeInfo; +import org.fao.geonet.domain.Source; +import org.fao.geonet.domain.SourceType; +import org.fao.geonet.kernel.setting.SettingManager; +import org.fao.geonet.kernel.setting.Settings; +import org.fao.geonet.repository.SourceRepository; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.GZIPOutputStream; + +public class DatahubFilter implements Filter { + private static final Logger log = Logger.getLogger(DatahubFilter.class); + + @Override + public void init(FilterConfig config) { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + ServletContext context = req.getServletContext(); + + String reqPath = req.getPathInfo(); + if (reqPath == null || !reqPath.matches("^/[a-zA-Z0-9_\\-]+/datahub.*")) { + chain.doFilter(request, res); + return; + } + + String isDatahubEnabled = getSettingManager().getValue(Settings.GEONETWORK_UI_DATAHUB_ENABLED); + if (!isDatahubEnabled.equals("true")) { + res.setStatus(404); + return; + } + + // a req path will be "/srv/datahub/bla/bla" + String[] parts = reqPath.split("/"); + String portalName = parts[1]; // element at i=0 is empty + + SourceRepository sourceRepository = getSourceRepository(); + Boolean datahubEnabled = false; + if (NodeInfo.DEFAULT_NODE.equals(portalName)) { + datahubEnabled = getSettingManager().getValue(Settings.GEONETWORK_UI_DATAHUB_ENABLED).equals("true"); + } else if (sourceRepository.existsByUuidAndType(portalName, SourceType.subportal)) { + datahubEnabled = sourceRepository.findOneByUuid(portalName).getDatahubEnabled(); + } + + if (!datahubEnabled) { + res.setStatus(404); + return; + } + + String filePath = Stream.of(parts).skip(2).collect(Collectors.joining("/")); + File actualFile = new File(context.getRealPath("/" + filePath)); + + // fallback to index.html if the file doesn't exist + if (!actualFile.exists()) { + actualFile = new File(context.getRealPath("/datahub/index.html")); + + // disable cache only for index.html + res.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache"); + res.setHeader(HttpHeaders.PRAGMA, "no-cache"); + res.setHeader(HttpHeaders.EXPIRES, "0"); + } + + res.setStatus(200); + String extension = FilenameUtils.getExtension(actualFile.getName()).toLowerCase(); + String contentType; + if (extension.equals("js")) { + contentType = "text/javascript; charset=UTF-8"; + } else { + contentType = Files.probeContentType(actualFile.toPath()); + } + res.setContentType(contentType); + + InputStream inStream; + + // the config is read from the settings + if (actualFile.getName().equals("default.toml")) { + inStream = readConfiguration(portalName); + } else { + inStream = new FileInputStream(actualFile); + } + OutputStream outStream = res.getOutputStream(); + + // handle gzip compression + if(req.getHeader(HttpHeaders.ACCEPT_ENCODING).contains("gzip")) { + res.setHeader(HttpHeaders.CONTENT_ENCODING, "gzip"); + outStream = new GZIPOutputStream(outStream); + } + + IOUtils.copy(inStream, outStream); + outStream.close(); + } + + private InputStream readConfiguration(String portalName) { + String configuration = getSettingManager().getValue(Settings.GEONETWORK_UI_DATAHUB_CONFIGURATION); + + if (!portalName.equals(NodeInfo.DEFAULT_NODE)) { + Source portal = getSourceRepository().findOneByUuid(portalName); + if (portal != null && !portal.getDatahubConfiguration().isEmpty()) { + configuration = portal.getDatahubConfiguration(); + } + } + + /*TomlParseResult toml = Toml.parse(configuration); + Map tomlMap = toml.toMap(); + + // Force the "gn4_api_url" field to a value including the portal name + if (!tomlMap.containsKey("global")) { + tomlMap.put("global", Map.of()); + } + Map globalSection = (Map) tomlMap.get("global"); + globalSection.put("geonetwork4_api_url", "/geonetwork/" + portalName + "/api"); + + TomlWriter tomlWriter = new TomlWriter(); + configuration = tomlWriter.write(tomlMap);*/ + + // remove url & add new one + configuration = configuration.replaceAll("\ngeonetwork4_api_url\\s?=.+", "\n") + .replace("[global]", "[global]\ngeonetwork4_api_url = \"/geonetwork/" + portalName + "/api\""); + return new ByteArrayInputStream(configuration.getBytes()); + } + + @Override + public void destroy() { + } + + private SettingManager getSettingManager() { + return ApplicationContextHolder.get().getBean(SettingManager.class); + } + private SourceRepository getSourceRepository() { + return ApplicationContextHolder.get().getBean(SourceRepository.class); + } +} diff --git a/domain/src/main/java/org/fao/geonet/domain/Source.java b/domain/src/main/java/org/fao/geonet/domain/Source.java index 7fb337745dc..791464d69f9 100644 --- a/domain/src/main/java/org/fao/geonet/domain/Source.java +++ b/domain/src/main/java/org/fao/geonet/domain/Source.java @@ -27,6 +27,7 @@ import org.fao.geonet.domain.converter.BooleanToYNConverter; import org.fao.geonet.entitylistener.SourceEntityListenerManager; import org.fao.geonet.repository.LanguageRepository; +import org.hibernate.annotations.Type; import javax.annotation.Nonnull; import javax.persistence.*; @@ -64,6 +65,9 @@ public class Source extends Localized { private Integer groupOwner; private Boolean listableInHeaderSelector = true; + private Boolean datahubEnabled = false; + private String datahubConfiguration = ""; // will use the main conf if empty + /** * Default constructor. Required by framework. */ @@ -224,6 +228,29 @@ public Source setUiConfig(String uiConfig) { return this; } + /** + * Only applies to subportal. + * + * @return + */ + public Boolean getDatahubEnabled() { + return datahubEnabled; + } + public Source setDatahubEnabled(Boolean datahubEnabled) { + this.datahubEnabled = datahubEnabled; + return this; + } + + @Lob + @Type(type = "org.hibernate.type.TextType") + public String getDatahubConfiguration() { + return datahubConfiguration; + } + public Source setDatahubConfiguration(String datahubConfiguration) { + this.datahubConfiguration = datahubConfiguration; + return this; + } + /** * Get the date that the source was created. diff --git a/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java b/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java index 5b50c543e5c..55bee35e903 100644 --- a/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java +++ b/services/src/main/java/org/fao/geonet/api/sources/SourcesApi.java @@ -327,6 +327,8 @@ private void updateSource(String sourceIdentifier, entity.setGroupOwner(source.getGroupOwner()); entity.setServiceRecord(source.getServiceRecord()); entity.setUiConfig(source.getUiConfig()); + entity.setDatahubEnabled(source.getDatahubEnabled()); + entity.setDatahubConfiguration(source.getDatahubConfiguration()); entity.setLogo(source.getLogo()); entity.setListableInHeaderSelector(source.isListableInHeaderSelector()); Map labelTranslations = source.getLabelTranslations(); diff --git a/web-ui/src/main/resources/catalog/js/admin/SourcesController.js b/web-ui/src/main/resources/catalog/js/admin/SourcesController.js index 2a6c5e86e62..746ec1939d0 100644 --- a/web-ui/src/main/resources/catalog/js/admin/SourcesController.js +++ b/web-ui/src/main/resources/catalog/js/admin/SourcesController.js @@ -133,7 +133,9 @@ filter: "", serviceRecord: null, groupOwner: null, - listableInHeaderSelector: true + listableInHeaderSelector: true, + datahubEnabled: false, + datahubConfiguration: "" }; // TODO: init labels }; diff --git a/web-ui/src/main/resources/catalog/templates/admin/settings/sources.html b/web-ui/src/main/resources/catalog/templates/admin/settings/sources.html index a0315d50b0f..85cd4e0fafc 100644 --- a/web-ui/src/main/resources/catalog/templates/admin/settings/sources.html +++ b/web-ui/src/main/resources/catalog/templates/admin/settings/sources.html @@ -177,6 +177,28 @@ displayInHeaderSwitcher

displayInHeaderSwitcher-help

+ + + +

sourceDatahubEnabled-help

+ + + +

sourceDatahubConfiguration-help

diff --git a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html index 6adfb7f93a1..f168a1b199e 100644 --- a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html +++ b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html @@ -778,6 +778,24 @@