mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 18:14:26 +00:00
Merge branch 'main' into CST-5306
This commit is contained in:
15
.github/workflows/docker.yml
vendored
15
.github/workflows/docker.yml
vendored
@@ -31,6 +31,11 @@ jobs:
|
||||
# We turn off 'latest' tag by default.
|
||||
TAGS_FLAVOR: |
|
||||
latest=false
|
||||
# Architectures / Platforms for which we will build Docker images
|
||||
# If this is a PR, we ONLY build for AMD64. For PRs we only do a sanity check test to ensure Docker builds work.
|
||||
# If this is NOT a PR (e.g. a tag or merge commit), also build for ARM64. NOTE: The ARM64 build takes MUCH
|
||||
# longer (around 45mins or so) which is why we only run it when pushing a new Docker image.
|
||||
PLATFORMS: linux/amd64${{ github.event_name != 'pull_request' && ', linux/arm64' || '' }}
|
||||
|
||||
steps:
|
||||
# https://github.com/actions/checkout
|
||||
@@ -42,7 +47,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
- name: Set up QEMU
|
||||
- name: Set up QEMU emulation to build for multiple architectures
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
# https://github.com/docker/login-action
|
||||
@@ -74,7 +79,7 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.dependencies
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
@@ -100,7 +105,7 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
@@ -129,7 +134,7 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.test
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
@@ -155,7 +160,7 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.cli
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: ${{ env.PLATFORMS }}
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
@@ -361,6 +361,23 @@
|
||||
<artifactId>ehcache</artifactId>
|
||||
<version>${ehcache.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache
|
||||
Caching dependencies for sherpa service. -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.cache</groupId>
|
||||
<artifactId>cache-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-jpamodelgen</artifactId>
|
||||
@@ -862,6 +879,13 @@
|
||||
<artifactId>mockserver-junit-rule</artifactId>
|
||||
<version>5.11.2</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<!-- Exclude snakeyaml to avoid conflicts with: spring-boot-starter-cache -->
|
||||
<exclusion>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@@ -31,6 +31,7 @@ import org.dspace.app.sherpa.v2.SHERPAResponse;
|
||||
import org.dspace.app.sherpa.v2.SHERPAUtils;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
|
||||
/**
|
||||
* SHERPAService is responsible for making the HTTP call to the SHERPA v2 API
|
||||
@@ -43,6 +44,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
* @author Kim Shepherd
|
||||
*/
|
||||
public class SHERPAService {
|
||||
|
||||
private CloseableHttpClient client = null;
|
||||
|
||||
private int maxNumberOfTries;
|
||||
@@ -91,6 +93,7 @@ public class SHERPAService {
|
||||
* @param query ISSN string to pass in an "issn equals" API query
|
||||
* @return SHERPAResponse containing an error or journal policies
|
||||
*/
|
||||
@Cacheable(key = "#query", cacheNames = "sherpa.searchByJournalISSN")
|
||||
public SHERPAResponse searchByJournalISSN(String query) {
|
||||
return performRequest("publication", "issn", "equals", query, 0, 1);
|
||||
}
|
||||
@@ -413,4 +416,5 @@ public class SHERPAService {
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
}
|
71
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheEvictService.java
vendored
Normal file
71
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheEvictService.java
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.sherpa.cache;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.dspace.app.sherpa.submit.SHERPASubmitService;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
/**
|
||||
* This service is responsible to deal with the SherpaService cache.
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
public class SherpaCacheEvictService {
|
||||
|
||||
// The cache that is managed by this service.
|
||||
static final String CACHE_NAME = "sherpa.searchByJournalISSN";
|
||||
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private SHERPASubmitService sherpaSubmitService;
|
||||
|
||||
/**
|
||||
* Remove immediately from the cache all the response that are related to a specific item
|
||||
* extracting the ISSNs from the item
|
||||
*
|
||||
* @param context The DSpace context
|
||||
* @param item an Item
|
||||
*/
|
||||
public void evictCacheValues(Context context, Item item) {
|
||||
Set<String> ISSNs = sherpaSubmitService.getISSNs(context, item);
|
||||
for (String issn : ISSNs) {
|
||||
Objects.requireNonNull(cacheManager.getCache(CACHE_NAME)).evictIfPresent(issn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate immediately the Sherpa cache
|
||||
*/
|
||||
public void evictAllCacheValues() {
|
||||
Objects.requireNonNull(cacheManager.getCache(CACHE_NAME)).invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reference to the cacheManager
|
||||
*
|
||||
* @param cacheManager
|
||||
*/
|
||||
public void setCacheManager(CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reference to the SherpaSubmitService
|
||||
*
|
||||
* @param sherpaSubmitService
|
||||
*/
|
||||
public void setSherpaSubmitService(SHERPASubmitService sherpaSubmitService) {
|
||||
this.sherpaSubmitService = sherpaSubmitService;
|
||||
}
|
||||
|
||||
}
|
34
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheLogger.java
vendored
Normal file
34
dspace-api/src/main/java/org/dspace/app/sherpa/cache/SherpaCacheLogger.java
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.sherpa.cache;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.ehcache.event.CacheEvent;
|
||||
import org.ehcache.event.CacheEventListener;
|
||||
|
||||
/**
|
||||
* This is a EHCache listner responsible for logging sherpa cache events. It is
|
||||
* bound to the sherpa cache via the dspace/config/ehcache.xml file. We need a
|
||||
* dedicated Logger for each cache as the CacheEvent doesn't include details
|
||||
* about where the event occur
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*
|
||||
*/
|
||||
public class SherpaCacheLogger implements CacheEventListener<Object, Object> {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(SherpaCacheLogger.class);
|
||||
|
||||
@Override
|
||||
public void onEvent(CacheEvent<?, ?> cacheEvent) {
|
||||
log.debug("Sherpa Cache Event Type: {} | Key: {} ",
|
||||
cacheEvent.getType(), cacheEvent.getKey());
|
||||
}
|
||||
|
||||
}
|
@@ -9,7 +9,6 @@ package org.dspace.app.sherpa.submit;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -63,19 +62,19 @@ public class SHERPASubmitService {
|
||||
* issnItemExtractor(s) in the SHERPA spring configuration.
|
||||
* The ISSNs are not validated with a regular expression or other rules - any values
|
||||
* extracted will be included in API queries.
|
||||
* Return the first not empty response from Sherpa
|
||||
* @see "dspace-dspace-addon-sherpa-configuration-services.xml"
|
||||
* @param context DSpace context
|
||||
* @param item DSpace item containing ISSNs to be checked
|
||||
* @return SHERPA v2 API response (policy data)
|
||||
*/
|
||||
public List<SHERPAResponse> searchRelatedJournals(Context context, Item item) {
|
||||
public SHERPAResponse searchRelatedJournals(Context context, Item item) {
|
||||
Set<String> issns = getISSNs(context, item);
|
||||
if (issns == null || issns.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
// SHERPA v2 API no longer supports "OR'd" ISSN search, perform individual searches instead
|
||||
Iterator<String> issnIterator = issns.iterator();
|
||||
List<SHERPAResponse> responses = new LinkedList<>();
|
||||
while (issnIterator.hasNext()) {
|
||||
String issn = issnIterator.next();
|
||||
SHERPAResponse response = sherpaService.searchByJournalISSN(issn);
|
||||
@@ -83,14 +82,13 @@ public class SHERPASubmitService {
|
||||
// Continue with loop
|
||||
log.warn("Failed to look up SHERPA ROMeO result for ISSN: " + issn
|
||||
+ ": " + response.getMessage());
|
||||
return response;
|
||||
} else if (!response.getJournals().isEmpty()) {
|
||||
// return this response, if it is not empty
|
||||
return response;
|
||||
}
|
||||
// Store this response, even if it has an error (useful for UI reporting)
|
||||
responses.add(response);
|
||||
}
|
||||
if (responses.isEmpty()) {
|
||||
responses.add(new SHERPAResponse("SHERPA ROMeO lookup failed"));
|
||||
}
|
||||
return responses;
|
||||
return new SHERPAResponse();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Model class for the Embargo of SHERPAv2 API (JSON)
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
public class SHERPAEmbargo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 6140668058547523656L;
|
||||
|
||||
private int amount;
|
||||
private String units;
|
||||
|
||||
public SHERPAEmbargo(int amount, String units) {
|
||||
this.amount = amount;
|
||||
this.units = units;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(int amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return units;
|
||||
}
|
||||
|
||||
public void setUnits(String units) {
|
||||
this.units = units;
|
||||
}
|
||||
|
||||
}
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -21,7 +22,7 @@ import java.util.List;
|
||||
*
|
||||
* @author Kim Shepherd
|
||||
*/
|
||||
public class SHERPAJournal {
|
||||
public class SHERPAJournal implements Serializable {
|
||||
|
||||
private List<String> titles;
|
||||
private String url;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,9 @@ import java.util.List;
|
||||
*
|
||||
* @see SHERPAPublisherPolicy
|
||||
*/
|
||||
public class SHERPAPermittedVersion {
|
||||
public class SHERPAPermittedVersion implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4992181606327727442L;
|
||||
|
||||
// Version (submitted, accepted, published)
|
||||
private String articleVersion;
|
||||
@@ -47,11 +50,6 @@ public class SHERPAPermittedVersion {
|
||||
// Embargo
|
||||
private SHERPAEmbargo embargo;
|
||||
|
||||
protected static class SHERPAEmbargo {
|
||||
String units;
|
||||
int amount;
|
||||
}
|
||||
|
||||
public String getArticleVersion() {
|
||||
return articleVersion;
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Plain java representation of a SHERPA Publisher object, based on SHERPA API v2 responses.
|
||||
*
|
||||
@@ -18,7 +20,7 @@ package org.dspace.app.sherpa.v2;
|
||||
* @see SHERPAJournal
|
||||
* @see SHERPAPublisherResponse
|
||||
*/
|
||||
public class SHERPAPublisher {
|
||||
public class SHERPAPublisher implements Serializable {
|
||||
private String name = null;
|
||||
private String relationshipType;
|
||||
private String country;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -22,7 +23,7 @@ import java.util.Map;
|
||||
* @see SHERPAJournal
|
||||
* @see SHERPAPermittedVersion
|
||||
*/
|
||||
public class SHERPAPublisherPolicy {
|
||||
public class SHERPAPublisherPolicy implements Serializable {
|
||||
|
||||
private int id;
|
||||
private boolean openAccessPermitted;
|
||||
|
@@ -10,12 +10,15 @@ package org.dspace.app.sherpa.v2;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.json.JSONArray;
|
||||
@@ -33,7 +36,10 @@ import org.json.JSONTokener;
|
||||
* @author Kim Shepherd
|
||||
*
|
||||
*/
|
||||
public class SHERPAResponse {
|
||||
public class SHERPAResponse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2732963970169240597L;
|
||||
|
||||
// Is this response to be treated as an error?
|
||||
private boolean error;
|
||||
|
||||
@@ -52,6 +58,9 @@ public class SHERPAResponse {
|
||||
// SHERPA URI (the human page version of this API response)
|
||||
private String uri;
|
||||
|
||||
@JsonIgnore
|
||||
private Date retrievalTime = new Date();
|
||||
|
||||
// Format enum - currently only JSON is supported
|
||||
public enum SHERPAFormat {
|
||||
JSON, XML
|
||||
@@ -71,6 +80,11 @@ public class SHERPAResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty SHERPAResponse representation
|
||||
*/
|
||||
public SHERPAResponse() {}
|
||||
|
||||
/**
|
||||
* Parse the SHERPA v2 API JSON and construct Romeo policy data for display
|
||||
* This method does not return a value, but rather populates the metadata and journals objects
|
||||
@@ -479,6 +493,12 @@ public class SHERPAResponse {
|
||||
}
|
||||
permittedVersion.setLicenses(sherpaLicenses);
|
||||
|
||||
if (permitted.has("embargo")) {
|
||||
JSONObject embargo = permitted.getJSONObject("embargo");
|
||||
SHERPAEmbargo SHERPAEmbargo = new SHERPAEmbargo(embargo.getInt("amount"), embargo.getString("units"));
|
||||
permittedVersion.setEmbargo(SHERPAEmbargo);
|
||||
}
|
||||
|
||||
return permittedVersion;
|
||||
}
|
||||
|
||||
@@ -542,4 +562,8 @@ public class SHERPAResponse {
|
||||
public SHERPASystemMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public Date getRetrievalTime() {
|
||||
return retrievalTime;
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package org.dspace.app.sherpa.v2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Plain java representation of a SHERPA System Metadata object, based on SHERPA API v2 responses.
|
||||
*
|
||||
@@ -18,7 +20,7 @@ package org.dspace.app.sherpa.v2;
|
||||
*
|
||||
* @author Kim Shepherd
|
||||
*/
|
||||
public class SHERPASystemMetadata {
|
||||
public class SHERPASystemMetadata implements Serializable {
|
||||
|
||||
private int id;
|
||||
private String uri;
|
||||
|
@@ -50,7 +50,7 @@ public class AuthoritySolrServiceImpl implements AuthorityIndexingService, Autho
|
||||
*/
|
||||
protected SolrClient solr = null;
|
||||
|
||||
protected SolrClient getSolr()
|
||||
public SolrClient getSolr()
|
||||
throws MalformedURLException, SolrServerException, IOException {
|
||||
if (solr == null) {
|
||||
|
||||
@@ -67,7 +67,11 @@ public class AuthoritySolrServiceImpl implements AuthorityIndexingService, Autho
|
||||
|
||||
SolrQuery solrQuery = new SolrQuery().setQuery("*:*");
|
||||
|
||||
try {
|
||||
solrServer.query(solrQuery);
|
||||
} catch (Exception ex) {
|
||||
log.error("An error occurs querying authority solr core", ex);
|
||||
}
|
||||
|
||||
solr = solrServer;
|
||||
}
|
||||
|
@@ -657,6 +657,15 @@ public class Context implements AutoCloseable {
|
||||
return myGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of all of the special groups uuids that current user is a member of.
|
||||
*
|
||||
* @return list of special groups uuids
|
||||
*/
|
||||
public Set<UUID> getSpecialGroupUuids() {
|
||||
return CollectionUtils.isEmpty(specialGroups) ? Set.of() : specialGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary change the user bound to the context, empty the special groups that
|
||||
* are retained to allow subsequent restore
|
||||
|
@@ -113,9 +113,11 @@ public abstract class IndexFactoryImpl<T extends IndexableObject, S> implements
|
||||
log.info("Full text is larger than the configured limit (discovery.solr.fulltext.charLimit)."
|
||||
+ " Only the first {} characters were indexed.", charLimit);
|
||||
} else {
|
||||
log.error("Tika parsing error. Could not index full text.", saxe);
|
||||
throw new IOException("Tika parsing error. Could not index full text.", saxe);
|
||||
}
|
||||
} catch (TikaException ex) {
|
||||
log.error("Tika parsing error. Could not index full text.", ex);
|
||||
throw new IOException("Tika parsing error. Could not index full text.", ex);
|
||||
}
|
||||
|
||||
|
@@ -569,4 +569,9 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
|
||||
public int countTotal(Context context) throws SQLException {
|
||||
return ePersonDAO.countRows(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(EPerson dso) {
|
||||
return dso.getName();
|
||||
}
|
||||
}
|
||||
|
@@ -829,4 +829,9 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
|
||||
final MetadataField metadataField) throws SQLException {
|
||||
return groupDAO.findByMetadataField(context, searchValue, metadataField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Group dso) {
|
||||
return dso.getName();
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.app.rest.cache;
|
||||
package org.dspace.iiif.logger;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.cache;
|
||||
package org.dspace.iiif.logger;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.statistics;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Service that handle the GeoIP database file.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class GeoIpService {
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
/**
|
||||
* Returns an instance of {@link DatabaseReader} based on the configured db
|
||||
* file, if any.
|
||||
*
|
||||
* @return the Database reader
|
||||
* @throws IllegalStateException if the db file is not configured correctly
|
||||
*/
|
||||
public DatabaseReader getDatabaseReader() throws IllegalStateException {
|
||||
String dbPath = configurationService.getProperty("usage-statistics.dbfile");
|
||||
if (StringUtils.isBlank(dbPath)) {
|
||||
throw new IllegalStateException("The required 'dbfile' configuration is missing in solr-statistics.cfg!");
|
||||
}
|
||||
|
||||
try {
|
||||
File dbFile = new File(dbPath);
|
||||
return new DatabaseReader.Builder(dbFile).build();
|
||||
} catch (FileNotFoundException fe) {
|
||||
throw new IllegalStateException(
|
||||
"The GeoLite Database file is missing (" + dbPath + ")! Solr Statistics cannot generate location " +
|
||||
"based reports! Please see the DSpace installation instructions for instructions to install " +
|
||||
"this file.",fe);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(
|
||||
"Unable to load GeoLite Database file (" + dbPath + ")! You may need to reinstall it. See the " +
|
||||
"DSpace installation instructions for more details.", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.statistics;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -142,6 +141,8 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
private ClientInfoService clientInfoService;
|
||||
@Autowired
|
||||
private SolrStatisticsCore solrStatisticsCore;
|
||||
@Autowired
|
||||
private GeoIpService geoIpService;
|
||||
|
||||
/** URL to the current-year statistics core. Prior-year shards will have a year suffixed. */
|
||||
private String statisticsCoreURL;
|
||||
@@ -179,26 +180,10 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
//spiderIps = SpiderDetector.getSpiderIpAddresses();
|
||||
|
||||
DatabaseReader service = null;
|
||||
// Get the db file for the location
|
||||
String dbPath = configurationService.getProperty("usage-statistics.dbfile");
|
||||
if (dbPath != null) {
|
||||
try {
|
||||
File dbFile = new File(dbPath);
|
||||
service = new DatabaseReader.Builder(dbFile).build();
|
||||
} catch (FileNotFoundException fe) {
|
||||
log.error(
|
||||
"The GeoLite Database file is missing (" + dbPath + ")! Solr Statistics cannot generate location " +
|
||||
"based reports! Please see the DSpace installation instructions for instructions to install " +
|
||||
"this file.",
|
||||
fe);
|
||||
} catch (IOException e) {
|
||||
log.error(
|
||||
"Unable to load GeoLite Database file (" + dbPath + ")! You may need to reinstall it. See the " +
|
||||
"DSpace installation instructions for more details.",
|
||||
e);
|
||||
}
|
||||
} else {
|
||||
log.error("The required 'dbfile' configuration is missing in solr-statistics.cfg!");
|
||||
service = geoIpService.getDatabaseReader();
|
||||
} catch (IllegalStateException ex) {
|
||||
log.error(ex);
|
||||
}
|
||||
locationService = service;
|
||||
}
|
||||
|
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
|
||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||
|
||||
<context:annotation-config/> <!-- allows us to use spring annotations in beans -->
|
||||
|
||||
<bean class="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService"
|
||||
id="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService">
|
||||
<property name="issnItemExtractors">
|
||||
<list>
|
||||
<bean class="org.dspace.app.sherpa.submit.MetadataValueISSNExtractor">
|
||||
<property name="metadataList">
|
||||
<list>
|
||||
<value>dc.identifier.issn</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
<!-- Use the follow if you have the SHERPARoMEOJournalTitle enabled
|
||||
<bean class="org.dspace.app.sherpa.submit.MetadataAuthorityISSNExtractor">
|
||||
<property name="metadataList">
|
||||
<list>
|
||||
<value>dc.title.alternative</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean> -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -25,10 +25,38 @@
|
||||
<property name="timeout" value="5000"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean class="org.dspace.app.sherpa.submit.SHERPASubmitService"
|
||||
id="org.dspace.app.sherpa.submit.SHERPASubmitService">
|
||||
<property name="sherpaService" ref="org.dspace.app.sherpa.SHERPAService"/>
|
||||
<property name="configuration" ref="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService"
|
||||
id="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService">
|
||||
<property name="issnItemExtractors">
|
||||
<list>
|
||||
<bean class="org.dspace.app.sherpa.submit.MetadataValueISSNExtractor">
|
||||
<property name="metadataList">
|
||||
<list>
|
||||
<value>dc.identifier.issn</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
<!-- Use the follow if you have the SHERPARoMEOJournalTitle enabled
|
||||
<bean class="org.dspace.app.sherpa.submit.MetadataAuthorityISSNExtractor">
|
||||
<property name="metadataList">
|
||||
<list>
|
||||
<value>dc.title.alternative</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean> -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean class="org.dspace.app.sherpa.cache.SherpaCacheEvictService">
|
||||
<property name="sherpaSubmitService"
|
||||
ref="org.dspace.app.sherpa.submit.SHERPASubmitService"/>
|
||||
<property name="cacheManager" ref="cacheManager" />
|
||||
</bean>
|
||||
</beans>
|
||||
|
@@ -137,6 +137,12 @@
|
||||
<processing-class>org.dspace.app.rest.submit.step.DescribeStep</processing-class>
|
||||
<type>submission-form</type>
|
||||
</step-definition>
|
||||
|
||||
<step-definition id="sherpaPolicies" mandatory="true">
|
||||
<heading>submit.progressbar.sherpapolicy</heading>
|
||||
<processing-class>org.dspace.app.rest.submit.step.SherpaPolicyStep</processing-class>
|
||||
<type>sherpaPolicy</type>
|
||||
</step-definition>
|
||||
</step-definitions>
|
||||
|
||||
<!-- The submission-definitions map lays out the detailed definition of -->
|
||||
@@ -172,6 +178,7 @@
|
||||
<!-- <step id="upload-with-embargo"/> -->
|
||||
<!-- <step id="extractionstep"/> -->
|
||||
<step id="defaultAC"/>
|
||||
<step id="sherpaPolicies"/>
|
||||
|
||||
<!--Step will be to Sign off on the License -->
|
||||
<step id="license"/>
|
||||
|
@@ -145,6 +145,9 @@ useProxies = true
|
||||
proxies.trusted.ipranges = 7.7.7.7
|
||||
proxies.trusted.include_ui_ip = true
|
||||
|
||||
# For the tests we have to disable this health indicator because there isn't a mock server and the calculated status was DOWN
|
||||
management.health.solrOai.enabled = false
|
||||
|
||||
researcher-profile.entity-type = Person
|
||||
|
||||
# Configuration settings required for Researcher Profiles
|
||||
|
@@ -15,13 +15,7 @@
|
||||
<!-- SHERPA data providers set up to use mock SHERPA service -->
|
||||
<bean class="org.dspace.external.provider.impl.SHERPAv2JournalISSNDataProvider" init-method="init">
|
||||
<property name="sourceIdentifier" value="sherpaJournalIssn"/>
|
||||
<property name="sherpaService">
|
||||
<bean class="org.dspace.app.sherpa.MockSHERPAService">
|
||||
<property name="maxNumberOfTries" value="3"/>
|
||||
<property name="sleepBetweenTimeouts" value="2000"/>
|
||||
<property name="timeout" value="5000"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="sherpaService" ref="org.dspace.app.sherpa.MockSHERPAService" />
|
||||
<property name="supportedEntityTypes">
|
||||
<list>
|
||||
<value>Journal</value>
|
||||
@@ -30,13 +24,7 @@
|
||||
</bean>
|
||||
<bean class="org.dspace.external.provider.impl.SHERPAv2JournalDataProvider" init-method="init">
|
||||
<property name="sourceIdentifier" value="sherpaJournal"/>
|
||||
<property name="sherpaService">
|
||||
<bean class="org.dspace.app.sherpa.MockSHERPAService">
|
||||
<property name="maxNumberOfTries" value="3"/>
|
||||
<property name="sleepBetweenTimeouts" value="2000"/>
|
||||
<property name="timeout" value="5000"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="sherpaService" ref="org.dspace.app.sherpa.MockSHERPAService" />
|
||||
<property name="supportedEntityTypes">
|
||||
<list>
|
||||
<value>Journal</value>
|
||||
@@ -45,13 +33,7 @@
|
||||
</bean>
|
||||
<bean class="org.dspace.external.provider.impl.SHERPAv2PublisherDataProvider" init-method="init">
|
||||
<property name="sourceIdentifier" value="sherpaPublisher"/>
|
||||
<property name="sherpaService">
|
||||
<bean class="org.dspace.app.sherpa.MockSHERPAService">
|
||||
<property name="maxNumberOfTries" value="3"/>
|
||||
<property name="sleepBetweenTimeouts" value="2000"/>
|
||||
<property name="timeout" value="5000"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="sherpaService" ref="org.dspace.app.sherpa.MockSHERPAService" />
|
||||
<property name="supportedEntityTypes">
|
||||
<list>
|
||||
<value>OrgUnit</value>
|
||||
|
@@ -33,4 +33,18 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- during test we need the mock sherpa service everywhere -->
|
||||
<alias name="org.dspace.app.sherpa.SHERPAService" alias="org.dspace.app.sherpa.MockSHERPAService"/>
|
||||
<bean class="org.dspace.app.sherpa.MockSHERPAService" id="org.dspace.app.sherpa.SHERPAService">
|
||||
<property name="maxNumberOfTries" value="3"/>
|
||||
<property name="sleepBetweenTimeouts" value="2000"/>
|
||||
<property name="timeout" value="5000"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.dspace.app.sherpa.submit.SHERPASubmitService"
|
||||
id="org.dspace.app.sherpa.submit.SHERPASubmitService">
|
||||
<property name="sherpaService" ref="org.dspace.app.sherpa.MockSHERPAService"/>
|
||||
<property name="configuration" ref="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
@@ -48,4 +48,6 @@
|
||||
class="org.dspace.statistics.MockSolrStatisticsCore"
|
||||
autowire-candidate="true"/>
|
||||
|
||||
<bean class="org.dspace.statistics.GeoIpService" autowire-candidate="true"/>
|
||||
|
||||
</beans>
|
||||
|
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd"
|
||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||
|
||||
<context:annotation-config/> <!-- allows us to use spring annotations in beans -->
|
||||
|
||||
<!-- during test we need the mock sherpa service everywhere -->
|
||||
<alias name="org.dspace.app.sherpa.SHERPAService" alias="org.dspace.app.sherpa.MockSHERPAService"/>
|
||||
<bean class="org.dspace.app.sherpa.MockSHERPAService" id="org.dspace.app.sherpa.SHERPAService">
|
||||
<property name="maxNumberOfTries" value="3"/>
|
||||
<property name="sleepBetweenTimeouts" value="2000"/>
|
||||
<property name="timeout" value="5000"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean class="org.dspace.app.sherpa.submit.SHERPASubmitService"
|
||||
id="org.dspace.app.sherpa.submit.SHERPASubmitService">
|
||||
<property name="sherpaService" ref="org.dspace.app.sherpa.MockSHERPAService"/>
|
||||
<property name="configuration" ref="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -11,6 +11,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.dspace.app.sherpa.v2.SHERPAPublisherResponse;
|
||||
import org.dspace.app.sherpa.v2.SHERPAResponse;
|
||||
@@ -25,20 +26,6 @@ import org.dspace.app.sherpa.v2.SHERPAResponse;
|
||||
*/
|
||||
public class MockSHERPAService extends SHERPAService {
|
||||
|
||||
/**
|
||||
* Simple overridden 'searchByJournalISSN' so that we do attempt to build the URI but rather than make
|
||||
* an actual HTTP call, return parsed SHERPAResponse for The Lancet based on known-good JSON stored with our
|
||||
* test resources.
|
||||
* If URI creation, parsing, or IO fails along the way, a SHERPAResponse with an error message set will be
|
||||
* returned.
|
||||
* @param query ISSN string to pass in an "issn equals" API query
|
||||
* @return SHERPAResponse
|
||||
*/
|
||||
@Override
|
||||
public SHERPAResponse searchByJournalISSN(String query) {
|
||||
return performRequest("publication", "issn", "equals", query, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple overridden performRequest so that we do attempt to build the URI but rather than make
|
||||
* an actual HTTP call, return parsed SHERPAResponse for The Lancet based on known-good JSON stored with our
|
||||
@@ -67,8 +54,12 @@ public class MockSHERPAService extends SHERPAService {
|
||||
return new SHERPAResponse("Error building URI");
|
||||
}
|
||||
|
||||
// Get mock JSON - in this case, a known good result for The Lancet
|
||||
content = getClass().getResourceAsStream("thelancet.json");
|
||||
// Get mock JSON
|
||||
// if a file with the name contained in the value does not exist, returns thelancet.json
|
||||
content = getContent(value.concat(".json"));
|
||||
if (Objects.isNull(content)) {
|
||||
content = getContent("thelancet.json");
|
||||
}
|
||||
|
||||
// Parse JSON input stream and return response for later evaluation
|
||||
return new SHERPAResponse(content, SHERPAResponse.SHERPAFormat.JSON);
|
||||
@@ -88,6 +79,10 @@ public class MockSHERPAService extends SHERPAService {
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream getContent(String fileName) {
|
||||
return getClass().getResourceAsStream(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple overridden performPublisherRequest so that we do attempt to build the URI but rather than make
|
||||
* an actual HTTP call, return parsed SHERPAPublisherResponse for PLOS based on known-good JSON stored with our
|
||||
@@ -133,4 +128,5 @@ public class MockSHERPAService extends SHERPAService {
|
||||
return new SHERPAPublisherResponse(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.AbstractUnitTest;
|
||||
import org.dspace.app.sherpa.v2.SHERPAResponse;
|
||||
@@ -109,20 +108,18 @@ public class SHERPASubmitServiceTest extends AbstractUnitTest {
|
||||
|
||||
// Get responses from SHERPA submit service, which should inspect item ISSNs and perform search
|
||||
// on the mock SHERPA service
|
||||
List<SHERPAResponse> responses = sherpaSubmitService.searchRelatedJournals(context, testItem);
|
||||
SHERPAResponse response = sherpaSubmitService.searchRelatedJournals(context, testItem);
|
||||
|
||||
// Make sure response is not null or empty
|
||||
assertTrue("Response list should not be null or empty",
|
||||
responses != null && !responses.isEmpty());
|
||||
assertTrue("Response should not be null", response != null);
|
||||
|
||||
// For each response (there should be only one based on test data) perform the standard set
|
||||
// of thorough parsing tests
|
||||
for (SHERPAResponse response : responses) {
|
||||
|
||||
// Assert response is not error, or fail with message
|
||||
assertFalse("Response was flagged as 'isError'", response.isError());
|
||||
|
||||
// Skip remainder of parsing tests - these are already done in SHERPAServiceTEst
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -177,14 +177,18 @@ public class WorkspaceItemBuilder extends AbstractBuilder<WorkspaceItem, Workspa
|
||||
return addMetadataValue(MetadataSchemaEnum.DC.getName(), "subject", null, subject);
|
||||
}
|
||||
|
||||
public WorkspaceItemBuilder withAbstract(final String subject) {
|
||||
return addMetadataValue(MetadataSchemaEnum.DC.getName(),"description", "abstract", subject);
|
||||
public WorkspaceItemBuilder withIssn(String issn) {
|
||||
return addMetadataValue(MetadataSchemaEnum.DC.getName(), "identifier", "issn", issn);
|
||||
}
|
||||
|
||||
public WorkspaceItemBuilder withEntityType(final String entityType) {
|
||||
return addMetadataValue("dspace", "entity", "type", entityType);
|
||||
}
|
||||
|
||||
public WorkspaceItemBuilder withAbstract(final String subject) {
|
||||
return addMetadataValue(MetadataSchemaEnum.DC.getName(),"description", "abstract", subject);
|
||||
}
|
||||
|
||||
public WorkspaceItemBuilder grantLicense() {
|
||||
Item item = workspaceItem.getItem();
|
||||
String license;
|
||||
|
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"items": []
|
||||
}
|
@@ -0,0 +1,504 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"system_metadata": {
|
||||
"id": 40863,
|
||||
"uri": "https://v2.sherpa.ac.uk/id/publication/40863",
|
||||
"date_modified": "2022-03-25 14:08:29",
|
||||
"publicly_visible": "yes",
|
||||
"publicly_visible_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Yes",
|
||||
"value": "yes"
|
||||
}
|
||||
],
|
||||
"date_created": "2022-01-11 09:43:53"
|
||||
},
|
||||
"tj_status_phrases": [
|
||||
{
|
||||
"phrase": "Plan S Approved",
|
||||
"value": "plan_s_approved",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"type_phrases": [
|
||||
{
|
||||
"value": "journal",
|
||||
"phrase": "Journal",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"id": 40863,
|
||||
"issns": [
|
||||
{
|
||||
"issn": "2731-0582"
|
||||
}
|
||||
],
|
||||
"publishers": [
|
||||
{
|
||||
"relationship_type": "commercial_publisher",
|
||||
"relationship_type_phrases": [
|
||||
{
|
||||
"value": "commercial_publisher",
|
||||
"phrase": "Commercial Publisher",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"publisher": {
|
||||
"id": 3286,
|
||||
"name": [
|
||||
{
|
||||
"name": "Nature Research",
|
||||
"language": "en",
|
||||
"preferred_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Name",
|
||||
"value": "name"
|
||||
}
|
||||
],
|
||||
"preferred": "name",
|
||||
"language_phrases": [
|
||||
{
|
||||
"phrase": "English",
|
||||
"value": "en",
|
||||
"language": "en"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"imprint_of_id": 62037,
|
||||
"country": "gb",
|
||||
"country_phrases": [
|
||||
{
|
||||
"value": "gb",
|
||||
"phrase": "United Kingdom",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"publication_count": 87,
|
||||
"uri": "https://v2.sherpa.ac.uk/id/publisher/3286",
|
||||
"url": "https://www.nature.com/"
|
||||
}
|
||||
}
|
||||
],
|
||||
"listed_in_doaj_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "No",
|
||||
"value": "no"
|
||||
}
|
||||
],
|
||||
"listed_in_doaj": "no",
|
||||
"tj_status": [
|
||||
"plan_s_approved"
|
||||
],
|
||||
"publisher_policy": [
|
||||
{
|
||||
"open_access_prohibited": "no",
|
||||
"id": 3286,
|
||||
"publication_count": 36,
|
||||
"internal_moniker": "Default Policy",
|
||||
"urls": [
|
||||
{
|
||||
"description": "Self archiving and license to publish",
|
||||
"url": "https://www.nature.com/neuro/editorial-policies/self-archiving-and-license-to-publish"
|
||||
},
|
||||
{
|
||||
"description": "Preprints and Conference Proceedings",
|
||||
"url": "https://www.nature.com/nature-portfolio/editorial-policies/preprints-and-conference-proceedings"
|
||||
},
|
||||
{
|
||||
"url": "https://www.springernature.com/gp/open-research/policies/accepted-manuscript-terms",
|
||||
"description": "Accepted manuscript terms of use"
|
||||
}
|
||||
],
|
||||
"open_access_prohibited_phrases": [
|
||||
{
|
||||
"value": "no",
|
||||
"phrase": "No",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"uri": "https://v2.sherpa.ac.uk/id/publisher_policy/3286",
|
||||
"permitted_oa": [
|
||||
{
|
||||
"prerequisites": {
|
||||
"prerequisites_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "when_research_article",
|
||||
"phrase": "If a Research Article"
|
||||
}
|
||||
],
|
||||
"prerequisites": [
|
||||
"when_research_article"
|
||||
]
|
||||
},
|
||||
"copyright_owner": "authors",
|
||||
"additional_oa_fee_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "no",
|
||||
"phrase": "No"
|
||||
}
|
||||
],
|
||||
"article_version_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "submitted",
|
||||
"phrase": "Submitted"
|
||||
}
|
||||
],
|
||||
"additional_oa_fee": "no",
|
||||
"copyright_owner_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "authors",
|
||||
"phrase": "Authors"
|
||||
}
|
||||
],
|
||||
"article_version": [
|
||||
"submitted"
|
||||
],
|
||||
"location": {
|
||||
"location_phrases": [
|
||||
{
|
||||
"value": "authors_homepage",
|
||||
"phrase": "Author's Homepage",
|
||||
"language": "en"
|
||||
},
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Funder Designated Location",
|
||||
"value": "funder_designated_location"
|
||||
},
|
||||
{
|
||||
"language": "en",
|
||||
"value": "institutional_repository",
|
||||
"phrase": "Institutional Repository"
|
||||
},
|
||||
{
|
||||
"phrase": "Preprint Repository",
|
||||
"value": "preprint_repository",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
"authors_homepage",
|
||||
"funder_designated_location",
|
||||
"institutional_repository",
|
||||
"preprint_repository"
|
||||
]
|
||||
},
|
||||
"conditions": [
|
||||
"Must link to publisher version",
|
||||
"Upon publication, source must be acknowledged and DOI cited",
|
||||
"Post-prints are subject to Springer Nature re-use terms",
|
||||
"Non-commercial use only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"embargo": {
|
||||
"units": "months",
|
||||
"amount": 6,
|
||||
"units_phrases": [
|
||||
{
|
||||
"phrase": "Months",
|
||||
"value": "months",
|
||||
"language": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
"license": [
|
||||
{
|
||||
"license_phrases": [
|
||||
{
|
||||
"phrase": "Publisher's Bespoke License",
|
||||
"value": "bespoke_license",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"license": "bespoke_license"
|
||||
}
|
||||
],
|
||||
"article_version_phrases": [
|
||||
{
|
||||
"value": "accepted",
|
||||
"phrase": "Accepted",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"additional_oa_fee": "no",
|
||||
"conditions": [
|
||||
"Must link to publisher version",
|
||||
"Published source must be acknowledged and DOI cited",
|
||||
"Post-prints are subject to Springer Nature re-use terms",
|
||||
"Non-commercial use only"
|
||||
],
|
||||
"copyright_owner_phrases": [
|
||||
{
|
||||
"phrase": "Authors",
|
||||
"value": "authors",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"location": {
|
||||
"location": [
|
||||
"authors_homepage",
|
||||
"funder_designated_location",
|
||||
"institutional_repository",
|
||||
"named_repository"
|
||||
],
|
||||
"location_phrases": [
|
||||
{
|
||||
"phrase": "Author's Homepage",
|
||||
"value": "authors_homepage",
|
||||
"language": "en"
|
||||
},
|
||||
{
|
||||
"phrase": "Funder Designated Location",
|
||||
"value": "funder_designated_location",
|
||||
"language": "en"
|
||||
},
|
||||
{
|
||||
"language": "en",
|
||||
"value": "institutional_repository",
|
||||
"phrase": "Institutional Repository"
|
||||
},
|
||||
{
|
||||
"language": "en",
|
||||
"value": "named_repository",
|
||||
"phrase": "Named Repository"
|
||||
}
|
||||
],
|
||||
"named_repository": [
|
||||
"PubMed Central",
|
||||
"Europe PMC"
|
||||
]
|
||||
},
|
||||
"article_version": [
|
||||
"accepted"
|
||||
],
|
||||
"prerequisites": {
|
||||
"prerequisites": [
|
||||
"when_research_article"
|
||||
],
|
||||
"prerequisites_phrases": [
|
||||
{
|
||||
"value": "when_research_article",
|
||||
"phrase": "If a Research Article",
|
||||
"language": "en"
|
||||
}
|
||||
]
|
||||
},
|
||||
"copyright_owner": "authors",
|
||||
"additional_oa_fee_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "no",
|
||||
"phrase": "No"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4410,
|
||||
"open_access_prohibited": "no",
|
||||
"urls": [
|
||||
{
|
||||
"url": "https://www.springernature.com/gp/open-research/about/the-fundamentals-of-open-access-and-open-research",
|
||||
"description": "The fundamentals of open access and open research"
|
||||
},
|
||||
{
|
||||
"url": "https://www.nature.com/neuro/editorial-policies/self-archiving-and-license-to-publish",
|
||||
"description": "Self archiving and license to publish"
|
||||
},
|
||||
{
|
||||
"url": "https://www.springernature.com/gp/open-research/policies/journal-policies",
|
||||
"description": "Open access policies for journals"
|
||||
}
|
||||
],
|
||||
"open_access_prohibited_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "No",
|
||||
"value": "no"
|
||||
}
|
||||
],
|
||||
"internal_moniker": "Open Access",
|
||||
"publication_count": 34,
|
||||
"permitted_oa": [
|
||||
{
|
||||
"additional_oa_fee_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Yes",
|
||||
"value": "yes"
|
||||
}
|
||||
],
|
||||
"copyright_owner": "authors",
|
||||
"conditions": [
|
||||
"Published source must be acknowledged with citation"
|
||||
],
|
||||
"article_version": [
|
||||
"published"
|
||||
],
|
||||
"copyright_owner_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "authors",
|
||||
"phrase": "Authors"
|
||||
}
|
||||
],
|
||||
"location": {
|
||||
"location_phrases": [
|
||||
{
|
||||
"phrase": "Any Website",
|
||||
"value": "any_website",
|
||||
"language": "en"
|
||||
},
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Journal Website",
|
||||
"value": "this_journal"
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
"any_website",
|
||||
"this_journal"
|
||||
]
|
||||
},
|
||||
"additional_oa_fee": "yes",
|
||||
"article_version_phrases": [
|
||||
{
|
||||
"phrase": "Published",
|
||||
"value": "published",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"license": [
|
||||
{
|
||||
"license_phrases": [
|
||||
{
|
||||
"phrase": "CC BY",
|
||||
"value": "cc_by",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"license": "cc_by",
|
||||
"version": "4.0"
|
||||
}
|
||||
],
|
||||
"publisher_deposit": [
|
||||
{
|
||||
"repository_metadata": {
|
||||
"type_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "disciplinary",
|
||||
"phrase": "Disciplinary"
|
||||
}
|
||||
],
|
||||
"notes": "Launched as UK PubMed Central (UKPMC) in January 2007, changed to Europe PubMed Central in November 2012.\r\nSpecial item types include: Links",
|
||||
"url": "http://europepmc.org/",
|
||||
"type": "disciplinary",
|
||||
"name": [
|
||||
{
|
||||
"name": "Europe PMC",
|
||||
"language": "en",
|
||||
"preferred": "name",
|
||||
"language_phrases": [
|
||||
{
|
||||
"value": "en",
|
||||
"phrase": "English",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"preferred_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Name",
|
||||
"value": "name"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"system_metadata": {
|
||||
"id": 908,
|
||||
"uri": "https://v2.sherpa.ac.uk/id/repository/908"
|
||||
}
|
||||
},
|
||||
{
|
||||
"system_metadata": {
|
||||
"id": 267,
|
||||
"uri": "https://v2.sherpa.ac.uk/id/repository/267"
|
||||
},
|
||||
"repository_metadata": {
|
||||
"type_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Disciplinary",
|
||||
"value": "disciplinary"
|
||||
}
|
||||
],
|
||||
"type": "disciplinary",
|
||||
"url": "http://www.ncbi.nlm.nih.gov/pmc/",
|
||||
"name": [
|
||||
{
|
||||
"language": "en",
|
||||
"name": "PubMed Central",
|
||||
"preferred": "name",
|
||||
"language_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "en",
|
||||
"phrase": "English"
|
||||
}
|
||||
],
|
||||
"preferred_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "name",
|
||||
"phrase": "Name"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"uri": "https://v2.sherpa.ac.uk/id/publisher_policy/4410"
|
||||
}
|
||||
],
|
||||
"title": [
|
||||
{
|
||||
"preferred_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"phrase": "Title",
|
||||
"value": "name"
|
||||
}
|
||||
],
|
||||
"language_phrases": [
|
||||
{
|
||||
"language": "en",
|
||||
"value": "en",
|
||||
"phrase": "English"
|
||||
}
|
||||
],
|
||||
"preferred": "name",
|
||||
"title": "Nature Synthesis",
|
||||
"language": "en"
|
||||
}
|
||||
],
|
||||
"type": "journal",
|
||||
"url": "https://www.nature.com/natsynth/"
|
||||
}
|
||||
]
|
||||
}
|
@@ -72,7 +72,12 @@ public class DSpaceOAIDataProvider {
|
||||
|
||||
private DSpaceResumptionTokenFormatter resumptionTokenFormat = new DSpaceResumptionTokenFormatter();
|
||||
|
||||
@RequestMapping({"", "/"})
|
||||
@RequestMapping("")
|
||||
public void index(HttpServletResponse response, HttpServletRequest request) throws IOException {
|
||||
response.sendRedirect(request.getRequestURI() + "/");
|
||||
}
|
||||
|
||||
@RequestMapping({"/"})
|
||||
public String indexAction(HttpServletResponse response, Model model) throws ServletException {
|
||||
try {
|
||||
XOAIManager manager = xoaiManagerResolver.getManager();
|
||||
|
@@ -272,6 +272,12 @@
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.flipkart.zjsonpatch</groupId>
|
||||
<artifactId>zjsonpatch</artifactId>
|
||||
@@ -457,7 +463,6 @@
|
||||
<dependency>
|
||||
<groupId>javax.cache</groupId>
|
||||
<artifactId>cache-api</artifactId>
|
||||
<version>1.1.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
|
||||
<dependency>
|
||||
|
@@ -161,6 +161,7 @@ public class Application extends SpringBootServletInitializer {
|
||||
@Override
|
||||
public void addCorsMappings(@NonNull CorsRegistry registry) {
|
||||
// Get allowed origins for api and iiif endpoints.
|
||||
// The actuator endpoints are configured using management.endpoints.web.cors.* properties
|
||||
String[] corsAllowedOrigins = configuration
|
||||
.getCorsAllowedOrigins(configuration.getCorsAllowedOriginsConfig());
|
||||
String[] iiifAllowedOrigins = configuration
|
||||
|
@@ -153,8 +153,9 @@ public class BitstreamRestController {
|
||||
}
|
||||
|
||||
org.dspace.app.rest.utils.BitstreamResource bitstreamResource =
|
||||
new org.dspace.app.rest.utils.BitstreamResource(
|
||||
name, uuid, currentUser != null ? currentUser.getID() : null, citationEnabledForBitstream);
|
||||
new org.dspace.app.rest.utils.BitstreamResource(name, uuid,
|
||||
currentUser != null ? currentUser.getID() : null,
|
||||
context.getSpecialGroupUuids(), citationEnabledForBitstream);
|
||||
|
||||
//We have all the data we need, close the connection to the database so that it doesn't stay open during
|
||||
//download/streaming
|
||||
|
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.configuration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.dspace.app.rest.DiscoverableEndpointsService;
|
||||
import org.dspace.app.rest.health.GeoIpHealthIndicator;
|
||||
import org.dspace.authority.AuthoritySolrServiceImpl;
|
||||
import org.dspace.discovery.SolrSearchCore;
|
||||
import org.dspace.statistics.SolrStatisticsCore;
|
||||
import org.dspace.xoai.services.api.solr.SolrServerResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
import org.springframework.boot.actuate.solr.SolrHealthIndicator;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.hateoas.Link;
|
||||
|
||||
/**
|
||||
* Configuration class related to the actuator endpoints.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class ActuatorConfiguration {
|
||||
|
||||
public static final Status UP_WITH_ISSUES_STATUS = new Status("UP_WITH_ISSUES");
|
||||
|
||||
@Autowired
|
||||
private DiscoverableEndpointsService discoverableEndpointsService;
|
||||
|
||||
@Value("${management.endpoints.web.base-path:/actuator}")
|
||||
private String actuatorBasePath;
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void registerActuatorEndpoints() {
|
||||
discoverableEndpointsService.register(this, Arrays.asList(Link.of(actuatorBasePath, "actuator")));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledHealthIndicator("solrSearch")
|
||||
@ConditionalOnProperty("discovery.search.server")
|
||||
public SolrHealthIndicator solrSearchCoreHealthIndicator(SolrSearchCore solrSearchCore) {
|
||||
return new SolrHealthIndicator(solrSearchCore.getSolr());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledHealthIndicator("solrStatistics")
|
||||
@ConditionalOnProperty("solr-statistics.server")
|
||||
public SolrHealthIndicator solrStatisticsCoreHealthIndicator(SolrStatisticsCore solrStatisticsCore) {
|
||||
return new SolrHealthIndicator(solrStatisticsCore.getSolr());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledHealthIndicator("solrAuthority")
|
||||
@ConditionalOnProperty("solr.authority.server")
|
||||
public SolrHealthIndicator solrAuthorityCoreHealthIndicator(AuthoritySolrServiceImpl authoritySolrService)
|
||||
throws MalformedURLException, SolrServerException, IOException {
|
||||
return new SolrHealthIndicator(authoritySolrService.getSolr());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledHealthIndicator("solrOai")
|
||||
@ConditionalOnProperty("oai.solr.url")
|
||||
public SolrHealthIndicator solrOaiCoreHealthIndicator(SolrServerResolver solrServerResolver)
|
||||
throws SolrServerException {
|
||||
return new SolrHealthIndicator(solrServerResolver.getServer());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledHealthIndicator("geoIp")
|
||||
public GeoIpHealthIndicator geoIpHealthIndicator() {
|
||||
return new GeoIpHealthIndicator();
|
||||
}
|
||||
|
||||
public String getActuatorBasePath() {
|
||||
return actuatorBasePath;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.health;
|
||||
|
||||
import static org.dspace.app.rest.configuration.ActuatorConfiguration.UP_WITH_ISSUES_STATUS;
|
||||
|
||||
import org.dspace.statistics.GeoIpService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.Health.Builder;
|
||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
||||
|
||||
/**
|
||||
* Implementation of {@link HealthIndicator} that verifies if the GeoIP database
|
||||
* is configured correctly.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class GeoIpHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
@Autowired
|
||||
private GeoIpService geoIpService;
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Builder builder) throws Exception {
|
||||
|
||||
try {
|
||||
geoIpService.getDatabaseReader();
|
||||
builder.up();
|
||||
} catch (IllegalStateException ex) {
|
||||
builder.status(UP_WITH_ISSUES_STATUS).withDetail("reason", ex.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -18,10 +18,18 @@ import org.dspace.app.rest.RestResourceController;
|
||||
* This class acts as a data holder for the RelationshipResource
|
||||
* Refer to {@link org.dspace.content.Relationship} for explanation about the properties
|
||||
*/
|
||||
@LinksRest(links = {
|
||||
@LinkRest(
|
||||
name = RelationshipRest.RELATIONSHIP_TYPE,
|
||||
method = "getRelationshipType"
|
||||
)
|
||||
})
|
||||
public class RelationshipRest extends BaseObjectRest<Integer> {
|
||||
public static final String NAME = "relationship";
|
||||
public static final String CATEGORY = "core";
|
||||
|
||||
public static final String RELATIONSHIP_TYPE = "relationshipType";
|
||||
|
||||
@JsonIgnore
|
||||
private UUID leftId;
|
||||
@JsonIgnore
|
||||
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.step;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.dspace.app.sherpa.v2.SHERPAResponse;
|
||||
|
||||
/**
|
||||
* Java Bean to expose Sherpa policies during in progress submission.
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
public class SherpaPolicy implements SectionData {
|
||||
|
||||
private static final long serialVersionUID = 2440249335255683173L;
|
||||
|
||||
private Date retrievalTime;
|
||||
|
||||
private SHERPAResponse sherpaResponse;
|
||||
|
||||
public Date getRetrievalTime() {
|
||||
return retrievalTime;
|
||||
}
|
||||
|
||||
public void setRetrievalTime(Date retrievalTime) {
|
||||
this.retrievalTime = retrievalTime;
|
||||
}
|
||||
|
||||
public SHERPAResponse getSherpaResponse() {
|
||||
return sherpaResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting a sherpaResponse will automatically set the retrievealTime
|
||||
* of the section copying the value from the response if not null
|
||||
*/
|
||||
public void setSherpaResponse(SHERPAResponse sherpaResponse) {
|
||||
this.sherpaResponse = sherpaResponse;
|
||||
this.retrievalTime = sherpaResponse.getRetrievalTime();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.model.RelationshipRest;
|
||||
import org.dspace.app.rest.model.RelationshipTypeRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.content.Relationship;
|
||||
import org.dspace.content.RelationshipType;
|
||||
import org.dspace.content.service.RelationshipService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Link repository for "relationshipType" subresource of an individual Relationship.
|
||||
*/
|
||||
@Component(RelationshipRest.CATEGORY + "." + RelationshipRest.NAME + "." + RelationshipRest.RELATIONSHIP_TYPE)
|
||||
public class RelationshipTypeRelationshipLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
RelationshipService relationshipService;
|
||||
|
||||
@PreAuthorize("permitAll()")
|
||||
public RelationshipTypeRest getRelationshipType(@Nullable HttpServletRequest request,
|
||||
Integer relationshipId,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) {
|
||||
try {
|
||||
Context context = obtainContext();
|
||||
Relationship relationship = relationshipService.find(context, relationshipId);
|
||||
if (relationship == null) {
|
||||
throw new ResourceNotFoundException("No such relationship: " + relationshipId);
|
||||
}
|
||||
int total = relationshipService.countByRelationshipType(context, relationship.getRelationshipType());
|
||||
Pageable pageable = utils.getPageable(optionalPageable);
|
||||
RelationshipType relationshipType = relationship.getRelationshipType();
|
||||
return converter.toRest(relationshipType, projection);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,6 +11,7 @@ import org.dspace.app.rest.exception.DSpaceAccessDeniedHandler;
|
||||
import org.dspace.authenticate.service.AuthenticationService;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -65,6 +66,9 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
private DSpaceAccessDeniedHandler accessDeniedHandler;
|
||||
|
||||
@Value("${management.endpoints.web.base-path:/actuator}")
|
||||
private String actuatorBasePath;
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity webSecurity) throws Exception {
|
||||
// Define URL patterns which Spring Security will ignore entirely.
|
||||
@@ -83,7 +87,7 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
// Configure authentication requirements for ${dspace.server.url}/api/ URL only
|
||||
// NOTE: REST API is hardcoded to respond on /api/. Other modules (OAI, SWORD, IIIF, etc) use other root paths.
|
||||
http.requestMatchers()
|
||||
.antMatchers("/api/**", "/iiif/**")
|
||||
.antMatchers("/api/**", "/iiif/**", actuatorBasePath + "/**")
|
||||
.and()
|
||||
// Enable Spring Security authorization on these paths
|
||||
.authorizeRequests()
|
||||
@@ -91,6 +95,7 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
.antMatchers(HttpMethod.POST,"/api/authn/login").permitAll()
|
||||
// Everyone can call GET on the status endpoint (used to check your authentication status)
|
||||
.antMatchers(HttpMethod.GET, "/api/authn/status").permitAll()
|
||||
.antMatchers(HttpMethod.GET, actuatorBasePath + "/info").hasAnyAuthority(ADMIN_GRANT)
|
||||
.and()
|
||||
// Tell Spring to not create Sessions
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||
|
@@ -35,5 +35,4 @@ public abstract class AbstractProcessingStep implements DataProcessingStep {
|
||||
protected MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
|
||||
protected ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.submit.step;
|
||||
|
||||
import java.util.Objects;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.model.step.SherpaPolicy;
|
||||
import org.dspace.app.rest.submit.AbstractProcessingStep;
|
||||
import org.dspace.app.rest.submit.SubmissionService;
|
||||
import org.dspace.app.sherpa.cache.SherpaCacheEvictService;
|
||||
import org.dspace.app.sherpa.submit.SHERPASubmitService;
|
||||
import org.dspace.app.sherpa.v2.SHERPAResponse;
|
||||
import org.dspace.app.util.SubmissionStepConfig;
|
||||
import org.dspace.content.InProgressSubmission;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.dspace.web.ContextUtil;
|
||||
|
||||
/**
|
||||
* SherpaPolicy step for DSpace Spring Rest. Expose information about
|
||||
* the Sherpa policies for the in progress submission.
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
public class SherpaPolicyStep extends AbstractProcessingStep {
|
||||
|
||||
public static final String SHERPA_RETRIEVAL_TIME = "retrievalTime";
|
||||
|
||||
private SherpaCacheEvictService sherpaCacheEvictService = new DSpace().getSingletonService(
|
||||
SherpaCacheEvictService.class);
|
||||
private SHERPASubmitService sherpaSubmitService = new DSpace().getSingletonService(SHERPASubmitService.class);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SherpaPolicy getData(SubmissionService submissionService, InProgressSubmission obj,
|
||||
SubmissionStepConfig config) throws Exception {
|
||||
Context context = ContextUtil.obtainCurrentRequestContext();
|
||||
SHERPAResponse response = sherpaSubmitService.searchRelatedJournals(context, obj.getItem());
|
||||
if (Objects.nonNull(response)) {
|
||||
SherpaPolicy result = new SherpaPolicy();
|
||||
result.setSherpaResponse(response);
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doPatchProcessing(Context context, HttpServletRequest currentRequest, InProgressSubmission source,
|
||||
Operation op, SubmissionStepConfig stepConf) throws Exception {
|
||||
String path = op.getPath();
|
||||
if (path.contains(SHERPA_RETRIEVAL_TIME)) {
|
||||
sherpaCacheEvictService.evictCacheValues(context, source.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -11,6 +11,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -40,6 +41,7 @@ public class BitstreamResource extends AbstractResource {
|
||||
private UUID currentUserUUID;
|
||||
private boolean shouldGenerateCoverPage;
|
||||
private byte[] file;
|
||||
private Set<UUID> currentSpecialGroups;
|
||||
|
||||
private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
|
||||
private EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
@@ -47,11 +49,12 @@ public class BitstreamResource extends AbstractResource {
|
||||
new DSpace().getServiceManager()
|
||||
.getServicesByType(CitationDocumentService.class).get(0);
|
||||
|
||||
public BitstreamResource(String name, UUID uuid, UUID currentUserUUID,
|
||||
public BitstreamResource(String name, UUID uuid, UUID currentUserUUID, Set<UUID> currentSpecialGroups,
|
||||
boolean shouldGenerateCoverPage) {
|
||||
this.name = name;
|
||||
this.uuid = uuid;
|
||||
this.currentUserUUID = currentUserUUID;
|
||||
this.currentSpecialGroups = currentSpecialGroups;
|
||||
this.shouldGenerateCoverPage = shouldGenerateCoverPage;
|
||||
}
|
||||
|
||||
@@ -84,9 +87,8 @@ public class BitstreamResource extends AbstractResource {
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
try (Context context = new Context()) {
|
||||
EPerson currentUser = ePersonService.find(context, currentUserUUID);
|
||||
context.setCurrentUser(currentUser);
|
||||
try (Context context = initializeContext()) {
|
||||
|
||||
Bitstream bitstream = bitstreamService.find(context, uuid);
|
||||
InputStream out;
|
||||
|
||||
@@ -110,9 +112,7 @@ public class BitstreamResource extends AbstractResource {
|
||||
|
||||
@Override
|
||||
public long contentLength() throws IOException {
|
||||
try (Context context = new Context()) {
|
||||
EPerson currentUser = ePersonService.find(context, currentUserUUID);
|
||||
context.setCurrentUser(currentUser);
|
||||
try (Context context = initializeContext()) {
|
||||
Bitstream bitstream = bitstreamService.find(context, uuid);
|
||||
if (shouldGenerateCoverPage) {
|
||||
return getCoverpageByteArray(context, bitstream).length;
|
||||
@@ -123,4 +123,12 @@ public class BitstreamResource extends AbstractResource {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Context initializeContext() throws SQLException {
|
||||
Context context = new Context();
|
||||
EPerson currentUser = ePersonService.find(context, currentUserUUID);
|
||||
context.setCurrentUser(currentUser);
|
||||
currentSpecialGroups.forEach(context::setSpecialGroup);
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.utils;
|
||||
|
||||
import org.dspace.app.util.Util;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Class that use the configuration service to add a property named
|
||||
* 'dspace.version' with the current DSpace application version.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class DSpaceVersionConfigurationEnricher implements ApplicationRunner {
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
configurationService.addPropertyValue("dspace.version", Util.getSourceVersion());
|
||||
}
|
||||
|
||||
}
|
@@ -63,9 +63,9 @@ public class OAIpmhIT extends AbstractControllerIntegrationTest {
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
// All OAI-PMH paths that we test against
|
||||
private final String ROOT_PATH = "/oai";
|
||||
private final String ROOT_PATH = "/oai/";
|
||||
private final String DEFAULT_CONTEXT_PATH = "request";
|
||||
private final String DEFAULT_CONTEXT = ROOT_PATH + "/" + DEFAULT_CONTEXT_PATH;
|
||||
private final String DEFAULT_CONTEXT = ROOT_PATH + DEFAULT_CONTEXT_PATH;
|
||||
|
||||
// Mock to ensure XOAI caching is disabled for all tests (see @Before method)
|
||||
@MockBean
|
||||
|
@@ -684,6 +684,56 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
|
||||
checkNumberOfStatsRecords(bitstream, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedSpecialGroupBitstreamTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
|
||||
Group restrictedGroup = GroupBuilder.createGroup(context)
|
||||
.withName("Restricted Group")
|
||||
.build();
|
||||
|
||||
String bitstreamContent = "Private!";
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
|
||||
Item item = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("item 1")
|
||||
.withIssueDate("2013-01-17")
|
||||
.withAuthor("Doe, John")
|
||||
.build();
|
||||
|
||||
bitstream = BitstreamBuilder
|
||||
.createBitstream(context, item, is)
|
||||
.withName("Test Embargoed Bitstream")
|
||||
.withDescription("This bitstream is embargoed")
|
||||
.withMimeType("text/plain")
|
||||
.withReaderGroup(restrictedGroup)
|
||||
.build();
|
||||
}
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String authToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(authToken).perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
|
||||
.andExpect(status().isForbidden());
|
||||
|
||||
configurationService.setProperty("authentication-password.login.specialgroup", "Restricted Group");
|
||||
|
||||
authToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(authToken).perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
checkNumberOfStatsRecords(bitstream, 1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restrictedGroupBitstreamAccessGrantByAdminsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static org.dspace.app.rest.configuration.ActuatorConfiguration.UP_WITH_ISSUES_STATUS;
|
||||
import static org.dspace.app.rest.link.search.HealthIndicatorMatcher.match;
|
||||
import static org.dspace.app.rest.link.search.HealthIndicatorMatcher.matchDatabase;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
|
||||
/**
|
||||
* Integration tests to verify the health indicators configuration.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class HealthIndicatorsIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
private static final String HEALTH_PATH = "/actuator/health";
|
||||
|
||||
@Test
|
||||
public void testWithAnonymousUser() throws Exception {
|
||||
|
||||
getClient().perform(get(HEALTH_PATH))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.status", is(UP_WITH_ISSUES_STATUS.getCode())))
|
||||
.andExpect(jsonPath("$.components").doesNotExist());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNotAdminUser() throws Exception {
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(token).perform(get(HEALTH_PATH))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.status", is(UP_WITH_ISSUES_STATUS.getCode())))
|
||||
.andExpect(jsonPath("$.components").doesNotExist());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithAdminUser() throws Exception {
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token).perform(get(HEALTH_PATH))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.status", is(UP_WITH_ISSUES_STATUS.getCode())))
|
||||
.andExpect(jsonPath("$.components", allOf(
|
||||
matchDatabase(Status.UP),
|
||||
match("solrSearchCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
||||
match("solrStatisticsCore", Status.UP, Map.of("status", 0, "detectedPathType", "root")),
|
||||
match("geoIp", UP_WITH_ISSUES_STATUS,
|
||||
Map.of("reason", "The required 'dbfile' configuration is missing in solr-statistics.cfg!"))
|
||||
)));
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Integration tests for info actuator.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class InfoEndpointIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
private static final String INFO_PATH = "/actuator/info";
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Test
|
||||
public void testWithAnonymousUser() throws Exception {
|
||||
|
||||
getClient().perform(get(INFO_PATH))
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNotAdminUser() throws Exception {
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(token).perform(get(INFO_PATH))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithAdminUser() throws Exception {
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(token).perform(get(INFO_PATH))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.app.name", matchProperty("dspace.name")))
|
||||
.andExpect(jsonPath("$.app.dir", matchProperty("dspace.dir")))
|
||||
.andExpect(jsonPath("$.app.url", matchProperty("dspace.server.url")))
|
||||
.andExpect(jsonPath("$.app.db", matchProperty("db.url")))
|
||||
.andExpect(jsonPath("$.app.solr.server", matchProperty("solr.server")))
|
||||
.andExpect(jsonPath("$.app.solr.prefix", matchProperty("solr.multicorePrefix")))
|
||||
.andExpect(jsonPath("$.app.mail.server", matchProperty("mail.server")))
|
||||
.andExpect(jsonPath("$.app.mail.from-address", matchProperty("mail.from.address")))
|
||||
.andExpect(jsonPath("$.app.mail.feedback-recipient", matchProperty("feedback.recipient")))
|
||||
.andExpect(jsonPath("$.app.mail.mail-admin", matchProperty("mail.admin")))
|
||||
.andExpect(jsonPath("$.app.mail.mail-helpdesk", matchProperty("mail.helpdesk")))
|
||||
.andExpect(jsonPath("$.app.mail.alert-recipient", matchProperty("alert.recipient")))
|
||||
.andExpect(jsonPath("$.app.cors.allowed-origins", matchProperty("rest.cors.allowed-origins")))
|
||||
.andExpect(jsonPath("$.app.ui.url", matchProperty("dspace.ui.url")))
|
||||
.andExpect(jsonPath("$.java").exists());
|
||||
|
||||
}
|
||||
|
||||
private Matcher<?> matchProperty(String name) {
|
||||
return is(configurationService.getProperty(name));
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -3164,4 +3164,28 @@ public class RelationshipRestRepositoryIT extends AbstractEntityIntegrationTest
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findTheCreatedRelationshipTypeTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
Relationship relationship = RelationshipBuilder
|
||||
.createRelationshipBuilder(context, author1, orgUnit1, isOrgUnitOfPersonRelationshipType).build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
Integer relationshipId = relationship.getID();
|
||||
getClient().perform(get("/api/core/relationships/" + relationshipId))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id", is(relationship.getID())))
|
||||
.andExpect(jsonPath("$._embedded.relationships").doesNotExist())
|
||||
.andExpect(jsonPath("$._links.relationshipType.href",
|
||||
containsString("/api/core/relationships/" + relationshipId + "/relationshipType"))
|
||||
);
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(adminToken).perform(get("/api/core/relationships/" + relationshipId + "/relationshipType"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -205,7 +205,7 @@ public class SubmissionDefinitionsControllerIT extends AbstractControllerIntegra
|
||||
// We expect the content type to be "application/hal+json;charset=UTF-8"
|
||||
.andExpect(content().contentType(contentType))
|
||||
// Match only that a section exists with a submission configuration behind
|
||||
.andExpect(jsonPath("$._embedded.submissionsections", hasSize(7)))
|
||||
.andExpect(jsonPath("$._embedded.submissionsections", hasSize(8)))
|
||||
.andExpect(jsonPath("$._embedded.submissionsections",
|
||||
Matchers.hasItem(
|
||||
allOf(
|
||||
|
@@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE;
|
||||
import static org.springframework.http.MediaType.parseMediaType;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
@@ -372,7 +373,9 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
|
||||
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
|
||||
.withTitle("Workspace Item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withAuthor("Smith, Donald")
|
||||
.withIssn("222731-0582")
|
||||
.withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
@@ -7597,4 +7600,200 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sherpaPolicySectionCacheTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
String dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
|
||||
.withTitle("Workspace Item 1")
|
||||
.withIssueDate("2021-11-21")
|
||||
.withAuthor("Smith, Donald")
|
||||
.withIssn("2731-0582")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
AtomicReference<String> retrievalTime = new AtomicReference<String>();
|
||||
AtomicReference<String> retrievalTime2 = new AtomicReference<String>();
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + witem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(false)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].titles[0]",
|
||||
is("Nature Synthesis")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].issns[0]",
|
||||
is("2731-0582")))))
|
||||
.andDo(result -> retrievalTime.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
Date date = new SimpleDateFormat(dateFormat).parse(retrievalTime.get());
|
||||
|
||||
// reload page, to verify that the retrievalTime is not changed
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + witem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(false)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].titles[0]",
|
||||
is("Nature Synthesis")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].issns[0]",
|
||||
is("2731-0582")))))
|
||||
.andDo(result -> retrievalTime2.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
Date date2 = new SimpleDateFormat(dateFormat).parse(retrievalTime2.get());
|
||||
|
||||
assertTrue(date.equals(date2));
|
||||
|
||||
// create a list of values to use in add operation
|
||||
List<Operation> operations = new ArrayList<>();
|
||||
operations.add(new RemoveOperation("/sections/sherpaPolicies/retrievalTime"));
|
||||
|
||||
// empty the cache and verify the retrivatTime
|
||||
String patchBody = getPatchContent(operations);
|
||||
getClient(token).perform(patch("/api/submission/workspaceitems/" + witem.getID())
|
||||
.content(patchBody)
|
||||
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(false)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].titles[0]",
|
||||
is("Nature Synthesis")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].issns[0]",
|
||||
is("2731-0582")))))
|
||||
.andDo(result -> retrievalTime.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
date = new SimpleDateFormat(dateFormat).parse(retrievalTime.get());
|
||||
|
||||
assertTrue(date.after(date2));
|
||||
|
||||
// reload page, to verify that the retrievalTime is not changed
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + witem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(false)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].titles[0]",
|
||||
is("Nature Synthesis")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals[0].issns[0]",
|
||||
is("2731-0582")))))
|
||||
.andDo(result -> retrievalTime2.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
date2 = new SimpleDateFormat(dateFormat).parse(retrievalTime2.get());
|
||||
assertTrue(date.equals(date2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sherpaPolicySectionWithWrongIssnCacheTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
String dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
|
||||
.withTitle("Workspace Item 1")
|
||||
.withIssueDate("2021-11-21")
|
||||
.withAuthor("Smith, Donald")
|
||||
.withIssn("0000-0000")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
AtomicReference<String> retrievalTime = new AtomicReference<String>();
|
||||
AtomicReference<String> retrievalTime2 = new AtomicReference<String>();
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + witem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(true)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.message", is("No results found")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals", nullValue()))))
|
||||
.andDo(result -> retrievalTime.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
Date date = new SimpleDateFormat(dateFormat).parse(retrievalTime.get());
|
||||
|
||||
// reload page, to verify that the retrievalTime is not changed
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + witem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(true)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.message", is("No results found")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals", nullValue()))))
|
||||
.andDo(result -> retrievalTime2.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
Date date2 = new SimpleDateFormat(dateFormat).parse(retrievalTime2.get());
|
||||
|
||||
assertTrue(date.equals(date2));
|
||||
|
||||
// create a list of values to use in add operation
|
||||
List<Operation> operations = new ArrayList<>();
|
||||
operations.add(new RemoveOperation("/sections/sherpaPolicies/retrievalTime"));
|
||||
|
||||
// empty the cache and verify the retrivatTime
|
||||
String patchBody = getPatchContent(operations);
|
||||
getClient(token).perform(patch("/api/submission/workspaceitems/" + witem.getID())
|
||||
.content(patchBody)
|
||||
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(true)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.message", is("No results found")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals", nullValue()))))
|
||||
.andDo(result -> retrievalTime.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
date = new SimpleDateFormat(dateFormat).parse(retrievalTime.get());
|
||||
|
||||
assertTrue(date.after(date2));
|
||||
|
||||
// reload page, to verify that the retrievalTime is not changed
|
||||
getClient(token).perform(get("/api/submission/workspaceitems/" + witem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.error", is(true)))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.message", is("No results found")))))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$.sections.sherpaPolicies.sherpaResponse.journals", nullValue()))))
|
||||
.andDo(result -> retrievalTime2.set(read(
|
||||
result.getResponse().getContentAsString(), "$.sections.sherpaPolicies.retrievalTime")));
|
||||
|
||||
date2 = new SimpleDateFormat(dateFormat).parse(retrievalTime2.get());
|
||||
assertTrue(date.equals(date2));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.health;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.anEmptyMap;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.maxmind.geoip2.DatabaseReader;
|
||||
import org.dspace.app.rest.configuration.ActuatorConfiguration;
|
||||
import org.dspace.statistics.GeoIpService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GeoIpHealthIndicator}.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GeoIpHealthIndicatorTest {
|
||||
|
||||
@Mock
|
||||
private GeoIpService geoIpService;
|
||||
|
||||
@InjectMocks
|
||||
private GeoIpHealthIndicator geoIpHealthIndicator;
|
||||
|
||||
@Mock
|
||||
private DatabaseReader databaseReader;
|
||||
|
||||
@Test
|
||||
public void testWithGeoIpConfiguredCorrectly() {
|
||||
when(geoIpService.getDatabaseReader()).thenReturn(databaseReader);
|
||||
|
||||
Health health = geoIpHealthIndicator.health();
|
||||
|
||||
assertThat(health.getStatus(), is(Status.UP));
|
||||
assertThat(health.getDetails(), anEmptyMap());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithGeoIpWrongConfiguration() {
|
||||
when(geoIpService.getDatabaseReader()).thenThrow(new IllegalStateException("Missing db file"));
|
||||
|
||||
Health health = geoIpHealthIndicator.health();
|
||||
|
||||
assertThat(health.getStatus(), is(ActuatorConfiguration.UP_WITH_ISSUES_STATUS));
|
||||
assertThat(health.getDetails(), is(Map.of("reason", "Missing db file")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithUnexpectedError() {
|
||||
when(geoIpService.getDatabaseReader()).thenThrow(new RuntimeException("Generic error"));
|
||||
|
||||
Health health = geoIpHealthIndicator.health();
|
||||
|
||||
assertThat(health.getStatus(), is(Status.DOWN));
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.link.search;
|
||||
|
||||
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
|
||||
/**
|
||||
* Matcher for the health indicators.
|
||||
*
|
||||
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||
*
|
||||
*/
|
||||
public final class HealthIndicatorMatcher {
|
||||
|
||||
private HealthIndicatorMatcher() {
|
||||
|
||||
}
|
||||
|
||||
public static Matcher<? super Object> matchDatabase(Status status) {
|
||||
return allOf(
|
||||
hasJsonPath("$.db"),
|
||||
hasJsonPath("$.db.status", is(status.getCode())),
|
||||
hasJsonPath("$.db.components", allOf(
|
||||
match("dspaceDataSource", status, Map.of("database", "H2", "validationQuery", "isValid()")),
|
||||
match("dataSource", status, Map.of("database", "H2", "validationQuery", "isValid()")))));
|
||||
}
|
||||
|
||||
public static Matcher<? super Object> match(String name, Status status, Map<String, Object> details) {
|
||||
return allOf(
|
||||
hasJsonPath("$." + name),
|
||||
hasJsonPath("$." + name + ".status", is(status.getCode())),
|
||||
hasJsonPath("$." + name + ".details", is(details)));
|
||||
}
|
||||
}
|
@@ -1551,6 +1551,7 @@ module_dir = modules
|
||||
# PRIOR to those below (and therefore may override configs in these default
|
||||
# module configuration files).
|
||||
|
||||
include = ${module_dir}/actuator.cfg
|
||||
include = ${module_dir}/altmetrics.cfg
|
||||
include = ${module_dir}/authentication.cfg
|
||||
include = ${module_dir}/authentication-ip.cfg
|
||||
|
@@ -1,22 +1,19 @@
|
||||
<!--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
-->
|
||||
<config
|
||||
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||
<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||
xmlns='http://www.ehcache.org/v3'
|
||||
xsi:schemaLocation="
|
||||
http://www.ehcache.org/v3
|
||||
xsi:schemaLocation="http://www.ehcache.org/v3
|
||||
http://www.ehcache.org/schema/ehcache-core-3.7.xsd">
|
||||
|
||||
<cache-template name="iiif-default">
|
||||
<listeners>
|
||||
<listener>
|
||||
<class>org.dspace.app.rest.cache.CacheLogger</class>
|
||||
<class>org.dspace.iiif.logger.CacheLogger</class>
|
||||
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
|
||||
<event-ordering-mode>UNORDERED</event-ordering-mode>
|
||||
<events-to-fire-on>CREATED</events-to-fire-on>
|
||||
@@ -33,7 +30,7 @@
|
||||
<cache-template name="iiif-canvas">
|
||||
<listeners>
|
||||
<listener>
|
||||
<class>org.dspace.app.rest.cache.CanvasCacheLogger</class>
|
||||
<class>org.dspace.iiif.logger.CanvasCacheLogger</class>
|
||||
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
|
||||
<event-ordering-mode>UNORDERED</event-ordering-mode>
|
||||
<events-to-fire-on>CREATED</events-to-fire-on>
|
||||
@@ -47,6 +44,26 @@
|
||||
<offheap unit="MB">4</offheap>
|
||||
</resources>
|
||||
</cache-template>
|
||||
<cache-template name="sherpa-default">
|
||||
<listeners>
|
||||
<listener>
|
||||
<class>org.dspace.app.sherpa.cache.SherpaCacheLogger</class>
|
||||
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
|
||||
<event-ordering-mode>UNORDERED</event-ordering-mode>
|
||||
<events-to-fire-on>CREATED</events-to-fire-on>
|
||||
<events-to-fire-on>EXPIRED</events-to-fire-on>
|
||||
<events-to-fire-on>REMOVED</events-to-fire-on>
|
||||
<events-to-fire-on>EVICTED</events-to-fire-on>
|
||||
</listener>
|
||||
</listeners>
|
||||
<resources>
|
||||
<heap>3000</heap>
|
||||
<offheap unit="MB">4</offheap>
|
||||
</resources>
|
||||
</cache-template>
|
||||
|
||||
<cache alias="manifests" uses-template="iiif-default"/>
|
||||
<cache alias="canvasdimensions" uses-template="iiif-canvas"/>
|
||||
<cache alias="sherpa.searchByJournalISSN" uses-template="sherpa-default"/>
|
||||
|
||||
</config>
|
@@ -203,6 +203,12 @@
|
||||
<processing-class>org.dspace.submit.step.SampleStep</processing-class>
|
||||
<type>sample</type>
|
||||
</step-definition>
|
||||
|
||||
<step-definition id="sherpaPolicies" mandatory="true">
|
||||
<heading>submit.progressbar.sherpapolicy</heading>
|
||||
<processing-class>org.dspace.app.rest.submit.step.SherpaPolicyStep</processing-class>
|
||||
<type>sherpaPolicy</type>
|
||||
</step-definition>
|
||||
</step-definitions>
|
||||
|
||||
<!-- The submission-definitions map lays out the detailed definition of -->
|
||||
@@ -235,8 +241,12 @@
|
||||
<!-- Uncomment this step to allow the user to embargo or access restrict the entire item -->
|
||||
<!-- <step id="itemAccessConditions"/> -->
|
||||
|
||||
<!-- Uncomment this step to show when appropriate publisher policies retrieved from SHERPA/RoMEO -->
|
||||
<!-- <step id="sherpaPolicies"/> -->
|
||||
|
||||
<!--Step will be to Upload the item -->
|
||||
<step id="upload"/>
|
||||
|
||||
<!-- <step id="extractionstep"/> -->
|
||||
|
||||
<!-- Uncomment this step to allow the user to select a Creative Commons License -->
|
||||
|
58
dspace/config/modules/actuator.cfg
Normal file
58
dspace/config/modules/actuator.cfg
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
#---------------------------------------------------------------#
|
||||
#------------SPRING BOOT ACTUATOR CONFIGURATION-----------------#
|
||||
#---------------------------------------------------------------#
|
||||
|
||||
# Health endpoint configuration, for more details see https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.health
|
||||
|
||||
## Configuration to establish when show the health status details
|
||||
management.endpoint.health.show-details = when-authorized
|
||||
## Configuration which users can see the health status details
|
||||
management.endpoint.health.roles = ADMIN
|
||||
## Configuration to establis
|
||||
management.endpoint.health.status.order= down, out-of-service, up-with-issues, up, unknown
|
||||
## Configuration that enables only health and info endpoints
|
||||
management.endpoints.web.exposure.include=health,info
|
||||
|
||||
## Configuration to set 200 as status of health http response when it is DOWN or OUT_OF_SERVICE
|
||||
## The DSpace UI requires these be set to 200 in order to support health status reports when services are down.
|
||||
management.endpoint.health.status.http-mapping.down = 200
|
||||
management.endpoint.health.status.http-mapping.out-of-service = 200
|
||||
|
||||
management.health.ping.enabled = false
|
||||
management.health.diskSpace.enabled = false
|
||||
|
||||
# CORS configuration for all actuators
|
||||
management.endpoints.web.cors.allowed-origins = ${rest.cors.allowed-origins}
|
||||
management.endpoints.web.cors.allowed-methods = *
|
||||
management.endpoints.web.cors.allowed-headers = Accept, Authorization, Content-Type, Origin, X-On-Behalf-Of, X-Requested-With, X-XSRF-TOKEN, X-CORRELATION-ID, X-REFERRER
|
||||
management.endpoints.web.cors.exposed-headers = Authorization, DSPACE-XSRF-TOKEN, Location, WWW-Authenticate
|
||||
management.endpoints.web.cors.allow-credentials = true
|
||||
|
||||
#---------------------------------------------------------------#
|
||||
#------------------------INFO ENDPOINT--------------------------#
|
||||
#---------------------------------------------------------------#
|
||||
|
||||
# All properties under the info key will be automatically exposed by the info actuator with a json structure. Furthermore, it is possible to
|
||||
# enrich the content of the response given by the info actuator by defining in the Spring context beans of classes that implements InfoContributor.
|
||||
|
||||
management.info.env.enabled = true
|
||||
management.info.java.enabled = true
|
||||
|
||||
info.app.name = ${dspace.name}
|
||||
info.app.version = ${dspace.version}
|
||||
info.app.dir = ${dspace.dir}
|
||||
info.app.url = ${dspace.server.url}
|
||||
info.app.db = ${db.url}
|
||||
info.app.solr.server = ${solr.server}
|
||||
info.app.solr.prefix = ${solr.multicorePrefix}
|
||||
info.app.mail.server = ${mail.server}
|
||||
info.app.mail.from-address = ${mail.from.address}
|
||||
info.app.mail.feedback-recipient = ${feedback.recipient}
|
||||
info.app.mail.mail-admin = ${mail.admin}
|
||||
info.app.mail.mail-helpdesk = ${mail.helpdesk}
|
||||
info.app.mail.alert-recipient = ${alert.recipient}
|
||||
|
||||
info.app.cors.allowed-origins = ${rest.cors.allowed-origins}
|
||||
|
||||
info.app.ui.url = ${dspace.ui.url}
|
21
dspace/config/spring/api/cache.xml
Normal file
21
dspace/config/spring/api/cache.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:cache="http://www.springframework.org/schema/cache"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/cache
|
||||
http://www.springframework.org/schema/cache/spring-cache.xsd">
|
||||
|
||||
<cache:annotation-driven />
|
||||
<bean id="cacheManager" class="org.springframework.cache.jcache.JCacheCacheManager">
|
||||
<property name="cacheManager">
|
||||
<bean class="org.springframework.cache.jcache.JCacheManagerFactoryBean">
|
||||
<property name="cacheManagerUri" value="file:${dspace.dir}/config/ehcache.xml"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -33,4 +33,16 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean class="org.dspace.app.sherpa.SHERPAService" id="org.dspace.app.sherpa.SHERPAService">
|
||||
<property name="maxNumberOfTries" value="3"/>
|
||||
<!-- the value of this property is in milliseconds -->
|
||||
<property name="sleepBetweenTimeouts" value="2000"/>
|
||||
<!-- the value of this property is in milliseconds -->
|
||||
<property name="timeout" value="5000"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.dspace.app.sherpa.cache.SherpaCacheEvictService">
|
||||
<property name="sherpaSubmitService"
|
||||
ref="org.dspace.app.sherpa.submit.SHERPASubmitService"/>
|
||||
</bean>
|
||||
</beans>
|
||||
|
@@ -32,4 +32,6 @@
|
||||
|
||||
<bean class="org.dspace.statistics.SolrStatisticsCore" autowire-candidate="true"/>
|
||||
|
||||
<bean class="org.dspace.statistics.GeoIpService" autowire-candidate="true"/>
|
||||
|
||||
</beans>
|
||||
|
Reference in New Issue
Block a user