diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 579c4f170b2..bf88981c124 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -177,4 +177,4 @@ jobs: --request POST \ https://api.github.com/repos/dataquest-dev/\ dspace-angular/actions/workflows/deploy.yml/dispatches \ - --data "{\"ref\":\"refs/heads/dtq-dev-7.5\"}" + --data "{\"ref\":\"refs/heads/dtq-dev\"}" diff --git a/dspace-api/src/main/java/org/dspace/app/statistics/clarin/ClarinMatomoBitstreamTracker.java b/dspace-api/src/main/java/org/dspace/app/statistics/clarin/ClarinMatomoBitstreamTracker.java index 7763745afd0..f3b6dc9ea4c 100644 --- a/dspace-api/src/main/java/org/dspace/app/statistics/clarin/ClarinMatomoBitstreamTracker.java +++ b/dspace-api/src/main/java/org/dspace/app/statistics/clarin/ClarinMatomoBitstreamTracker.java @@ -111,8 +111,10 @@ private String getItemIdentifier(Item item) { public void trackBitstreamDownload(Context context, HttpServletRequest request, Bitstream bit) throws SQLException { // We only track a download request when serving a request without Range header. Do not track the // download if the downloading continues or the tracking is not allowed by the configuration. - if (StringUtils.isNotBlank(request.getHeader("Range")) && - BooleanUtils.isFalse(configurationService.getBooleanProperty("matomo.track.enabled"))) { + if (StringUtils.isNotBlank(request.getHeader("Range"))) { + return; + } + if (BooleanUtils.isFalse(configurationService.getBooleanProperty("matomo.track.enabled"))) { return; } diff --git a/dspace-api/src/main/java/org/dspace/authenticate/clarin/Headers.java b/dspace-api/src/main/java/org/dspace/authenticate/clarin/Headers.java index 25f07561b30..e683ac2e140 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/clarin/Headers.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/clarin/Headers.java @@ -8,6 +8,7 @@ /* Created for LINDAT/CLARIN */ package org.dspace.authenticate.clarin; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; @@ -15,6 +16,9 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + /** * Helper class for request headers. * Class is copied from UFAL/CLARIN-DSPACE (https://github.com/ufal/clarin-dspace) and modified by @@ -22,6 +26,7 @@ */ public class Headers { + private static final Logger log = LogManager.getLogger(org.dspace.authenticate.clarin.Headers.class); // variables // @@ -56,7 +61,7 @@ public void initialise(HttpServletRequest request, String header_separator, List List vals = new ArrayList(); Enumeration e_vals = request.getHeaders(key); while (e_vals.hasMoreElements()) { - String values = (String)e_vals.nextElement(); + String values = updateValueByCharset((String) e_vals.nextElement()); vals.addAll( header2values(values) ); } @@ -149,4 +154,20 @@ private List header2values(String header) { return values; } + + + /** + * Convert ISO header value to UTF-8 + * @param value ISO header value String + * @return + */ + private String updateValueByCharset(String value) { + try { + return new String(value.getBytes("ISO-8859-1"), "UTF-8"); + } catch (UnsupportedEncodingException ex) { + log.warn("Failed to reconvert shibboleth attribute with value (" + + value + ").", ex); + } + return value; + } } diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 9f38a463019..f06e482ba38 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -272,3 +272,6 @@ authority.controlled.dspace.object.owner = true # Configuration required for thorough testing of browse links webui.browse.link.1 = author:dc.contributor.* webui.browse.link.2 = subject:dc.subject.* + +# If the versioning is disabled Versioning Integration Tests will fail - allow it for the tests +versioning.enabled=true diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java index 510456d8226..de98d236187 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/Application.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; +import java.util.function.Predicate; import javax.servlet.Filter; import org.dspace.app.rest.filter.DSpaceRequestContextFilter; @@ -39,6 +40,8 @@ import org.springframework.lang.NonNull; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.security.web.firewall.HttpFirewall; +import org.springframework.security.web.firewall.StrictHttpFirewall; import org.springframework.web.context.request.RequestContextListener; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -167,6 +170,23 @@ protected LinkRelationProvider dspaceLinkRelationProvider() { return new DSpaceLinkRelationProvider(); } + /** + * StrictHttpFirewall doesn't allow ISO header values by default. It could throw an error during Shibboleth + * authentication if the user has UTF-8 characters in the name. + * Updated allowedHeaderValues without any regex - it allows every character. + * @return + */ + @Bean + public HttpFirewall allowUrlEncodedSlashHttpFirewall() { + StrictHttpFirewall firewall = new StrictHttpFirewall(); + Predicate test = (s) -> { + return true; + }; + + firewall.setAllowedHeaderValues(test); + return firewall; + } + @Bean public WebMvcConfigurer webMvcConfigurer() { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java index 9fe6fa5c9e4..fe26d501b09 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/security/clarin/ClarinShibbolethLoginFilter.java @@ -78,7 +78,8 @@ public class ClarinShibbolethLoginFilter extends StatelessLoginFilter { public static final String VERIFICATION_TOKEN_HEADER = "Verification-Token"; - private static final Logger log = LogManager.getLogger(org.dspace.app.rest.security.ShibbolethLoginFilter.class); + private static final Logger log = LogManager.getLogger(org.dspace.app.rest.security.clarin. + ClarinShibbolethLoginFilter.class); /** * Property which handles information if the IdP send required information. @@ -176,6 +177,11 @@ public Authentication attemptAuthentication(HttpServletRequest req, } } + // logging + log.info("Shib-Identity-Provider: " + idp); + log.info("authentication-shibboleth.netid-header: " + netidHeader + " with value: " + netid); + log.info("authentication-shibboleth.email-header: " + emailHeader + " with value: " + email); + try { if (StringUtils.isEmpty(netid) || StringUtils.isEmpty(idp)) { log.error("Cannot load the netid or idp from the request headers."); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java index 47c9682181e..a2f413cbc5b 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/security/ClarinShibbolethLoginFilterIT.java @@ -458,4 +458,35 @@ public void testRedirectToGivenUntrustedUrl() throws Exception { .header("SHIB-NETID", NET_ID_TEST_EPERSON)) .andExpect(status().isBadRequest()); } + + @Test + public void testUTF8ShibHeaders() throws Exception { + // NOTE: The initial call to /shibboleth comes *from* an external Shibboleth site. So, it is always + // unauthenticated, but it must include some expected SHIB attributes. + // SHIB-MAIL attribute is the default email header sent from Shibboleth after a successful login. + // In this test we are simply mocking that behavior by setting it to an existing EPerson. + String token = getClient().perform(get("/api/authn/shibboleth") + .header("SHIB-MAIL", clarinEperson.getEmail()) + .header("Shib-Identity-Provider", IDP_TEST_EPERSON) + .header("SHIB-NETID", NET_ID_TEST_EPERSON) + .header("SHIB-GIVENNAME", "knihovna KůÅ\u0088 test ŽluÅ¥ouÄ\u008Dký")) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("http://localhost:4000")) + .andReturn().getResponse().getHeader("Authorization"); + + + getClient(token).perform(get("/api/authn/status")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authenticated", is(true))) + .andExpect(jsonPath("$.authenticationMethod", is("shibboleth"))); + + getClient(token).perform( + get("/api/authz/authorizations/search/object") + .param("embed", "feature") + .param("feature", feature) + .param("uri", utils.linkToSingleResource(ePersonRest, "self").getHref())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.page.totalElements", is(0))) + .andExpect(jsonPath("$._embedded").doesNotExist()); + } } diff --git a/dspace/config/clarin-dspace.cfg b/dspace/config/clarin-dspace.cfg index ff6828860c2..b5b19b79a77 100644 --- a/dspace/config/clarin-dspace.cfg +++ b/dspace/config/clarin-dspace.cfg @@ -174,3 +174,48 @@ statistics.cache-server.uri = http://cache-server.none ##### Importing ##### import.metadata.field.not.update = dc.description.provenance, dc.date.available, dc.date.accessioned, dc.identifier.uri + +#------------------------------------------------------------------# +#-------------------------Configure DOI----------------------------# +#------------------------------------------------------------------# + +# Credentials used to authenticate against the registration agency: +identifier.doi.user = username +identifier.doi.password = password +# DOI prefix used to mint DOIs. All DOIs minted by DSpace will use this prefix. +# The Prefix will be assigned by the registration agency. +identifier.doi.prefix = 10.5072 +# If you want to, you can further separate your namespace. Should all the +# suffixes of all DOIs minted by DSpace start with a special string to separate +# it from other services also minting DOIs under your prefix? +identifier.doi.namespaceseparator = dspace/ + +## +## Configure XSLT-driven submission crosswalk for DataCite +## +crosswalk.dissemination.DataCite.stylesheet = crosswalks/DIM2DataCite.xsl +crosswalk.dissemination.DataCite.schemaLocation = \ + http://datacite.org/schema/kernel-3 \ + http://schema.datacite.org/meta/kernel-3/metadata.xsd +crosswalk.dissemination.DataCite.preferList = false +crosswalk.dissemination.DataCite.publisher = My University +#crosswalk.dissemination.DataCite.dataManager = # defaults to publisher +#crosswalk.dissemination.DataCite.hostingInstitution = # defaults to publisher +crosswalk.dissemination.DataCite.namespace = http://datacite.org/schema/kernel-3 + +# consumer to update metadata of DOIs +event.consumer.doi.class = org.dspace.identifier.doi.DOIConsumer +event.consumer.doi.filters = Item+Modify_Metadata + +# Add doi here if you are using org.dspace.identifier.DOIIdentifierProvider to generate DOIs. +# Adding doi here makes DSpace send metadata updates to your doi registration agency. +# Add rdf here, if you are using dspace-rdf to export your repository content as RDF. +# Add iiif here, if you are using dspace-iiif. +event.dispatcher.default.consumers = versioning, discovery, eperson + +# Edit Item - Status option +identifiers.item-status.register-doi = false + +##### Dataquest URL - sing in the footer ##### +themed.by.url = https://www.dataquest.sk/dspace +themed.by.company.name = dataquest s.r.o. diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index 1c81d6c2f0b..687ad7fea85 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -266,7 +266,7 @@ identifier.doi.user = username identifier.doi.password = password # URL for the DOI resolver. This will be the stem for generated DOIs. -#identifier.doi.resolver = https://doi.org +# identifier.doi.resolver = https://doi.org # DOI prefix used to mint DOIs. All DOIs minted by DSpace will use this prefix. # The Prefix will be assigned by the registration agency. @@ -1165,6 +1165,11 @@ webui.browse.index.1 = dateissued:item:dateissued webui.browse.index.2 = author:metadata:dc.contributor.*\,dc.creator:text webui.browse.index.3 = title:item:title webui.browse.index.4 = subject:metadata:dc.subject.*:text +# webui.browse.index.5 = publisher:metadata:dc.publisher:text +# webui.browse.index.6 = language:metadata:dc.language.iso:iso_lang +# webui.browse.index.7 = itemtype:metadata:dc.type:text +# webui.browse.index.8 = rights:metadata:dc.rights.label:text + ## example of authority-controlled browse category - see authority control config #webui.browse.index.5 = lcAuthor:metadataAuthority:dc.contributor.author:authority diff --git a/dspace/config/modules/rest.cfg b/dspace/config/modules/rest.cfg index babb93a2970..82e1ef7a5da 100644 --- a/dspace/config/modules/rest.cfg +++ b/dspace/config/modules/rest.cfg @@ -62,6 +62,16 @@ rest.properties.exposed = dspace.name rest.properties.exposed = dspace.ui.url rest.properties.exposed = versioning.item.history.include.submitter rest.properties.exposed = statistics.cache-server.uri +rest.properties.exposed = themed.by.url +rest.properties.exposed = themed.by.company.name +rest.properties.exposed = identifier.doi.resolver +# TUL +rest.properties.exposed = dspace.ui.url +rest.properties.exposed = versioning.item.history.include.submitter +rest.properties.exposed = statistics.cache-server.uri +rest.properties.exposed = citace.pro.url +rest.properties.exposed = citace.pro.university +rest.properties.exposed = citace.pro.allowed #---------------------------------------------------------------# diff --git a/dspace/config/spring/api/core-services.xml b/dspace/config/spring/api/core-services.xml index 815e3a03425..a010fe23796 100644 --- a/dspace/config/spring/api/core-services.xml +++ b/dspace/config/spring/api/core-services.xml @@ -171,7 +171,7 @@ - +