From 5a5efd5e7ebf6aa492d8eb83765fd5df2a31380a Mon Sep 17 00:00:00 2001 From: Romuald Caplier Date: Wed, 12 Jun 2024 10:20:25 +0200 Subject: [PATCH 1/6] feat(geonetwork/web): Add datahub integration. --- .../org/fao/geonet/web/DatahubFilter.java | 77 +++++++++++++ web/get-datahub.sh | 33 ++++++ web/pom.xml | 101 ++++++++++++++++++ web/src/main/webResources/WEB-INF/web.xml | 13 +++ .../config-security-mapping.xml | 5 +- 5 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/fao/geonet/web/DatahubFilter.java create mode 100755 web/get-datahub.sh 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..77ac07591b4 --- /dev/null +++ b/core/src/main/java/org/fao/geonet/web/DatahubFilter.java @@ -0,0 +1,77 @@ +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.utils.Log; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.nio.file.Files; +import java.util.zip.GZIPOutputStream; + +public class DatahubFilter implements Filter { + private static final Logger log = Logger.getLogger(DatahubFilter.class); + final String PATH_TO_DIST_FOLDER = "/datahub"; // this is relative to the context root + + @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(); + + + File fileFromDistFolder = null; + String reqPath = req.getPathInfo(); + + + if (reqPath != null) { + // compute actual file path from requested file in the URL + String filePath = reqPath + .replace("/static", ""); + fileFromDistFolder = new File(context.getRealPath(PATH_TO_DIST_FOLDER + filePath)); + } + if (fileFromDistFolder != null && fileFromDistFolder.exists()) { + res.setStatus(200); + String extension = FilenameUtils.getExtension(fileFromDistFolder.getName()).toLowerCase(); + String contentType; + if (extension.equals("js")) { + contentType = "text/javascript; charset=UTF-8"; + } else { + contentType = Files.probeContentType(fileFromDistFolder.toPath()); + } + res.setContentType(contentType); + + // set headers for disabling cache + res.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache"); + res.setHeader(HttpHeaders.PRAGMA, "no-cache"); + res.setHeader(HttpHeaders.EXPIRES, "0"); + + InputStream inStream = new FileInputStream(fileFromDistFolder); + 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(); + + } else { + chain.doFilter(request, res); + } + } + + @Override + public void destroy() { + } +} diff --git a/web/get-datahub.sh b/web/get-datahub.sh new file mode 100755 index 00000000000..f890bc87304 --- /dev/null +++ b/web/get-datahub.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +BRANCH_NAME=$1 + +REPO_URL="git@github.com:geonetwork/geonetwork-ui.git" +DATAHUB_FOLDER="src/main/datahub" + +if [ -z "$BRANCH_NAME" ]; then + echo "get-datahub.sh Error: BRANCH_NAME is not set." + exit 1 +fi + +# Remove datahub directory if it exists +if [ -d "$DATAHUB_FOLDER" ]; then + rm -rf "$DATAHUB_FOLDER" +fi + +mkdir -p "$DATAHUB_FOLDER" + +# Create a temporary directory for cloning +TEMP_DIR=$(mktemp -d) + +# Get the current directory +CURRENT_DIR=$(pwd) + +# Clone the repository into the temporary directory +git clone --branch "$BRANCH_NAME" "$REPO_URL" "$TEMP_DIR" + +# Move the contents of the specified folder to the datahub folder +mv "$TEMP_DIR"/* "$CURRENT_DIR/$DATAHUB_FOLDER" + +# Clean up the temporary directory +rm -rf "$TEMP_DIR" diff --git a/web/pom.xml b/web/pom.xml index 11a53de7522..91f0db5c259 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -633,6 +633,106 @@ + + + + + org.codehaus.mojo + exec-maven-plugin + 3.3.0 + + + sparse-checkout + initialize + + exec + + + sh + + ${project.basedir}/get-datahub.sh + ${datahub.git.branch} + + + + + + + + + com.github.eirslett + frontend-maven-plugin + 1.15.0 + + + + install-node-and-npm + + install-node-and-npm + + + v20.12.2 + 10.7.0 + + + + + npm-install + + npm + + + install + src/main/datahub + ${basedir} + + + + + npm-build + + npm + + + + false + + + run nx -- build datahub + + src/main/datahub + ${basedir} + + + + + + + + maven-resources-plugin + 3.1.0 + + + copy-resources + generate-resources + + copy-resources + + + true + UTF-8 + ${project.build.directory}/datahub + + + src/main/datahub/dist/apps/datahub + false + + + + + + + io.github.git-commit-id @@ -1395,6 +1495,7 @@ + main ${project.version} SNAPSHOT ${basedir}/src/main/webapp diff --git a/web/src/main/webResources/WEB-INF/web.xml b/web/src/main/webResources/WEB-INF/web.xml index d75022d9890..3379aab6a8d 100644 --- a/web/src/main/webResources/WEB-INF/web.xml +++ b/web/src/main/webResources/WEB-INF/web.xml @@ -82,6 +82,19 @@ /* + + + + datahubFilter + org.fao.geonet.web.DatahubFilter + + + + datahubFilter + /srv/datahub/* + + + diff --git a/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml b/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml index 1da3e0c5fac..fa5171d30dd 100644 --- a/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml +++ b/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml @@ -89,6 +89,9 @@ pattern="/[a-zA-Z0-9_\-]+/[a-z]{2,3}/admin.config.csw.customelementset.save!?.*" access="hasAuthority('Administrator')"/> + - + From 79e32dd9fb3091add078d9fbfd627f4a8a137176 Mon Sep 17 00:00:00 2001 From: Olivia Date: Mon, 17 Jun 2024 15:38:56 +0200 Subject: [PATCH 2/6] simplify web/pom to not use a separate script, use npm ci ignore generated directories --- .gitignore | 4 ++++ web/get-datahub.sh | 33 --------------------------------- web/pom.xml | 43 ++++++++++++++++++++++++++++++------------- 3 files changed, 34 insertions(+), 46 deletions(-) delete mode 100755 web/get-datahub.sh 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/web/get-datahub.sh b/web/get-datahub.sh deleted file mode 100755 index f890bc87304..00000000000 --- a/web/get-datahub.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -BRANCH_NAME=$1 - -REPO_URL="git@github.com:geonetwork/geonetwork-ui.git" -DATAHUB_FOLDER="src/main/datahub" - -if [ -z "$BRANCH_NAME" ]; then - echo "get-datahub.sh Error: BRANCH_NAME is not set." - exit 1 -fi - -# Remove datahub directory if it exists -if [ -d "$DATAHUB_FOLDER" ]; then - rm -rf "$DATAHUB_FOLDER" -fi - -mkdir -p "$DATAHUB_FOLDER" - -# Create a temporary directory for cloning -TEMP_DIR=$(mktemp -d) - -# Get the current directory -CURRENT_DIR=$(pwd) - -# Clone the repository into the temporary directory -git clone --branch "$BRANCH_NAME" "$REPO_URL" "$TEMP_DIR" - -# Move the contents of the specified folder to the datahub folder -mv "$TEMP_DIR"/* "$CURRENT_DIR/$DATAHUB_FOLDER" - -# Clean up the temporary directory -rm -rf "$TEMP_DIR" diff --git a/web/pom.xml b/web/pom.xml index 91f0db5c259..ee9eacb607b 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -635,23 +635,40 @@ - + org.codehaus.mojo exec-maven-plugin 3.3.0 - sparse-checkout + delete-existing initialize exec - sh + rm - ${project.basedir}/get-datahub.sh - ${datahub.git.branch} + -rf + src/main/geonetwork-ui + + + + + checkout-geonetwork-ui + initialize + + exec + + + git + + clone + --branch + ${geonetwork-ui.git.branch} + https://github.com/geonetwork/geonetwork-ui.git + src/main/geonetwork-ui @@ -675,15 +692,15 @@ 10.7.0 - + npm-install npm - install - src/main/datahub + ci --loglevel error + src/main/geonetwork-ui ${basedir} @@ -698,9 +715,9 @@ false - run nx -- build datahub + run nx -- build datahub --base-href=./ - src/main/datahub + src/main/geonetwork-ui ${basedir} @@ -721,10 +738,10 @@ true UTF-8 - ${project.build.directory}/datahub + ${build.webapp.resources}/datahub - src/main/datahub/dist/apps/datahub + src/main/geonetwork-ui/dist/apps/datahub false @@ -1495,7 +1512,7 @@ - main + main ${project.version} SNAPSHOT ${basedir}/src/main/webapp From 6b0bc268d814f16bcfca444cf447eaa8c222ef95 Mon Sep 17 00:00:00 2001 From: Olivia Date: Mon, 17 Jun 2024 18:19:39 +0200 Subject: [PATCH 3/6] make Datahub work in GeoNetwork --- .../org/fao/geonet/web/DatahubFilter.java | 84 +++++++++++-------- web/src/main/webResources/WEB-INF/web.xml | 3 +- .../config-security-mapping.xml | 4 + 3 files changed, 54 insertions(+), 37 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/web/DatahubFilter.java b/core/src/main/java/org/fao/geonet/web/DatahubFilter.java index 77ac07591b4..bab5486eb33 100644 --- a/core/src/main/java/org/fao/geonet/web/DatahubFilter.java +++ b/core/src/main/java/org/fao/geonet/web/DatahubFilter.java @@ -4,18 +4,29 @@ import org.apache.commons.io.IOUtils; import org.apache.http.HttpHeaders; import org.apache.log4j.Logger; -import org.fao.geonet.utils.Log; -import javax.servlet.*; +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.*; +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); - final String PATH_TO_DIST_FOLDER = "/datahub"; // this is relative to the context root +// final String PATH_TO_DIST_FOLDER = "/"; // this is relative to the context root @Override public void init(FilterConfig config) { @@ -27,48 +38,49 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha HttpServletResponse res = (HttpServletResponse) response; ServletContext context = req.getServletContext(); - - File fileFromDistFolder = null; String reqPath = req.getPathInfo(); + if (reqPath == null || !reqPath.startsWith("/srv/datahub")) { + chain.doFilter(request, res); + return; + } + // a req path will be "/srv/datahub/bla/bla" + String[] parts = reqPath.split("/"); + String portalName = parts[1]; // element at i=0 is empty + String filePath = Stream.of(parts).skip(2).collect(Collectors.joining("/")); - if (reqPath != null) { - // compute actual file path from requested file in the URL - String filePath = reqPath - .replace("/static", ""); - fileFromDistFolder = new File(context.getRealPath(PATH_TO_DIST_FOLDER + filePath)); - } - if (fileFromDistFolder != null && fileFromDistFolder.exists()) { - res.setStatus(200); - String extension = FilenameUtils.getExtension(fileFromDistFolder.getName()).toLowerCase(); - String contentType; - if (extension.equals("js")) { - contentType = "text/javascript; charset=UTF-8"; - } else { - contentType = Files.probeContentType(fileFromDistFolder.toPath()); - } - res.setContentType(contentType); + File actualFile = new File(context.getRealPath("/" + filePath)); - // set headers for disabling cache + // 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 = new FileInputStream(fileFromDistFolder); - 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(); + InputStream inStream = new FileInputStream(actualFile); + OutputStream outStream = res.getOutputStream(); - } else { - chain.doFilter(request, res); + // 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(); } @Override diff --git a/web/src/main/webResources/WEB-INF/web.xml b/web/src/main/webResources/WEB-INF/web.xml index 3379aab6a8d..4d56aae727f 100644 --- a/web/src/main/webResources/WEB-INF/web.xml +++ b/web/src/main/webResources/WEB-INF/web.xml @@ -91,7 +91,8 @@ datahubFilter - /srv/datahub/* + + /* diff --git a/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml b/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml index fa5171d30dd..1ee4b251a77 100644 --- a/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml +++ b/web/src/main/webapp/WEB-INF/config-security/config-security-mapping.xml @@ -258,7 +258,11 @@ access="permitAll"/> + + + + From 567e4e92e5ed4c70248b28911494c801411e47b6 Mon Sep 17 00:00:00 2001 From: Olivia Date: Tue, 18 Jun 2024 15:55:55 +0200 Subject: [PATCH 4/6] add configuration for default datahub --- core/pom.xml | 6 ++ .../fao/geonet/kernel/setting/Settings.java | 3 + .../org/fao/geonet/web/DatahubFilter.java | 44 ++++++++++- .../templates/admin/settings/system.html | 18 +++++ .../sql/migrate/v445/migrate-default.sql | 76 +++++++++++++++++++ 5 files changed, 145 insertions(+), 2 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index e75a312c7c7..0fba362569b 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -589,6 +589,12 @@ org.jasypt jasypt + + + com.moandjiezana.toml + toml4j + 0.7.2 + 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 index bab5486eb33..a4524c09724 100644 --- a/core/src/main/java/org/fao/geonet/web/DatahubFilter.java +++ b/core/src/main/java/org/fao/geonet/web/DatahubFilter.java @@ -1,9 +1,18 @@ package org.fao.geonet.web; +import com.moandjiezana.toml.Toml; +import com.moandjiezana.toml.TomlWriter; 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.constants.Geonet; +import org.fao.geonet.kernel.setting.SettingManager; +import org.fao.geonet.kernel.setting.Settings; +import org.fao.geonet.utils.Log; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -14,19 +23,20 @@ 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.Map; 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); -// final String PATH_TO_DIST_FOLDER = "/"; // this is relative to the context root @Override public void init(FilterConfig config) { @@ -44,6 +54,13 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha return; } + SettingManager settingManager = ApplicationContextHolder.get().getBean(SettingManager.class); + String isDatahubEnabled = settingManager.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 @@ -60,6 +77,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha res.setHeader(HttpHeaders.PRAGMA, "no-cache"); res.setHeader(HttpHeaders.EXPIRES, "0"); } + res.setStatus(200); String extension = FilenameUtils.getExtension(actualFile.getName()).toLowerCase(); String contentType; @@ -70,7 +88,14 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha } res.setContentType(contentType); - InputStream inStream = new FileInputStream(actualFile); + 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 @@ -83,6 +108,21 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha outStream.close(); } + private InputStream readConfiguration(String portalName) { + SettingManager settingManager = ApplicationContextHolder.get().getBean(SettingManager.class); + String datahubConfiguration = settingManager.getValue(Settings.GEONETWORK_UI_DATAHUB_CONFIGURATION); + + Toml toml = new Toml().read(datahubConfiguration); + Map tomlMap = toml.toMap(); + + // Force the "gn4_api_url" field to a value including the portal name + tomlMap.put("geonetwork4_api_url", "/geonetwork/" + portalName + "/api"); + + TomlWriter tomlWriter = new TomlWriter(); + String configuration = tomlWriter.write(tomlMap); + return new ByteArrayInputStream(configuration.getBytes()); + } + @Override public void destroy() { } 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 @@