mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Merge branch 'main' into CST-4122-ExposewWithdrawnItemsToAnonymousUsersFilteringOutTheMetadata
This commit is contained in:
15
SECURITY.md
Normal file
15
SECURITY.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
For information regarding which versions of DSpace are currently under support, please see our DSpace Software Support Policy:
|
||||
|
||||
https://wiki.lyrasis.org/display/DSPACE/DSpace+Software+Support+Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you believe you have found a security vulnerability in a supported version of DSpace, we encourage you to let us know right away.
|
||||
We will investigate all legitimate reports and do our best to quickly fix the problem. Please see our DSpace Software Support Policy
|
||||
for information on privately reporting vulnerabilities:
|
||||
|
||||
https://wiki.lyrasis.org/display/DSPACE/DSpace+Software+Support+Policy
|
@@ -501,10 +501,10 @@ public class BundleServiceImpl extends DSpaceObjectServiceImpl<Bundle> implement
|
||||
|
||||
// Remove bitstreams
|
||||
List<Bitstream> bitstreams = bundle.getBitstreams();
|
||||
bundle.clearBitstreams();
|
||||
for (Bitstream bitstream : bitstreams) {
|
||||
removeBitstream(context, bundle, bitstream);
|
||||
}
|
||||
bundle.clearBitstreams();
|
||||
|
||||
List<Item> items = new LinkedList<>(bundle.getItems());
|
||||
bundle.getItems().clear();
|
||||
|
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.xoai.app;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.lyncode.xoai.dataprovider.xml.xoai.Element;
|
||||
import com.lyncode.xoai.dataprovider.xml.xoai.Metadata;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.license.factory.LicenseServiceFactory;
|
||||
import org.dspace.license.service.CreativeCommonsService;
|
||||
import org.dspace.xoai.util.ItemUtils;
|
||||
|
||||
/**
|
||||
* XOAIExtensionItemCompilePlugin aims to add structured information about the
|
||||
* creative commons license applied to the item (if any).
|
||||
* The xoai document will be enriched with a structure like that
|
||||
* <code>
|
||||
* <element name="other">
|
||||
* <element name="cc">
|
||||
* <field name="uri"></field>
|
||||
* <field name="name"></field>
|
||||
* </element>
|
||||
* </element>
|
||||
* </code>
|
||||
*
|
||||
*/
|
||||
public class CCElementItemCompilePlugin implements XOAIExtensionItemCompilePlugin {
|
||||
|
||||
@Override
|
||||
public Metadata additionalMetadata(Context context, Metadata metadata, Item item) {
|
||||
CreativeCommonsService creativeCommonsService = LicenseServiceFactory.getInstance().getCreativeCommonsService();
|
||||
String licenseURI = creativeCommonsService.getLicenseURI(item);
|
||||
String licenseName = creativeCommonsService.getLicenseName(item);
|
||||
// licence uri is mandatory, name is optional
|
||||
if (StringUtils.isNotBlank(licenseURI)) {
|
||||
Element ccLicense = ItemUtils.create("cc");
|
||||
ccLicense.getField().add(ItemUtils.createValue("uri", licenseURI));
|
||||
if (StringUtils.isNotBlank(licenseName)) {
|
||||
ccLicense.getField().add(ItemUtils.createValue("name", licenseName));
|
||||
}
|
||||
Element other;
|
||||
List<Element> elements = metadata.getElement();
|
||||
if (ItemUtils.getElement(elements, "others") != null) {
|
||||
other = ItemUtils.getElement(elements, "others");
|
||||
} else {
|
||||
other = ItemUtils.create("others");
|
||||
}
|
||||
other.getElement().add(ccLicense);
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
@@ -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.xoai.app;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.dspace.kernel.config.SpringLoader;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
|
||||
/**
|
||||
* Spring Loader to load specific bean implementation only for OAI Spring
|
||||
* context
|
||||
*
|
||||
*/
|
||||
public class OAISpringLoader implements SpringLoader {
|
||||
|
||||
@Override
|
||||
public String[] getResourcePaths(ConfigurationService configurationService) {
|
||||
StringBuffer filePath = new StringBuffer();
|
||||
filePath.append(configurationService.getProperty("dspace.dir"));
|
||||
filePath.append(File.separator);
|
||||
filePath.append("config");
|
||||
filePath.append(File.separator);
|
||||
filePath.append("spring");
|
||||
filePath.append(File.separator);
|
||||
filePath.append("oai");
|
||||
filePath.append(File.separator);
|
||||
|
||||
try {
|
||||
return new String[] { new File(filePath.toString()).toURI().toURL().toString() + XML_SUFFIX };
|
||||
} catch (MalformedURLException e) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -27,6 +27,7 @@ import javax.xml.stream.XMLStreamException;
|
||||
import com.lyncode.xoai.dataprovider.exceptions.ConfigurationException;
|
||||
import com.lyncode.xoai.dataprovider.exceptions.WritingXmlException;
|
||||
import com.lyncode.xoai.dataprovider.xml.XmlOutputContext;
|
||||
import com.lyncode.xoai.dataprovider.xml.xoai.Metadata;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
@@ -56,6 +57,7 @@ import org.dspace.core.Context;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.util.SolrUtils;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.dspace.xoai.exceptions.CompilingException;
|
||||
import org.dspace.xoai.services.api.CollectionsService;
|
||||
import org.dspace.xoai.services.api.cache.XOAICacheService;
|
||||
@@ -95,6 +97,8 @@ public class XOAI {
|
||||
private final static ConfigurationService configurationService = DSpaceServicesFactory
|
||||
.getInstance().getConfigurationService();
|
||||
|
||||
private List<XOAIExtensionItemCompilePlugin> extensionPlugins;
|
||||
|
||||
private List<String> getFileFormats(Item item) {
|
||||
List<String> formats = new ArrayList<>();
|
||||
try {
|
||||
@@ -120,6 +124,8 @@ public class XOAI {
|
||||
// Load necessary DSpace services
|
||||
this.authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||
this.itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
this.extensionPlugins = new DSpace().getServiceManager()
|
||||
.getServicesByType(XOAIExtensionItemCompilePlugin.class);
|
||||
}
|
||||
|
||||
public XOAI(Context ctx, boolean hasOption) {
|
||||
@@ -129,6 +135,8 @@ public class XOAI {
|
||||
// Load necessary DSpace services
|
||||
this.authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||
this.itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
this.extensionPlugins = new DSpace().getServiceManager()
|
||||
.getServicesByType(XOAIExtensionItemCompilePlugin.class);
|
||||
}
|
||||
|
||||
private void println(String line) {
|
||||
@@ -455,7 +463,14 @@ public class XOAI {
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
XmlOutputContext xmlContext = XmlOutputContext.emptyContext(out, Second);
|
||||
retrieveMetadata(context, item).write(xmlContext);
|
||||
Metadata metadata = retrieveMetadata(context, item);
|
||||
|
||||
// Do any additional metadata element, depends on the plugins
|
||||
for (XOAIExtensionItemCompilePlugin plugin : extensionPlugins) {
|
||||
metadata = plugin.additionalMetadata(context, metadata, item);
|
||||
}
|
||||
|
||||
metadata.write(xmlContext);
|
||||
xmlContext.getWriter().flush();
|
||||
xmlContext.getWriter().close();
|
||||
doc.addField("item.compile", out.toString());
|
||||
@@ -698,4 +713,5 @@ public class XOAI {
|
||||
System.out.println(" -h Shows this text");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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.xoai.app;
|
||||
|
||||
import com.lyncode.xoai.dataprovider.xml.xoai.Metadata;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
|
||||
/**
|
||||
* This interface can be implemented by plugins that aims to contribute to the
|
||||
* generation of the xoai document stored in the item.compile solr OAI core
|
||||
* field
|
||||
*
|
||||
*/
|
||||
public interface XOAIExtensionItemCompilePlugin {
|
||||
|
||||
/**
|
||||
* This method allows plugins to add content to the xoai document generated for
|
||||
* the item.
|
||||
*
|
||||
* @param context the DSpace Context
|
||||
* @param metadata the basic xoai representation of the item that can be
|
||||
* manipulated by the plugin
|
||||
* @param item the dspace item to index
|
||||
* @return the altered xoai metadata
|
||||
*/
|
||||
public Metadata additionalMetadata(Context context, Metadata metadata, Item item);
|
||||
|
||||
}
|
@@ -65,7 +65,7 @@ public class ItemUtils {
|
||||
private ItemUtils() {
|
||||
}
|
||||
|
||||
private static Element getElement(List<Element> list, String name) {
|
||||
public static Element getElement(List<Element> list, String name) {
|
||||
for (Element e : list) {
|
||||
if (name.equals(e.getName())) {
|
||||
return e;
|
||||
@@ -75,13 +75,13 @@ public class ItemUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Element create(String name) {
|
||||
public static Element create(String name) {
|
||||
Element e = new Element();
|
||||
e.setName(name);
|
||||
return e;
|
||||
}
|
||||
|
||||
private static Element.Field createValue(String name, String value) {
|
||||
public static Element.Field createValue(String name, String value) {
|
||||
Element.Field e = new Element.Field();
|
||||
e.setValue(value);
|
||||
e.setName(name);
|
||||
@@ -108,7 +108,7 @@ public class ItemUtils {
|
||||
String url = "";
|
||||
String bsName = bit.getName();
|
||||
String sid = String.valueOf(bit.getSequenceID());
|
||||
String baseUrl = configurationService.getProperty("oai", "bitstream.baseUrl");
|
||||
String baseUrl = configurationService.getProperty("oai.bitstream.baseUrl");
|
||||
String handle = null;
|
||||
// get handle of parent Item of this bitstream, if there
|
||||
// is one:
|
||||
@@ -119,15 +119,7 @@ public class ItemUtils {
|
||||
handle = bi.get(0).getHandle();
|
||||
}
|
||||
}
|
||||
if (bsName == null) {
|
||||
List<String> ext = bit.getFormat(context).getExtensions();
|
||||
bsName = "bitstream_" + sid + (ext.isEmpty() ? "" : ext.get(0));
|
||||
}
|
||||
if (handle != null && baseUrl != null) {
|
||||
url = baseUrl + "/bitstream/" + handle + "/" + sid + "/" + URLUtils.encode(bsName);
|
||||
} else {
|
||||
url = URLUtils.encode(bsName);
|
||||
}
|
||||
url = baseUrl + "/bitstreams/" + bit.getID().toString() + "/download";
|
||||
|
||||
String cks = bit.getChecksum();
|
||||
String cka = bit.getChecksumAlgorithm();
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<properties>
|
||||
<!-- This is the path to the root [dspace-src] directory. -->
|
||||
<root.basedir>${basedir}/..</root.basedir>
|
||||
<spring-security.version>5.3.3.RELEASE</spring-security.version>
|
||||
<spring-security.version>5.3.9.RELEASE</spring-security.version>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@@ -42,7 +42,7 @@ public class BrowseEntryHalLinkFactory extends HalLinkFactory<BrowseEntryResourc
|
||||
addFilterParams(baseLink, data);
|
||||
|
||||
list.add(buildLink(BrowseIndexRest.ITEMS,
|
||||
baseLink.build().toUriString()));
|
||||
baseLink.build().encode().toUriString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,7 @@ public class SearchFacetValueHalLinkFactory extends DiscoveryRestHalLinkFactory<
|
||||
|
||||
addFilterForFacetValue(builder, halResource.getFacetData(), halResource.getValueData());
|
||||
|
||||
list.add(buildLink("search", builder.build().toUriString()));
|
||||
list.add(buildLink("search", builder.build().encode().toUriString()));
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -147,7 +147,7 @@ public class ItemRestRepository extends DSpaceObjectRestRepository<Item, ItemRes
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@PreAuthorize("hasPermission(#id, 'ITEM', 'DELETE')")
|
||||
protected void delete(Context context, UUID id) throws AuthorizeException {
|
||||
String[] copyVirtual =
|
||||
requestService.getCurrentRequest().getServletRequest()
|
||||
|
@@ -13,6 +13,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.dspace.app.rest.model.UploadBitstreamAccessConditionDTO;
|
||||
import org.dspace.app.rest.model.patch.LateObjectEvaluator;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
@@ -57,23 +58,23 @@ public class BitstreamResourcePolicyAddPatchOperation extends AddPatchOperation<
|
||||
Iterator<UploadConfiguration> uploadConfigs = uploadConfigsCollection.iterator();
|
||||
for (Bundle bb : bundle) {
|
||||
int idx = 0;
|
||||
for (Bitstream b : bb.getBitstreams()) {
|
||||
for (Bitstream bitstream : bb.getBitstreams()) {
|
||||
if (idx == Integer.parseInt(split[1])) {
|
||||
|
||||
List<UploadBitstreamAccessConditionDTO> newAccessConditions =
|
||||
new ArrayList<UploadBitstreamAccessConditionDTO>();
|
||||
if (split.length == 3) {
|
||||
authorizeService.removePoliciesActionFilter(context, b, Constants.READ);
|
||||
authorizeService.removePoliciesActionFilter(context, bitstream, Constants.READ);
|
||||
newAccessConditions = evaluateArrayObject((LateObjectEvaluator) value);
|
||||
} else if (split.length == 4) {
|
||||
// contains "-", call index-based accessConditions it make not sense
|
||||
newAccessConditions.add(evaluateSingleObject((LateObjectEvaluator) value));
|
||||
}
|
||||
|
||||
for (UploadBitstreamAccessConditionDTO newAccessCondition : newAccessConditions) {
|
||||
// TODO manage duplicate policy
|
||||
BitstreamResourcePolicyUtils.findApplyResourcePolicy(context, uploadConfigs,
|
||||
b, newAccessCondition);
|
||||
// TODO manage duplicate policy
|
||||
if (CollectionUtils.isNotEmpty(newAccessConditions)) {
|
||||
BitstreamResourcePolicyUtils.findApplyResourcePolicy(context, uploadConfigs, bitstream,
|
||||
newAccessConditions);
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
|
@@ -79,15 +79,17 @@ public class BitstreamResourcePolicyReplacePatchOperation extends ReplacePatchOp
|
||||
}
|
||||
|
||||
if (split.length == 4) {
|
||||
ResourcePolicyRest newAccessCondition = evaluateSingleObject((LateObjectEvaluator) value);
|
||||
while (uploadConfigs.hasNext()) {
|
||||
ResourcePolicyRest newAccessCondition = evaluateSingleObject((LateObjectEvaluator) value);
|
||||
|
||||
String name = newAccessCondition.getName();
|
||||
String description = newAccessCondition.getDescription();
|
||||
Date startDate = newAccessCondition.getStartDate();
|
||||
Date endDate = newAccessCondition.getEndDate();
|
||||
// TODO manage duplicate policy
|
||||
BitstreamResourcePolicyUtils.findApplyResourcePolicy(context, uploadConfigs,
|
||||
b, name, description, startDate, endDate);
|
||||
String name = newAccessCondition.getName();
|
||||
String description = newAccessCondition.getDescription();
|
||||
Date startDate = newAccessCondition.getStartDate();
|
||||
Date endDate = newAccessCondition.getEndDate();
|
||||
// TODO manage duplicate policy
|
||||
BitstreamResourcePolicyUtils.findApplyResourcePolicy(context, uploadConfigs.next(), b, name,
|
||||
description, startDate, endDate);
|
||||
}
|
||||
} else {
|
||||
// "path":
|
||||
// "/sections/upload/files/0/accessConditions/0/startDate"
|
||||
|
@@ -11,6 +11,7 @@ import java.sql.SQLException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.model.UploadBitstreamAccessConditionDTO;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
@@ -47,15 +48,20 @@ public class BitstreamResourcePolicyUtils {
|
||||
* @throws AuthorizeException If the user is not authorized
|
||||
*/
|
||||
public static void findApplyResourcePolicy(Context context, Iterator<UploadConfiguration> uploadConfigs,
|
||||
Bitstream b, UploadBitstreamAccessConditionDTO newAccessCondition)
|
||||
Bitstream b, List<UploadBitstreamAccessConditionDTO> newAccessConditions)
|
||||
throws SQLException, AuthorizeException, ParseException {
|
||||
String name = newAccessCondition.getName();
|
||||
String description = newAccessCondition.getDescription();
|
||||
while (uploadConfigs.hasNext()) {
|
||||
UploadConfiguration uploadConfiguration = uploadConfigs.next();
|
||||
for (UploadBitstreamAccessConditionDTO newAccessCondition : newAccessConditions) {
|
||||
String name = newAccessCondition.getName();
|
||||
String description = newAccessCondition.getDescription();
|
||||
|
||||
Date startDate = newAccessCondition.getStartDate();
|
||||
Date endDate = newAccessCondition.getEndDate();
|
||||
Date startDate = newAccessCondition.getStartDate();
|
||||
Date endDate = newAccessCondition.getEndDate();
|
||||
|
||||
findApplyResourcePolicy(context, uploadConfigs, b, name, description, startDate, endDate);
|
||||
findApplyResourcePolicy(context, uploadConfiguration, b, name, description, startDate, endDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,21 +79,15 @@ public class BitstreamResourcePolicyUtils {
|
||||
* @throws SQLException If a database error occurs
|
||||
* @throws AuthorizeException If the user is not authorized
|
||||
*/
|
||||
public static void findApplyResourcePolicy(Context context, Iterator<UploadConfiguration> uploadConfigs,
|
||||
public static void findApplyResourcePolicy(Context context, UploadConfiguration uploadConfiguration,
|
||||
Bitstream b, String name, String description,
|
||||
Date startDate, Date endDate)
|
||||
throws SQLException, AuthorizeException, ParseException {
|
||||
while (uploadConfigs
|
||||
.hasNext()) {
|
||||
UploadConfiguration uploadConfiguration = uploadConfigs.next();
|
||||
for (AccessConditionOption aco : uploadConfiguration.getOptions()) {
|
||||
if (aco.getName().equalsIgnoreCase(name)) {
|
||||
aco.createResourcePolicy(context, b, name, description, startDate, endDate);
|
||||
return;
|
||||
}
|
||||
for (AccessConditionOption aco : uploadConfiguration.getOptions()) {
|
||||
if (aco.getName().equalsIgnoreCase(name)) {
|
||||
aco.createResourcePolicy(context, b, name, description, startDate, endDate);
|
||||
return;
|
||||
}
|
||||
}
|
||||
log.warn("no AccessCondition found or applied for bitstream " + b.getID() +
|
||||
" with AccessCondition " + name);
|
||||
}
|
||||
}
|
||||
|
@@ -77,6 +77,18 @@ spring.http.encoding.force=true
|
||||
# However, you may wish to set this to "always" in your 'local.cfg' for development or debugging purposes.
|
||||
server.error.include-stacktrace = never
|
||||
|
||||
# Spring Boot proxy configuration (can be overridden in local.cfg).
|
||||
# By default, Spring Boot does not automatically use X-Forwarded-* Headers when generating links (and similar) in the
|
||||
# DSpace REST API. Three options are currently supported by Spring Boot:
|
||||
# * NATIVE = allows your web server to natively support standard Forwarded headers
|
||||
# * FRAMEWORK = (DSpace default) enables Spring Framework's built in filter to manage these headers in Spring Boot.
|
||||
# This setting is used by default to support all X-Forwarded-* headers, as the DSpace backend is often
|
||||
# installed behind Apache HTTPD or Nginx proxy (both of which pass those headers to Tomcat).
|
||||
# * NONE = (Spring default) Forwarded headers are ignored
|
||||
# For more information see
|
||||
# https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-use-behind-a-proxy-server
|
||||
server.forward-headers-strategy=FRAMEWORK
|
||||
|
||||
######################
|
||||
# Spring Boot Autoconfigure
|
||||
#
|
||||
@@ -107,6 +119,9 @@ spring.main.allow-bean-definition-overriding = true
|
||||
# Log4J configuration
|
||||
logging.config = ${dspace.dir}/config/log4j2.xml
|
||||
|
||||
##################################
|
||||
# Spring MVC file upload settings
|
||||
#
|
||||
# Maximum size of a single uploaded file (default = 1MB)
|
||||
spring.servlet.multipart.max-file-size = 512MB
|
||||
|
||||
|
@@ -537,11 +537,7 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
.build();
|
||||
}
|
||||
|
||||
bundle1 = BundleBuilder.createBundle(context, item)
|
||||
.withName("testname")
|
||||
.withBitstream(bitstream1)
|
||||
.withBitstream(bitstream2)
|
||||
.build();
|
||||
bundle1 = item.getBundles("ORIGINAL").get(0);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
|
@@ -7,12 +7,14 @@
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static com.google.common.net.UrlEscapers.urlPathSegmentEscaper;
|
||||
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.emptyOrNullString;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
@@ -1140,6 +1142,58 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoverSearchObjectsWithSpecialCharacterTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context).build();
|
||||
Collection collection = CollectionBuilder.createCollection(context, parentCommunity).build();
|
||||
ItemBuilder.createItem(context, collection)
|
||||
.withAuthor("DSpace & friends")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(
|
||||
get("/api/discover/search/objects")
|
||||
.param("sort", "score,DESC")
|
||||
.param("page", "0")
|
||||
.param("size", "10"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.facets", hasItem(allOf(
|
||||
hasJsonPath("$.name", is("author")),
|
||||
hasJsonPath("$._embedded.values", hasItem(
|
||||
hasJsonPath("$._links.search.href", containsString("DSpace%20%26%20friends"))
|
||||
))
|
||||
))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoverSearchBrowsesWithSpecialCharacterTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context).build();
|
||||
Collection collection = CollectionBuilder.createCollection(context, parentCommunity).build();
|
||||
ItemBuilder.createItem(context, collection)
|
||||
.withAuthor("DSpace & friends")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(
|
||||
get("/api/discover/browses/author/entries")
|
||||
.param("sort", "default,ASC")
|
||||
.param("page", "0")
|
||||
.param("size", "20"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.entries", hasItem(allOf(
|
||||
hasJsonPath("$.value", is("DSpace & friends")),
|
||||
hasJsonPath("$._links.items.href", containsString("DSpace%20%26%20friends"))
|
||||
))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoverSearchObjectsTestHasMoreAuthorFacet() throws Exception {
|
||||
//We turn off the authorization system in order to create the structure defined below
|
||||
@@ -5711,7 +5765,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
|
||||
.andExpect(jsonPath("$._embedded.values[0].label", is("Smith, Donald")))
|
||||
.andExpect(jsonPath("$._embedded.values[0].count", is(1)))
|
||||
.andExpect(jsonPath("$._embedded.values[0]._links.search.href",
|
||||
containsString("api/discover/search/objects?query=Donald&f.author=Smith, Donald,equals")))
|
||||
containsString("api/discover/search/objects?query=Donald&f.author=" +
|
||||
urlPathSegmentEscaper().escape("Smith, Donald,equals")
|
||||
)))
|
||||
.andExpect(jsonPath("$._embedded.values").value(Matchers.hasSize(1)));
|
||||
|
||||
}
|
||||
@@ -5764,7 +5820,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
|
||||
.andExpect(jsonPath("$._embedded.values[0].label", is("2017 - 2020")))
|
||||
.andExpect(jsonPath("$._embedded.values[0].count", is(3)))
|
||||
.andExpect(jsonPath("$._embedded.values[0]._links.search.href",
|
||||
containsString("api/discover/search/objects?dsoType=Item&f.dateIssued=[2017 TO 2020],equals")))
|
||||
containsString("api/discover/search/objects?dsoType=Item&f.dateIssued=" +
|
||||
urlPathSegmentEscaper().escape("[2017 TO 2020],equals")
|
||||
)))
|
||||
.andExpect(jsonPath("$._embedded.values").value(Matchers.hasSize(1)));
|
||||
|
||||
}
|
||||
|
@@ -1260,7 +1260,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteOneArchivedTest() throws Exception {
|
||||
public void deleteOneArchivedTestAsSystemAdmin() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
@@ -1313,10 +1313,166 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
.andExpect(status().is(404));
|
||||
|
||||
//Trying to get deleted item bitstream should fail with 404
|
||||
getClient().perform(get("/api/core/biststreams/" + bitstream.getID()))
|
||||
// NOTE: it currently does not work without an admin token
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(adminToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||
.andExpect(status().is(404));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteOneArchivedTestAsCollectionAdmin() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
// A collection administrator
|
||||
EPerson col1Admin = EPersonBuilder.createEPerson(context)
|
||||
.withCanLogin(true)
|
||||
.withEmail("col1admin@email.com")
|
||||
.withPassword(password)
|
||||
.withNameInMetadata("Col1", "Admin")
|
||||
.build();
|
||||
|
||||
// A community with one collection.
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder
|
||||
.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.withAdminGroup(col1Admin)
|
||||
.build();
|
||||
|
||||
// One public item, one workspace item and one template item.
|
||||
Item publicItem = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Public item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
//Add a bitstream to an item
|
||||
String bitstreamContent = "ThisIsSomeDummyText";
|
||||
Bitstream bitstream = null;
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream = BitstreamBuilder.
|
||||
createBitstream(context, publicItem, is)
|
||||
.withName("Bitstream1")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
// Check publicItem creation
|
||||
getClient().perform(get("/api/core/items/" + publicItem.getID()))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Check publicItem bitstream creation (shuold be stored in bundle)
|
||||
getClient().perform(get("/api/core/items/" + publicItem.getID() + "/bundles"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers
|
||||
.containsString("/api/core/items/" + publicItem.getID() + "/bundles")));
|
||||
|
||||
String token = getAuthToken(col1Admin.getEmail(), password);
|
||||
|
||||
//Delete public item
|
||||
getClient(token).perform(delete("/api/core/items/" + publicItem.getID()))
|
||||
.andExpect(status().is(204));
|
||||
|
||||
//Trying to get deleted item should fail with 404
|
||||
getClient().perform(get("/api/core/items/" + publicItem.getID()))
|
||||
.andExpect(status().is(404));
|
||||
|
||||
//Trying to get deleted item bitstream should fail with 404
|
||||
// NOTE: it currently does not work without an admin token
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(adminToken).perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||
.andExpect(status().is(404));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteOneArchivedTestAsOtherCollectionAdmin() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
// two collection administrators
|
||||
EPerson col1Admin = EPersonBuilder.createEPerson(context)
|
||||
.withCanLogin(true)
|
||||
.withEmail("col1admin@email.com")
|
||||
.withPassword(password)
|
||||
.withNameInMetadata("Col1", "Admin")
|
||||
.build();
|
||||
|
||||
EPerson col2Admin = EPersonBuilder.createEPerson(context)
|
||||
.withCanLogin(true)
|
||||
.withEmail("col2admin@email.com")
|
||||
.withPassword(password)
|
||||
.withNameInMetadata("Col2", "Admin")
|
||||
.build();
|
||||
|
||||
// A community with two collections.
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder
|
||||
.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.withAdminGroup(col1Admin)
|
||||
.build();
|
||||
CollectionBuilder
|
||||
.createCollection(context, parentCommunity)
|
||||
.withName("Collection 2")
|
||||
.withAdminGroup(col2Admin)
|
||||
.build();
|
||||
|
||||
// One public item, one workspace item and one template item in the first collection.
|
||||
Item publicItem = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Public item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
//Add a bitstream to an item in the first collection
|
||||
String bitstreamContent = "ThisIsSomeDummyText";
|
||||
Bitstream bitstream = null;
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream = BitstreamBuilder.
|
||||
createBitstream(context, publicItem, is)
|
||||
.withName("Bitstream1")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// Check publicItem creation
|
||||
getClient().perform(get("/api/core/items/" + publicItem.getID()))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Check publicItem bitstream creation (should be stored in bundle)
|
||||
getClient().perform(get("/api/core/items/" + publicItem.getID() + "/bundles"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers
|
||||
.containsString("/api/core/items/" + publicItem.getID() + "/bundles")));
|
||||
|
||||
// the admin of collection 2 will try to delete an item of collection 1
|
||||
String token = getAuthToken(col2Admin.getEmail(), password);
|
||||
|
||||
// trying to delete the public item should fail
|
||||
getClient(token).perform(delete("/api/core/items/" + publicItem.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
|
||||
// the item should still exist
|
||||
getClient().perform(get("/api/core/items/" + publicItem.getID()))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// the bitstream should still exist
|
||||
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID()))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteOneTemplateTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -23,6 +23,7 @@ import java.util.List;
|
||||
import org.dspace.app.rest.test.AbstractEntityIntegrationTest;
|
||||
import org.dspace.builder.CollectionBuilder;
|
||||
import org.dspace.builder.CommunityBuilder;
|
||||
import org.dspace.builder.EPersonBuilder;
|
||||
import org.dspace.builder.ItemBuilder;
|
||||
import org.dspace.builder.RelationshipBuilder;
|
||||
import org.dspace.content.Collection;
|
||||
@@ -868,10 +869,94 @@ public class RelationshipDeleteRestRepositoryIT extends AbstractEntityIntegratio
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteItemCopyVirtualMetadataAllInsufficientPermissions() throws Exception {
|
||||
public void deleteItemCopyVirtualMetadataAllAsCollectionAdmin() throws Exception {
|
||||
initPersonProjectPublication();
|
||||
|
||||
getClient(getAuthToken(collectionAdmin.getEmail(), password)).perform(
|
||||
delete("/api/core/items/" + personItem.getID()))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
publicationItem = itemService.find(context, publicationItem.getID());
|
||||
List<MetadataValue> publicationAuthorList =
|
||||
itemService.getMetadata(publicationItem, "dc", "contributor", "author", Item.ANY);
|
||||
assertThat(publicationAuthorList.size(), equalTo(0));
|
||||
List<MetadataValue> publicationRelationships = itemService.getMetadata(publicationItem,
|
||||
"relation", "isAuthorOfPublication", Item.ANY, Item.ANY);
|
||||
assertThat(publicationRelationships.size(), equalTo(0));
|
||||
|
||||
projectItem = itemService.find(context, projectItem.getID());
|
||||
List<MetadataValue> projectAuthorList =
|
||||
itemService.getMetadata(projectItem, "dc", "contributor", "author", Item.ANY);
|
||||
assertThat(projectAuthorList.size(), equalTo(0));
|
||||
List<MetadataValue> projectRelationships = itemService.getMetadata(projectItem,
|
||||
"relation", "isPersonOfProject", Item.ANY, Item.ANY);
|
||||
assertThat(projectRelationships.size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteItemCopyVirtualMetadataTypeAsCollectionAdmin() throws Exception {
|
||||
initPersonProjectPublication();
|
||||
|
||||
getClient(getAuthToken(collectionAdmin.getEmail(), password)).perform(
|
||||
delete("/api/core/items/" + personItem.getID()
|
||||
+ "?copyVirtualMetadata=" + publicationPersonRelationshipType.getID()))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
publicationItem = itemService.find(context, publicationItem.getID());
|
||||
List<MetadataValue> publicationAuthorList =
|
||||
itemService.getMetadata(publicationItem, "dc", "contributor", "author", Item.ANY);
|
||||
assertThat(publicationAuthorList.size(), equalTo(1));
|
||||
assertThat(publicationAuthorList.get(0).getValue(), equalTo("Smith, Donald"));
|
||||
assertThat(publicationAuthorList.get(0).getAuthority(), equalTo(null));
|
||||
List<MetadataValue> publicationRelationships = itemService.getMetadata(publicationItem,
|
||||
"relation", "isAuthorOfPublication", Item.ANY, Item.ANY);
|
||||
assertThat(publicationRelationships.size(), equalTo(1));
|
||||
|
||||
projectItem = itemService.find(context, projectItem.getID());
|
||||
List<MetadataValue> projectAuthorList =
|
||||
itemService.getMetadata(projectItem, "dc", "contributor", "author", Item.ANY);
|
||||
assertThat(projectAuthorList.size(), equalTo(0));
|
||||
List<MetadataValue> projectRelationships = itemService.getMetadata(projectItem,
|
||||
"relation", "isPersonOfProject", Item.ANY, Item.ANY);
|
||||
assertThat(projectRelationships.size(), equalTo(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection admin that is unrelated to {@link #collection}.
|
||||
* @return an EPerson
|
||||
*/
|
||||
protected EPerson createOtherCollectionAdmin() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson otherCollectionAdmin = EPersonBuilder.createEPerson(context)
|
||||
.withNameInMetadata("other", "col admin")
|
||||
.withCanLogin(true)
|
||||
.withEmail("otherCollectionAdmin@email.com")
|
||||
.withPassword(password)
|
||||
.withLanguage(I18nUtil.getDefaultLocale().getLanguage())
|
||||
.build();
|
||||
|
||||
Community otherCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Other Community")
|
||||
.build();
|
||||
|
||||
CollectionBuilder.createCollection(context, otherCommunity)
|
||||
.withName("Other Collection")
|
||||
.withAdminGroup(otherCollectionAdmin)
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
return otherCollectionAdmin;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteItemCopyVirtualMetadataAllInsufficientPermissions() throws Exception {
|
||||
initPersonProjectPublication();
|
||||
|
||||
EPerson otherCollectionAdmin = createOtherCollectionAdmin();
|
||||
|
||||
getClient(getAuthToken(otherCollectionAdmin.getEmail(), password)).perform(
|
||||
delete("/api/core/items/" + personItem.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
|
||||
@@ -900,7 +985,9 @@ public class RelationshipDeleteRestRepositoryIT extends AbstractEntityIntegratio
|
||||
public void deleteItemCopyVirtualMetadataTypeInsufficientPermissions() throws Exception {
|
||||
initPersonProjectPublication();
|
||||
|
||||
getClient(getAuthToken(collectionAdmin.getEmail(), password)).perform(
|
||||
EPerson otherCollectionAdmin = createOtherCollectionAdmin();
|
||||
|
||||
getClient(getAuthToken(otherCollectionAdmin.getEmail(), password)).perform(
|
||||
delete("/api/core/items/" + personItem.getID()
|
||||
+ "?copyVirtualMetadata=" + publicationPersonRelationshipType.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
|
@@ -5247,4 +5247,56 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchUploadAddMultiAccessConditionTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
|
||||
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
|
||||
|
||||
WorkspaceItem witem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
|
||||
.withTitle("Test WorkspaceItem")
|
||||
.withIssueDate("2019-10-01")
|
||||
.withFulltext("simple-article.pdf", "/local/path/simple-article.pdf", pdf)
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// create a list of values to use in add operation
|
||||
List<Operation> addAccessCondition = new ArrayList<>();
|
||||
List<Map<String, String>> values = new ArrayList<Map<String,String>>();
|
||||
Map<String, String> value = new HashMap<>();
|
||||
value.put("name", "openaccess");
|
||||
|
||||
Map<String, String> value2 = new HashMap<>();
|
||||
value2.put("name", "administrator");
|
||||
|
||||
values.add(value);
|
||||
values.add(value2);
|
||||
|
||||
addAccessCondition.add(new AddOperation("/sections/upload/files/0/accessConditions", values));
|
||||
String authToken = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(authToken).perform(patch("/api/submission/workspaceitems/" + witem.getID())
|
||||
.content(getPatchContent(addAccessCondition))
|
||||
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.sections.upload.files[0].accessConditions[0].name", is("openaccess")))
|
||||
.andExpect(jsonPath("$.sections.upload.files[0].accessConditions[1].name", is("administrator")));
|
||||
|
||||
// verify that the patch changes have been persisted
|
||||
getClient(authToken).perform(get("/api/submission/workspaceitems/" + witem.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.sections.upload.files[0].accessConditions[0].name", is("openaccess")))
|
||||
.andExpect(jsonPath("$.sections.upload.files[0].accessConditions[1].name", is("administrator")));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
package org.dspace.app.rest.matcher;
|
||||
|
||||
import static com.google.common.net.UrlEscapers.urlPathSegmentEscaper;
|
||||
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
@@ -24,7 +25,9 @@ public class FacetValueMatcher {
|
||||
hasJsonPath("$.label", is(label)),
|
||||
hasJsonPath("$.type", is("discover")),
|
||||
hasJsonPath("$._links.search.href", containsString("api/discover/search/objects")),
|
||||
hasJsonPath("$._links.search.href", containsString("f.author=" + label + ",equals"))
|
||||
hasJsonPath("$._links.search.href", containsString(
|
||||
"f.author=" + urlPathSegmentEscaper().escape(label) + ",equals"
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -90,7 +90,9 @@
|
||||
<!-- oaire:citation* -->
|
||||
<xsl:apply-templates
|
||||
select="doc:metadata/doc:element[@name='oaire']/doc:element[@name='citation']" mode="oaire"/>
|
||||
|
||||
<!-- CREATIVE COMMON LICENSE -->
|
||||
<xsl:apply-templates
|
||||
select="doc:metadata/doc:element[@name='others']/doc:element[@name='cc']" mode="oaire" />
|
||||
</oaire:resource>
|
||||
</xsl:template>
|
||||
|
||||
@@ -641,9 +643,9 @@
|
||||
<xsl:with-param name="value" select="$rightsValue"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
<!-- We are checking to ensure that only values ending in "access" can be used as datacite:rights.
|
||||
This is a valid solution as we pre-normalize dc.rights values in openaire4.xsl to end in the term
|
||||
"access" according to COAR Controlled Vocabulary -->
|
||||
<!-- We are checking to ensure that only values ending in "access" can be used as datacite:rights.
|
||||
This is a valid solution as we pre-normalize dc.rights values in openaire4.xsl to end in the term
|
||||
"access" according to COAR Controlled Vocabulary -->
|
||||
<xsl:if test="ends-with($lc_rightsValue,'access')">
|
||||
<datacite:rights>
|
||||
<xsl:if test="$rightsURI">
|
||||
@@ -1642,7 +1644,25 @@
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<!-- Prepare data for CC License -->
|
||||
<xsl:variable name="ccstart">
|
||||
<xsl:value-of select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element[@name='issued']/doc:element/doc:field[@name='value']/text()"/>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:template
|
||||
match="doc:element[@name='others']/doc:element[@name='cc']"
|
||||
mode="oaire">
|
||||
<oaire:licenseCondition>
|
||||
<xsl:attribute name="startDate">
|
||||
<xsl:value-of
|
||||
select="$ccstart"/>
|
||||
</xsl:attribute>
|
||||
<xsl:attribute name="uri">
|
||||
<xsl:value-of select="./doc:field[@name='uri']/text()" />
|
||||
</xsl:attribute>
|
||||
<xsl:value-of select="./doc:field[@name='name']/text()" />
|
||||
</oaire:licenseCondition>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ignore all non specified text values or attributes -->
|
||||
<xsl:template match="text()|@*"/>
|
||||
|
@@ -20,11 +20,15 @@
|
||||
dspace.dir = /dspace
|
||||
|
||||
# URL of DSpace backend ('server' webapp). Include port number etc.
|
||||
# This is where REST API and all enabled server modules (OAI-PMH, SWORD, SWORDv2, RDF, etc) will respond
|
||||
# DO NOT end it with '/'.
|
||||
# This is where REST API and all enabled server modules (OAI-PMH, SWORD,
|
||||
# SWORDv2, RDF, etc) will respond.
|
||||
dspace.server.url = http://localhost:8080/server
|
||||
|
||||
# URL of DSpace frontend (Angular UI). Include port number etc
|
||||
# This is used by the backend to provide links in emails, RSS feeds, Sitemaps, etc.
|
||||
# URL of DSpace frontend (Angular UI). Include port number etc.
|
||||
# DO NOT end it with '/'.
|
||||
# This is used by the backend to provide links in emails, RSS feeds, Sitemaps,
|
||||
# etc.
|
||||
dspace.ui.url = http://localhost:4000
|
||||
|
||||
# Name of the site
|
||||
@@ -371,16 +375,6 @@ useProxies = true
|
||||
# (Requires reboot of servlet container, e.g. Tomcat, to reload)
|
||||
#proxies.trusted.include_ui_ip = true
|
||||
|
||||
# Spring Boot proxy configuration (can be set in local.cfg or in application.properties).
|
||||
# By default, Spring Boot does not automatically use X-Forwarded-* Headers when generating links (and similar) in the
|
||||
# REST API. When using a proxy in front of the REST API, you may need to modify this setting:
|
||||
# * NATIVE = allows your web server to natively support standard Forwarded headers
|
||||
# * FRAMEWORK = enables Spring Framework's built in filter to manage these headers in Spring Boot
|
||||
# * NONE = default value. Forwarded headers are ignored
|
||||
# For more information see
|
||||
# https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-use-behind-a-proxy-server
|
||||
#server.forward-headers-strategy=FRAMEWORK
|
||||
|
||||
#### Media Filter / Format Filter plugins (through PluginService) ####
|
||||
# Media/Format Filters help to full-text index content or
|
||||
# perform automated format conversions
|
||||
|
@@ -33,11 +33,15 @@
|
||||
dspace.dir=/dspace
|
||||
|
||||
# URL of DSpace backend ('server' webapp). Include port number etc.
|
||||
# This is where REST API and all enabled server modules (OAI-PMH, SWORD, SWORDv2, RDF, etc) will respond
|
||||
# DO NOT end it with '/'.
|
||||
# This is where REST API and all enabled server modules (OAI-PMH, SWORD,
|
||||
# SWORDv2, RDF, etc) will respond.
|
||||
dspace.server.url = http://localhost:8080/server
|
||||
|
||||
# URL of DSpace frontend (Angular UI). Include port number etc
|
||||
# This is used by the backend to provide links in emails, RSS feeds, Sitemaps, etc.
|
||||
# URL of DSpace frontend (Angular UI). Include port number etc.
|
||||
# DO NOT end it with '/'.
|
||||
# This is used by the backend to provide links in emails, RSS feeds, Sitemaps,
|
||||
# etc.
|
||||
dspace.ui.url = http://localhost:4000
|
||||
|
||||
# Name of the site
|
||||
|
@@ -7,4 +7,5 @@
|
||||
# The class names of the modules which the dspace servicemanager will attempt to retrieve.
|
||||
# These classes contain the paths to where to spring files are loaded
|
||||
spring.springloader.modules=org.dspace.app.configuration.APISpringLoader,\
|
||||
org.dspace.app.rest.configuration.RESTSpringLoader
|
||||
org.dspace.app.rest.configuration.RESTSpringLoader,\
|
||||
org.dspace.xoai.app.OAISpringLoader
|
||||
|
@@ -45,7 +45,7 @@
|
||||
<bitstream-type>
|
||||
<mimetype>text/plain; charset=utf-8</mimetype>
|
||||
<short_description>License</short_description>
|
||||
<description>Item-specific license agreed upon to submission</description>
|
||||
<description>Item-specific license agreed to upon submission</description>
|
||||
<support_level>1</support_level>
|
||||
<internal>true</internal>
|
||||
</bitstream-type>
|
||||
@@ -54,7 +54,7 @@
|
||||
<bitstream-type>
|
||||
<mimetype>text/html; charset=utf-8</mimetype>
|
||||
<short_description>CC License</short_description>
|
||||
<description>Item-specific Creative Commons license agreed upon to submission</description>
|
||||
<description>Item-specific Creative Commons license agreed to upon submission</description>
|
||||
<support_level>1</support_level>
|
||||
<internal>true</internal>
|
||||
</bitstream-type>
|
||||
|
24
dspace/config/spring/oai/oai.xml
Normal file
24
dspace/config/spring/oai/oai.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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">
|
||||
|
||||
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
|
||||
|
||||
<!-- Additional item.compile plugin to enrich field with information about
|
||||
Creative Commons License metadata -->
|
||||
<bean class="org.dspace.xoai.app.CCElementItemCompilePlugin"/>
|
||||
</beans>
|
2
pom.xml
2
pom.xml
@@ -37,7 +37,7 @@
|
||||
<!-- NOTE: Jetty needed for Solr, Handle Server & tests -->
|
||||
<jetty.version>9.4.38.v20210224</jetty.version>
|
||||
<log4j.version>2.13.3</log4j.version>
|
||||
<pdfbox-version>2.0.15</pdfbox-version>
|
||||
<pdfbox-version>2.0.24</pdfbox-version>
|
||||
<poi-version>3.17</poi-version>
|
||||
<slf4j.version>1.7.25</slf4j.version>
|
||||
|
||||
|
Reference in New Issue
Block a user