mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00
Merge branch 'main' into dynamic-default-dims
This commit is contained in:
@@ -7,6 +7,13 @@
|
||||
*/
|
||||
package org.dspace.app.itemimport;
|
||||
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_HEIGHT_QUALIFIER;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_IMAGE_ELEMENT;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_LABEL_ELEMENT;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_SCHEMA;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_TOC_ELEMENT;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_WIDTH_QUALIFIER;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
@@ -1172,6 +1179,59 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
boolean bundleExists = false;
|
||||
boolean permissionsExist = false;
|
||||
boolean descriptionExists = false;
|
||||
boolean labelExists = false;
|
||||
boolean heightExists = false;
|
||||
boolean widthExists = false;
|
||||
boolean tocExists = false;
|
||||
|
||||
// look for label
|
||||
String labelMarker = "\tiiif-label";
|
||||
int lMarkerIndex = line.indexOf(labelMarker);
|
||||
int lEndIndex = 0;
|
||||
if (lMarkerIndex > 0) {
|
||||
lEndIndex = line.indexOf("\t", lMarkerIndex + 1);
|
||||
if (lEndIndex == -1) {
|
||||
lEndIndex = line.length();
|
||||
}
|
||||
labelExists = true;
|
||||
}
|
||||
|
||||
// look for height
|
||||
String heightMarker = "\tiiif-height";
|
||||
int hMarkerIndex = line.indexOf(heightMarker);
|
||||
int hEndIndex = 0;
|
||||
if (hMarkerIndex > 0) {
|
||||
hEndIndex = line.indexOf("\t", hMarkerIndex + 1);
|
||||
if (hEndIndex == -1) {
|
||||
hEndIndex = line.length();
|
||||
}
|
||||
heightExists = true;
|
||||
}
|
||||
|
||||
// look for width
|
||||
String widthMarker = "\tiiif-width";
|
||||
int wMarkerIndex = line.indexOf(widthMarker);
|
||||
int wEndIndex = 0;
|
||||
if (wMarkerIndex > 0) {
|
||||
wEndIndex = line.indexOf("\t", wMarkerIndex + 1);
|
||||
if (wEndIndex == -1) {
|
||||
wEndIndex = line.length();
|
||||
}
|
||||
widthExists = true;
|
||||
}
|
||||
|
||||
// look for toc
|
||||
String tocMarker = "\tiiif-toc";
|
||||
int tMarkerIndex = line.indexOf(tocMarker);
|
||||
int tEndIndex = 0;
|
||||
if (tMarkerIndex > 0) {
|
||||
tEndIndex = line.indexOf("\t", tMarkerIndex + 1);
|
||||
if (tEndIndex == -1) {
|
||||
tEndIndex = line.length();
|
||||
}
|
||||
tocExists = true;
|
||||
}
|
||||
|
||||
|
||||
// look for a bundle name
|
||||
String bundleMarker = "\tbundle:";
|
||||
@@ -1231,7 +1291,9 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
System.out.println("\tBitstream: " + bitstreamName + primaryStr);
|
||||
}
|
||||
|
||||
if (permissionsExist || descriptionExists) {
|
||||
if (permissionsExist || descriptionExists || labelExists || heightExists
|
||||
|| widthExists || tocExists) {
|
||||
System.out.println("Gathering options.");
|
||||
String extraInfo = bitstreamName;
|
||||
|
||||
if (permissionsExist) {
|
||||
@@ -1244,6 +1306,26 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
+ line.substring(dMarkerIndex, dEndIndex);
|
||||
}
|
||||
|
||||
if (labelExists) {
|
||||
extraInfo = extraInfo
|
||||
+ line.substring(lMarkerIndex, lEndIndex);
|
||||
}
|
||||
|
||||
if (heightExists) {
|
||||
extraInfo = extraInfo
|
||||
+ line.substring(hMarkerIndex, hEndIndex);
|
||||
}
|
||||
|
||||
if (widthExists) {
|
||||
extraInfo = extraInfo
|
||||
+ line.substring(wMarkerIndex, wEndIndex);
|
||||
}
|
||||
|
||||
if (tocExists) {
|
||||
extraInfo = extraInfo
|
||||
+ line.substring(tMarkerIndex, tEndIndex);
|
||||
}
|
||||
|
||||
options.add(extraInfo);
|
||||
}
|
||||
}
|
||||
@@ -1425,11 +1507,16 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
*/
|
||||
protected void processOptions(Context c, Item myItem, List<String> options)
|
||||
throws SQLException, AuthorizeException {
|
||||
System.out.println("Processing options.");
|
||||
for (String line : options) {
|
||||
System.out.println("\tprocessing " + line);
|
||||
|
||||
boolean permissionsExist = false;
|
||||
boolean descriptionExists = false;
|
||||
boolean labelExists = false;
|
||||
boolean heightExists = false;
|
||||
boolean widthExists = false;
|
||||
boolean tocExists = false;
|
||||
|
||||
String permissionsMarker = "\tpermissions:";
|
||||
int pMarkerIndex = line.indexOf(permissionsMarker);
|
||||
@@ -1453,6 +1540,56 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
descriptionExists = true;
|
||||
}
|
||||
|
||||
|
||||
// look for label
|
||||
String labelMarker = "\tiiif-label:";
|
||||
int lMarkerIndex = line.indexOf(labelMarker);
|
||||
int lEndIndex = 0;
|
||||
if (lMarkerIndex > 0) {
|
||||
lEndIndex = line.indexOf("\t", lMarkerIndex + 1);
|
||||
if (lEndIndex == -1) {
|
||||
lEndIndex = line.length();
|
||||
}
|
||||
labelExists = true;
|
||||
}
|
||||
|
||||
// look for height
|
||||
String heightMarker = "\tiiif-height:";
|
||||
int hMarkerIndex = line.indexOf(heightMarker);
|
||||
int hEndIndex = 0;
|
||||
if (hMarkerIndex > 0) {
|
||||
hEndIndex = line.indexOf("\t", hMarkerIndex + 1);
|
||||
if (hEndIndex == -1) {
|
||||
hEndIndex = line.length();
|
||||
}
|
||||
heightExists = true;
|
||||
}
|
||||
|
||||
// look for width
|
||||
String widthMarker = "\tiiif-width:";
|
||||
int wMarkerIndex = line.indexOf(widthMarker);
|
||||
int wEndIndex = 0;
|
||||
if (wMarkerIndex > 0) {
|
||||
wEndIndex = line.indexOf("\t", wMarkerIndex + 1);
|
||||
if (wEndIndex == -1) {
|
||||
wEndIndex = line.length();
|
||||
}
|
||||
widthExists = true;
|
||||
}
|
||||
|
||||
// look for toc
|
||||
String tocMarker = "\tiiif-toc:";
|
||||
int tMarkerIndex = line.indexOf(tocMarker);
|
||||
int tEndIndex = 0;
|
||||
if (tMarkerIndex > 0) {
|
||||
tEndIndex = line.indexOf("\t", tMarkerIndex + 1);
|
||||
if (tEndIndex == -1) {
|
||||
tEndIndex = line.length();
|
||||
}
|
||||
tocExists = true;
|
||||
}
|
||||
|
||||
|
||||
int bsEndIndex = line.indexOf("\t");
|
||||
String bitstreamName = line.substring(0, bsEndIndex);
|
||||
|
||||
@@ -1502,8 +1639,38 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
.trim();
|
||||
}
|
||||
|
||||
String thisLabel = "";
|
||||
if (labelExists) {
|
||||
thisLabel = line.substring(
|
||||
lMarkerIndex + labelMarker.length(), lEndIndex)
|
||||
.trim();
|
||||
}
|
||||
|
||||
String thisHeight = "";
|
||||
if (heightExists) {
|
||||
thisHeight = line.substring(
|
||||
hMarkerIndex + heightMarker.length(), hEndIndex)
|
||||
.trim();
|
||||
}
|
||||
|
||||
String thisWidth = "";
|
||||
if (widthExists) {
|
||||
thisWidth = line.substring(
|
||||
wMarkerIndex + widthMarker.length(), wEndIndex)
|
||||
.trim();
|
||||
}
|
||||
|
||||
String thisToc = "";
|
||||
if (tocExists) {
|
||||
thisToc = line.substring(
|
||||
tMarkerIndex + tocMarker.length(), tEndIndex)
|
||||
.trim();
|
||||
}
|
||||
|
||||
Bitstream bs = null;
|
||||
boolean notfound = true;
|
||||
boolean updateRequired = false;
|
||||
|
||||
if (!isTest) {
|
||||
// find bitstream
|
||||
List<Bitstream> bitstreams = itemService.getNonInternalBitstreams(c, myItem);
|
||||
@@ -1538,6 +1705,45 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
System.out.println("\tSetting description for "
|
||||
+ bitstreamName);
|
||||
bs.setDescription(c, thisDescription);
|
||||
updateRequired = true;
|
||||
}
|
||||
|
||||
if (labelExists) {
|
||||
MetadataField metadataField = metadataFieldService
|
||||
.findByElement(c, METADATA_IIIF_SCHEMA, METADATA_IIIF_LABEL_ELEMENT, null);
|
||||
System.out.println("\tSetting label to " + thisLabel + " in element "
|
||||
+ metadataField.getElement() + " on " + bitstreamName);
|
||||
bitstreamService.addMetadata(c, bs, metadataField, null, thisLabel);
|
||||
updateRequired = true;
|
||||
}
|
||||
|
||||
if (heightExists) {
|
||||
MetadataField metadataField = metadataFieldService
|
||||
.findByElement(c, METADATA_IIIF_SCHEMA, METADATA_IIIF_IMAGE_ELEMENT,
|
||||
METADATA_IIIF_HEIGHT_QUALIFIER);
|
||||
System.out.println("\tSetting height to " + thisHeight + " in element "
|
||||
+ metadataField.getElement() + " on " + bitstreamName);
|
||||
bitstreamService.addMetadata(c, bs, metadataField, null, thisHeight);
|
||||
updateRequired = true;
|
||||
}
|
||||
if (widthExists) {
|
||||
MetadataField metadataField = metadataFieldService
|
||||
.findByElement(c, METADATA_IIIF_SCHEMA, METADATA_IIIF_IMAGE_ELEMENT,
|
||||
METADATA_IIIF_WIDTH_QUALIFIER);
|
||||
System.out.println("\tSetting width to " + thisWidth + " in element "
|
||||
+ metadataField.getElement() + " on " + bitstreamName);
|
||||
bitstreamService.addMetadata(c, bs, metadataField, null, thisWidth);
|
||||
updateRequired = true;
|
||||
}
|
||||
if (tocExists) {
|
||||
MetadataField metadataField = metadataFieldService
|
||||
.findByElement(c, METADATA_IIIF_SCHEMA, METADATA_IIIF_TOC_ELEMENT, null);
|
||||
System.out.println("\tSetting toc to " + thisToc + " in element "
|
||||
+ metadataField.getElement() + " on " + bitstreamName);
|
||||
bitstreamService.addMetadata(c, bs, metadataField, null, thisToc);
|
||||
updateRequired = true;
|
||||
}
|
||||
if (updateRequired) {
|
||||
bitstreamService.update(c, bs);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.content;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dspace.content.service.FeedbackService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.Email;
|
||||
import org.dspace.core.I18nUtil;
|
||||
|
||||
/**
|
||||
* Implementation of {@link FeedbackService} interface.
|
||||
* It is responsible for sendint a feedback email with content a DSpace user
|
||||
* fills from feedback section of DSpace.
|
||||
*/
|
||||
public class FeedbackServiceImpl implements FeedbackService {
|
||||
|
||||
@Override
|
||||
public void sendEmail(Context context, HttpServletRequest request, String recipientEmail, String senderEmail,
|
||||
String message, String page) throws IOException, MessagingException {
|
||||
String session = request.getHeader("x-correlation-id");
|
||||
String agent = request.getHeader("User-Agent");
|
||||
String currentUserEmail = StringUtils.EMPTY;
|
||||
|
||||
if (Objects.nonNull(context.getCurrentUser())) {
|
||||
currentUserEmail = context.getCurrentUser().getEmail();
|
||||
}
|
||||
Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "feedback"));
|
||||
email.addRecipient(recipientEmail);
|
||||
email.addArgument(new Date()); // Date
|
||||
email.addArgument(senderEmail); // Email
|
||||
email.addArgument(currentUserEmail); // Logged in as
|
||||
email.addArgument(page); // Referring page
|
||||
email.addArgument(agent); // User agent
|
||||
email.addArgument(session); // Session ID
|
||||
email.addArgument(message); // The feedback itself
|
||||
email.send();
|
||||
}
|
||||
|
||||
}
|
@@ -392,7 +392,7 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
|
||||
public Iterator<Item> findByLastModifiedSince(Context context, Date since)
|
||||
throws SQLException {
|
||||
Query query = createQuery(context,
|
||||
"SELECT i FROM item i WHERE last_modified > :last_modified ORDER BY id");
|
||||
"SELECT i FROM Item i WHERE last_modified > :last_modified ORDER BY id");
|
||||
query.setParameter("last_modified", since, TemporalType.TIMESTAMP);
|
||||
return iterate(query);
|
||||
}
|
||||
|
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.content.service;
|
||||
import java.io.IOException;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* Service interface class for the Feedback object.
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
public interface FeedbackService {
|
||||
|
||||
/**
|
||||
* This method sends the feeback email to the recipient passed as parameter
|
||||
* @param context current DSpace application context
|
||||
* @param request current servlet request
|
||||
* @param recipientEmail recipient to which mail is sent
|
||||
* @param senderEmail email address of the sender
|
||||
* @param message message body
|
||||
* @param page page from which user accessed and filled feedback form
|
||||
* @throws IOException
|
||||
* @throws MessagingException
|
||||
*/
|
||||
public void sendEmail(Context context, HttpServletRequest request, String recipientEmail, String senderEmail,
|
||||
String message, String page) throws IOException, MessagingException;
|
||||
|
||||
}
|
@@ -15,7 +15,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Bitstream;
|
||||
@@ -154,10 +153,10 @@ public class CitationPage extends AbstractCurationTask {
|
||||
.append(" is citable.");
|
||||
try {
|
||||
//Create the cited document
|
||||
Pair<InputStream, Long> citedDocument =
|
||||
citationDocument.makeCitedDocument(Curator.curationContext(), bitstream);
|
||||
InputStream citedInputStream =
|
||||
citationDocument.makeCitedDocument(Curator.curationContext(), bitstream).getLeft();
|
||||
//Add the cited document to the approiate bundle
|
||||
this.addCitedPageToItem(citedDocument.getLeft(), bundle, pBundle,
|
||||
this.addCitedPageToItem(citedInputStream, bundle, pBundle,
|
||||
dBundle, displayMap, item, bitstream);
|
||||
} catch (Exception e) {
|
||||
//Could be many things, but nothing that should be
|
||||
|
@@ -303,7 +303,12 @@ public class CitationDocumentServiceImpl implements CitationDocumentService, Ini
|
||||
PDDocument sourceDocument = new PDDocument();
|
||||
try {
|
||||
Item item = (Item) bitstreamService.getParentObject(context, bitstream);
|
||||
sourceDocument = sourceDocument.load(bitstreamService.retrieve(context, bitstream));
|
||||
final InputStream inputStream = bitstreamService.retrieve(context, bitstream);
|
||||
try {
|
||||
sourceDocument = sourceDocument.load(inputStream);
|
||||
} finally {
|
||||
inputStream.close();
|
||||
}
|
||||
PDPage coverPage = new PDPage(citationPageFormat);
|
||||
generateCoverPage(context, document, coverPage, item);
|
||||
addCoverPageToDocument(document, sourceDocument, coverPage);
|
||||
@@ -313,7 +318,7 @@ public class CitationDocumentServiceImpl implements CitationDocumentService, Ini
|
||||
document.save(out);
|
||||
|
||||
byte[] data = out.toByteArray();
|
||||
return Pair.of((InputStream) new ByteArrayInputStream(data), Long.valueOf(data.length));
|
||||
return Pair.of(new ByteArrayInputStream(data), Long.valueOf(data.length));
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
@@ -7,10 +7,10 @@
|
||||
*/
|
||||
package org.dspace.iiif.canvasdimension;
|
||||
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_HEIGHT;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_IMAGE;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_HEIGHT_QUALIFIER;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_IMAGE_ELEMENT;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_SCHEMA;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_WIDTH;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_WIDTH_QUALIFIER;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -62,7 +62,8 @@ public class IIIFCanvasDimensionServiceImpl implements IIIFCanvasDimensionServic
|
||||
private int processed = 0;
|
||||
|
||||
// used to check for existing canvas dimension
|
||||
private static final String IIIF_WIDTH_METADATA = "iiif.image.width";
|
||||
private static final String IIIF_WIDTH_METADATA = METADATA_IIIF_SCHEMA + "." + METADATA_IIIF_IMAGE_ELEMENT +
|
||||
"." + METADATA_IIIF_WIDTH_QUALIFIER;
|
||||
|
||||
@Override
|
||||
public void setForceProcessing(boolean force) {
|
||||
@@ -209,13 +210,13 @@ public class IIIFCanvasDimensionServiceImpl implements IIIFCanvasDimensionServic
|
||||
*/
|
||||
private boolean setBitstreamMetadata(Context context, Bitstream bitstream, int[] dims) throws SQLException {
|
||||
dSpaceObjectService.clearMetadata(context, bitstream, METADATA_IIIF_SCHEMA,
|
||||
METADATA_IIIF_IMAGE, METADATA_IIIF_WIDTH, Item.ANY);
|
||||
METADATA_IIIF_IMAGE_ELEMENT, METADATA_IIIF_WIDTH_QUALIFIER, Item.ANY);
|
||||
dSpaceObjectService.setMetadataSingleValue(context, bitstream, METADATA_IIIF_SCHEMA,
|
||||
METADATA_IIIF_IMAGE, METADATA_IIIF_WIDTH, null, String.valueOf(dims[0]));
|
||||
METADATA_IIIF_IMAGE_ELEMENT, METADATA_IIIF_WIDTH_QUALIFIER, null, String.valueOf(dims[0]));
|
||||
dSpaceObjectService.clearMetadata(context, bitstream, METADATA_IIIF_SCHEMA,
|
||||
METADATA_IIIF_IMAGE, METADATA_IIIF_HEIGHT, Item.ANY);
|
||||
METADATA_IIIF_IMAGE_ELEMENT, METADATA_IIIF_HEIGHT_QUALIFIER, Item.ANY);
|
||||
dSpaceObjectService.setMetadataSingleValue(context, bitstream, METADATA_IIIF_SCHEMA,
|
||||
METADATA_IIIF_IMAGE, METADATA_IIIF_HEIGHT, null, String.valueOf(dims[1]));
|
||||
METADATA_IIIF_IMAGE_ELEMENT, METADATA_IIIF_HEIGHT_QUALIFIER, null, String.valueOf(dims[1]));
|
||||
if (!isQuiet) {
|
||||
System.out.println("Added IIIF canvas metadata to bitstream: " + bitstream.getID());
|
||||
}
|
||||
|
@@ -36,9 +36,11 @@ public class IIIFSharedUtils {
|
||||
protected static final String IMAGE_SERVER_PATH = "iiif.image.server";
|
||||
// IIIF metadata definitions
|
||||
public static final String METADATA_IIIF_SCHEMA = "iiif";
|
||||
public static final String METADATA_IIIF_IMAGE = "image";
|
||||
public static final String METADATA_IIIF_HEIGHT = "height";
|
||||
public static final String METADATA_IIIF_WIDTH = "width";
|
||||
public static final String METADATA_IIIF_IMAGE_ELEMENT = "image";
|
||||
public static final String METADATA_IIIF_TOC_ELEMENT = "toc";
|
||||
public static final String METADATA_IIIF_LABEL_ELEMENT = "label";
|
||||
public static final String METADATA_IIIF_HEIGHT_QUALIFIER = "height";
|
||||
public static final String METADATA_IIIF_WIDTH_QUALIFIER = "width";
|
||||
|
||||
protected static final ConfigurationService configurationService
|
||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
|
@@ -7,10 +7,10 @@
|
||||
*/
|
||||
package org.dspace.app.iiif.service.utils;
|
||||
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_HEIGHT;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_IMAGE;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_HEIGHT_QUALIFIER;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_IMAGE_ELEMENT;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_SCHEMA;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_WIDTH;
|
||||
import static org.dspace.iiif.util.IIIFSharedUtils.METADATA_IIIF_WIDTH_QUALIFIER;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@@ -66,11 +66,11 @@ public class IIIFUtils {
|
||||
// metadata used to set the iiif viewing hint
|
||||
public static final String METADATA_IIIF_VIEWING_HINT = "iiif.viewing.hint";
|
||||
// metadata used to set the width of the canvas that has not an explicit name
|
||||
public static final String METADATA_IMAGE_WIDTH = METADATA_IIIF_SCHEMA + "." + METADATA_IIIF_IMAGE
|
||||
+ "." + METADATA_IIIF_WIDTH;
|
||||
public static final String METADATA_IMAGE_WIDTH = METADATA_IIIF_SCHEMA + "." + METADATA_IIIF_IMAGE_ELEMENT
|
||||
+ "." + METADATA_IIIF_WIDTH_QUALIFIER;
|
||||
// metadata used to set the height of the canvas that has not an explicit name
|
||||
public static final String METADATA_IMAGE_HEIGHT = METADATA_IIIF_SCHEMA + "." + METADATA_IIIF_IMAGE
|
||||
+ "." + METADATA_IIIF_HEIGHT;
|
||||
public static final String METADATA_IMAGE_HEIGHT = METADATA_IIIF_SCHEMA + "." + METADATA_IIIF_IMAGE_ELEMENT
|
||||
+ "." + METADATA_IIIF_HEIGHT_QUALIFIER;
|
||||
|
||||
// string used in the metadata toc as separator among the different levels
|
||||
public static final String TOC_SEPARATOR = "|||";
|
||||
|
@@ -38,6 +38,7 @@ import org.dspace.content.service.BitstreamFormatService;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.disseminate.service.CitationDocumentService;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.EventService;
|
||||
import org.dspace.usage.UsageEvent;
|
||||
@@ -108,6 +109,8 @@ public class BitstreamRestController {
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
|
||||
Bitstream bit = bitstreamService.find(context, uuid);
|
||||
EPerson currentUser = context.getCurrentUser();
|
||||
|
||||
if (bit == null) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return null;
|
||||
@@ -118,8 +121,6 @@ public class BitstreamRestController {
|
||||
String mimetype = format.getMIMEType();
|
||||
String name = getBitstreamName(bit, format);
|
||||
|
||||
Pair<InputStream, Long> bitstreamTuple = getBitstreamInputStreamAndSize(context, bit);
|
||||
|
||||
if (StringUtils.isBlank(request.getHeader("Range"))) {
|
||||
//We only log a download request when serving a request without Range header. This is because
|
||||
//a browser always sends a regular request first to check for Range support.
|
||||
@@ -131,14 +132,20 @@ public class BitstreamRestController {
|
||||
bit));
|
||||
}
|
||||
|
||||
// Pipe the bits
|
||||
InputStream is = bitstreamTuple.getLeft();
|
||||
try {
|
||||
HttpHeadersInitializer httpHeadersInitializer = HttpHeadersInitializer
|
||||
.fromInputStream(is)
|
||||
long filesize;
|
||||
if (citationDocumentService.isCitationEnabledForBitstream(bit, context)) {
|
||||
final Pair<InputStream, Long> citedDocument = citationDocumentService.makeCitedDocument(context, bit);
|
||||
filesize = citedDocument.getRight();
|
||||
citedDocument.getLeft().close();
|
||||
} else {
|
||||
filesize = bit.getSizeBytes();
|
||||
}
|
||||
|
||||
HttpHeadersInitializer httpHeadersInitializer = new HttpHeadersInitializer()
|
||||
.withBufferSize(BUFFER_SIZE)
|
||||
.withFileName(name)
|
||||
.withLength(bitstreamTuple.getRight())
|
||||
.withLength(filesize)
|
||||
.withChecksum(bit.getChecksum())
|
||||
.withMimetype(mimetype)
|
||||
.with(request)
|
||||
@@ -150,13 +157,15 @@ public class BitstreamRestController {
|
||||
|
||||
//Determine if we need to send the file as a download or if the browser can open it inline
|
||||
long dispositionThreshold = configurationService.getLongProperty("webui.content_disposition_threshold");
|
||||
if (dispositionThreshold >= 0 && bitstreamTuple.getRight() > dispositionThreshold) {
|
||||
if (dispositionThreshold >= 0 && filesize > dispositionThreshold) {
|
||||
httpHeadersInitializer.withDisposition(HttpHeadersInitializer.CONTENT_DISPOSITION_ATTACHMENT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
org.dspace.app.rest.utils.BitstreamResource bitstreamResource =
|
||||
new org.dspace.app.rest.utils.BitstreamResource(is, name, uuid, bit.getSizeBytes());
|
||||
new org.dspace.app.rest.utils.BitstreamResource(
|
||||
bit, name, uuid, filesize, currentUser != null ? currentUser.getID() : null);
|
||||
|
||||
//We have all the data we need, close the connection to the database so that it doesn't stay open during
|
||||
//download/streaming
|
||||
@@ -171,34 +180,12 @@ public class BitstreamRestController {
|
||||
} catch (ClientAbortException ex) {
|
||||
log.debug("Client aborted the request before the download was completed. " +
|
||||
"Client is probably switching to a Range request.", ex);
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Pair<InputStream, Long> getBitstreamInputStreamAndSize(Context context, Bitstream bit)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
|
||||
if (citationDocumentService.isCitationEnabledForBitstream(bit, context)) {
|
||||
return generateBitstreamWithCitation(context, bit);
|
||||
} else {
|
||||
return Pair.of(bitstreamService.retrieve(context, bit),bit.getSizeBytes());
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<InputStream, Long> generateBitstreamWithCitation(Context context, Bitstream bitstream)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
//Create the cited document
|
||||
Pair<InputStream, Long> citationDocument = citationDocumentService.makeCitedDocument(context, bitstream);
|
||||
if (citationDocument.getLeft() == null) {
|
||||
log.error("CitedDocument was null");
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("CitedDocument was ok, has size " + citationDocument.getRight());
|
||||
}
|
||||
}
|
||||
return citationDocument;
|
||||
}
|
||||
|
||||
private String getBitstreamName(Bitstream bit, BitstreamFormat format) {
|
||||
String name = bit.getName();
|
||||
if (name == null) {
|
||||
|
@@ -117,8 +117,7 @@ public class SitemapRestController {
|
||||
HttpServletRequest request) throws SQLException, IOException {
|
||||
// Pipe the bits
|
||||
try (InputStream is = new FileInputStream(foundSitemapFile)) {
|
||||
HttpHeadersInitializer sender = HttpHeadersInitializer
|
||||
.fromInputStream(is)
|
||||
HttpHeadersInitializer sender = new HttpHeadersInitializer()
|
||||
.withBufferSize(BUFFER_SIZE)
|
||||
.withFileName(foundSitemapFile.getName())
|
||||
.withLength(foundSitemapFile.length())
|
||||
|
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.authorization.impl;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||
import org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.app.rest.model.SiteRest;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* The send feedback feature. It can be used to verify if the parameter that contain
|
||||
* recipient e-mail is configured.
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
@Component
|
||||
@AuthorizationFeatureDocumentation(name = CanSendFeedbackFeature.NAME,
|
||||
description = "It can be used to verify if the parameter that contain recipient e-mail is configured.")
|
||||
public class CanSendFeedbackFeature implements AuthorizationFeature {
|
||||
|
||||
public static final String NAME = "canSendFeedback";
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||
String recipientEmail = configurationService.getProperty("feedback.recipient");
|
||||
return StringUtils.isNotBlank(recipientEmail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedTypes() {
|
||||
return new String[] { SiteRest.CATEGORY + "." + SiteRest.NAME };
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* When a request is malformed, we use this exception to indicate this to the client
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Not Found")
|
||||
public class DSpaceFeedbackNotFoundException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 4631940402294095433L;
|
||||
|
||||
public DSpaceFeedbackNotFoundException(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
public DSpaceFeedbackNotFoundException(String message, Exception e) {
|
||||
super(message, e);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
/**
|
||||
* The REST object for the Feedback objects
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
public class FeedbackRest extends BaseObjectRest<Integer> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final String NAME = "feedback";
|
||||
public static final String CATEGORY = RestAddressableModel.TOOLS;
|
||||
|
||||
private String page;
|
||||
private String email;
|
||||
private String message;
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(String page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* 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.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.exception.DSpaceFeedbackNotFoundException;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
import org.dspace.app.rest.model.FeedbackRest;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.service.FeedbackService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the Repository that takes care of the operations on the {@link FeedbackRest} objects
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
@Component(FeedbackRest.CATEGORY + "." + FeedbackRest.NAME)
|
||||
public class FeedbackRestRepository extends DSpaceRestRepository<FeedbackRest, Integer> {
|
||||
|
||||
@Autowired
|
||||
private FeedbackService feedbackService;
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||
public Page<FeedbackRest> findAll(Context context, Pageable pageable) {
|
||||
throw new RepositoryMethodNotImplementedException(FeedbackRest.NAME, "findAll");
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('AUTHENTICATED')")
|
||||
public FeedbackRest findOne(Context context, Integer id) {
|
||||
throw new RepositoryMethodNotImplementedException(FeedbackRest.NAME, "findOne");
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("permitAll()")
|
||||
protected FeedbackRest createAndReturn(Context context) throws AuthorizeException, SQLException {
|
||||
HttpServletRequest req = getRequestService().getCurrentRequest().getHttpServletRequest();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
FeedbackRest feedbackRest = null;
|
||||
|
||||
String recipientEmail = configurationService.getProperty("feedback.recipient");
|
||||
if (StringUtils.isBlank(recipientEmail)) {
|
||||
throw new DSpaceFeedbackNotFoundException("Feedback cannot be sent at this time, Feedback recipient " +
|
||||
"is disabled");
|
||||
}
|
||||
|
||||
try {
|
||||
feedbackRest = mapper.readValue(req.getInputStream(), FeedbackRest.class);
|
||||
} catch (IOException exIO) {
|
||||
throw new UnprocessableEntityException("error parsing the body " + exIO.getMessage(), exIO);
|
||||
}
|
||||
|
||||
String senderEmail = feedbackRest.getEmail();
|
||||
String message = feedbackRest.getMessage();
|
||||
|
||||
if (StringUtils.isBlank(senderEmail) || StringUtils.isBlank(message)) {
|
||||
throw new DSpaceBadRequestException("e-mail and message fields are mandatory!");
|
||||
}
|
||||
|
||||
try {
|
||||
feedbackService.sendEmail(context, req, recipientEmail, senderEmail, message, feedbackRest.getPage());
|
||||
} catch (IOException | MessagingException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<FeedbackRest> getDomainClass() {
|
||||
return FeedbackRest.class;
|
||||
}
|
||||
|
||||
public FeedbackService getFeedbackService() {
|
||||
return feedbackService;
|
||||
}
|
||||
|
||||
public void setFeedbackService(FeedbackService feedbackService) {
|
||||
this.feedbackService = feedbackService;
|
||||
}
|
||||
|
||||
}
|
@@ -9,8 +9,19 @@ package org.dspace.app.rest.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.disseminate.service.CitationDocumentService;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.springframework.core.io.AbstractResource;
|
||||
|
||||
/**
|
||||
@@ -21,16 +32,24 @@ import org.springframework.core.io.AbstractResource;
|
||||
*/
|
||||
public class BitstreamResource extends AbstractResource {
|
||||
|
||||
private InputStream inputStream;
|
||||
private Bitstream bitstream;
|
||||
private String name;
|
||||
private UUID uuid;
|
||||
private long sizeBytes;
|
||||
private UUID currentUserUUID;
|
||||
|
||||
public BitstreamResource(InputStream inputStream, String name, UUID uuid, long sizeBytes) {
|
||||
this.inputStream = inputStream;
|
||||
private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
|
||||
private EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
private CitationDocumentService citationDocumentService =
|
||||
new DSpace().getServiceManager()
|
||||
.getServicesByType(CitationDocumentService.class).get(0);
|
||||
|
||||
public BitstreamResource(Bitstream bitstream, String name, UUID uuid, long sizeBytes, UUID currentUserUUID) {
|
||||
this.bitstream = bitstream;
|
||||
this.name = name;
|
||||
this.uuid = uuid;
|
||||
this.sizeBytes = sizeBytes;
|
||||
this.currentUserUUID = currentUserUUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,7 +59,28 @@ public class BitstreamResource extends AbstractResource {
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return inputStream;
|
||||
Context context = new Context();
|
||||
try {
|
||||
EPerson currentUser = ePersonService.find(context, currentUserUUID);
|
||||
context.setCurrentUser(currentUser);
|
||||
InputStream out;
|
||||
|
||||
if (citationDocumentService.isCitationEnabledForBitstream(bitstream, context)) {
|
||||
out = citationDocumentService.makeCitedDocument(context, bitstream).getLeft();
|
||||
} else {
|
||||
out = bitstreamService.retrieve(context, bitstream);
|
||||
}
|
||||
|
||||
return out;
|
||||
} catch (SQLException | AuthorizeException e) {
|
||||
throw new IOException(e);
|
||||
} finally {
|
||||
try {
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -10,9 +10,7 @@ package org.dspace.app.rest.utils;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -64,7 +62,6 @@ public class HttpHeadersInitializer {
|
||||
//no-cache so request is always performed for logging
|
||||
private static final String CACHE_CONTROL_SETTING = "private,no-cache";
|
||||
|
||||
private BufferedInputStream inputStream;
|
||||
private HttpServletRequest request;
|
||||
private HttpServletResponse response;
|
||||
private String contentType;
|
||||
@@ -74,14 +71,8 @@ public class HttpHeadersInitializer {
|
||||
private String fileName;
|
||||
private String checksum;
|
||||
|
||||
public HttpHeadersInitializer(final InputStream inputStream) {
|
||||
public HttpHeadersInitializer() {
|
||||
//Convert to BufferedInputStream so we can re-read the stream
|
||||
this.inputStream = new BufferedInputStream(inputStream);
|
||||
}
|
||||
|
||||
|
||||
public static HttpHeadersInitializer fromInputStream(InputStream inputStream) {
|
||||
return new HttpHeadersInitializer(inputStream);
|
||||
}
|
||||
|
||||
public HttpHeadersInitializer with(HttpServletRequest httpRequest) {
|
||||
@@ -198,12 +189,6 @@ public class HttpHeadersInitializer {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inputStream == null) {
|
||||
log.error("Input stream has no content");
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(fileName)) {
|
||||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
return false;
|
||||
|
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* 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.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNotNull;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dspace.app.rest.model.FeedbackRest;
|
||||
import org.dspace.app.rest.repository.FeedbackRestRepository;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.content.FeedbackServiceImpl;
|
||||
import org.dspace.content.service.FeedbackService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Integration test class for the feedback endpoint
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk@4science.com)
|
||||
*/
|
||||
public class FeedbackRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
@Autowired
|
||||
private FeedbackRestRepository feedbackRestRepository;
|
||||
|
||||
@Test
|
||||
public void findAllTest() throws Exception {
|
||||
String authToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(authToken).perform(get("/api/tools/feedbacks"))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneTest() throws Exception {
|
||||
String authToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(authToken).perform(get("/api/tools/feedbacks/1"))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendFeedbackTest() throws Exception {
|
||||
configurationService.setProperty("feedback.recipient", "recipient.email@test.com");
|
||||
FeedbackService originFeedbackService = feedbackRestRepository.getFeedbackService();
|
||||
try {
|
||||
FeedbackService feedbackServiceMock = mock (FeedbackServiceImpl.class);
|
||||
feedbackRestRepository.setFeedbackService(feedbackServiceMock);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
FeedbackRest feedbackRest = new FeedbackRest();
|
||||
|
||||
feedbackRest.setEmail("misha.boychuk@test.com");
|
||||
feedbackRest.setMessage("My feedback!");
|
||||
|
||||
String authToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(authToken).perform(post("/api/tools/feedbacks")
|
||||
.content(mapper.writeValueAsBytes(feedbackRest))
|
||||
.contentType(contentType))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
verify(feedbackServiceMock).sendEmail(isNotNull(), isNotNull(), eq("recipient.email@test.com"),
|
||||
eq("misha.boychuk@test.com"), eq("My feedback!"), isNull());
|
||||
|
||||
verifyNoMoreInteractions(feedbackServiceMock);
|
||||
} finally {
|
||||
feedbackRestRepository.setFeedbackService(originFeedbackService);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendFeedbackWithRecipientEmailNotConfiguredTest() throws Exception {
|
||||
configurationService.setProperty("feedback.recipient", null);
|
||||
FeedbackService originFeedbackService = feedbackRestRepository.getFeedbackService();
|
||||
try {
|
||||
FeedbackService feedbackServiceMock = mock (FeedbackServiceImpl.class);
|
||||
feedbackRestRepository.setFeedbackService(feedbackServiceMock);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
FeedbackRest feedbackRest = new FeedbackRest();
|
||||
|
||||
feedbackRest.setEmail("misha.boychuk@test.com");
|
||||
feedbackRest.setMessage("My feedback!");
|
||||
|
||||
String authToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(authToken).perform(post("/api/tools/feedbacks")
|
||||
.content(mapper.writeValueAsBytes(feedbackRest))
|
||||
.contentType(contentType))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
verifyNoMoreInteractions(feedbackServiceMock);
|
||||
} finally {
|
||||
feedbackRestRepository.setFeedbackService(originFeedbackService);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendFeedbackBadRequestTest() throws Exception {
|
||||
FeedbackService originFeedbackService = feedbackRestRepository.getFeedbackService();
|
||||
try {
|
||||
FeedbackService feedbackServiceMock = mock (FeedbackServiceImpl.class);
|
||||
feedbackRestRepository.setFeedbackService(feedbackServiceMock);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
FeedbackRest feedbackRest = new FeedbackRest();
|
||||
|
||||
feedbackRest.setMessage("My feedback!");
|
||||
|
||||
String authToken = getAuthToken(admin.getEmail(), password);
|
||||
getClient(authToken).perform(post("/api/tools/feedbacks")
|
||||
.content(mapper.writeValueAsBytes(feedbackRest))
|
||||
.contentType(contentType))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
verifyNoMoreInteractions(feedbackServiceMock);
|
||||
} finally {
|
||||
feedbackRestRepository.setFeedbackService(originFeedbackService);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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.authorization;
|
||||
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.authorization.impl.CanSendFeedbackFeature;
|
||||
import org.dspace.app.rest.converter.SiteConverter;
|
||||
import org.dspace.app.rest.matcher.AuthorizationMatcher;
|
||||
import org.dspace.app.rest.model.SiteRest;
|
||||
import org.dspace.app.rest.projection.DefaultProjection;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.content.Site;
|
||||
import org.dspace.content.service.SiteService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Test for the canSendFeedback authorization feature.
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.com)
|
||||
*/
|
||||
public class CanSendFeedbackFeatureIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private SiteService siteService;
|
||||
@Autowired
|
||||
private SiteConverter siteConverter;
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
@Autowired
|
||||
private AuthorizationFeatureService authorizationFeatureService;
|
||||
|
||||
final String feature = "canSendFeedback";
|
||||
|
||||
private AuthorizationFeature canSendFeedbackFeature;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
canSendFeedbackFeature = authorizationFeatureService.find(CanSendFeedbackFeature.NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSendFeedbackFeatureTest() throws Exception {
|
||||
configurationService.setProperty("feedback.recipient", "myemail@test.com");
|
||||
|
||||
Site site = siteService.findSite(context);
|
||||
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
|
||||
|
||||
String tokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
// define authorizations
|
||||
Authorization authAdminSite = new Authorization(admin, canSendFeedbackFeature, siteRest);
|
||||
Authorization authAnonymousSite = new Authorization(null, canSendFeedbackFeature, siteRest);
|
||||
Authorization authEPersonSite = new Authorization(eperson, canSendFeedbackFeature, siteRest);
|
||||
|
||||
getClient(tokenAdmin).perform(get("/api/authz/authorizations/" + authAdminSite.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(
|
||||
AuthorizationMatcher.matchAuthorization(authAdminSite))));
|
||||
|
||||
getClient(tokenEperson).perform(get("/api/authz/authorizations/" + authEPersonSite.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(
|
||||
AuthorizationMatcher.matchAuthorization(authEPersonSite))));
|
||||
|
||||
getClient().perform(get("/api/authz/authorizations/" + authAnonymousSite.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(
|
||||
AuthorizationMatcher.matchAuthorization(authAnonymousSite))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canSendFeedbackFeatureWithRecipientEmailNotConfiguredTest() throws Exception {
|
||||
configurationService.setProperty("feedback.recipient", null);
|
||||
|
||||
Site site = siteService.findSite(context);
|
||||
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
|
||||
|
||||
String tokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
// define authorizations
|
||||
Authorization authAdminSite = new Authorization(admin, canSendFeedbackFeature, siteRest);
|
||||
Authorization authAnonymousSite = new Authorization(null, canSendFeedbackFeature, siteRest);
|
||||
Authorization authEPersonSite = new Authorization(eperson, canSendFeedbackFeature, siteRest);
|
||||
|
||||
getClient(tokenAdmin).perform(get("/api/authz/authorizations/" + authAdminSite.getID()))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
getClient(tokenEperson).perform(get("/api/authz/authorizations/" + authEPersonSite.getID()))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
getClient().perform(get("/api/authz/authorizations/" + authAnonymousSite.getID()))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
}
|
@@ -157,7 +157,7 @@ mail.from.address = dspace-noreply@myu.edu
|
||||
|
||||
# When feedback is submitted via the Feedback form, it is sent to this address
|
||||
# Currently limited to one recipient!
|
||||
# TODO: UNSUPPORTED in DSpace 7.0
|
||||
# if this property is empty or commented out, feedback form is disabled
|
||||
feedback.recipient = dspace-help@myu.edu
|
||||
|
||||
# General site administration (Webmaster) e-mail
|
||||
|
@@ -69,7 +69,8 @@ iiif.license.uri = dc.rights.uri
|
||||
# static text to be used as attribution in the iiif manifests
|
||||
iiif.attribution = ${dspace.name}
|
||||
|
||||
# URL for logo. If defined, the logo will be added to the manifest.
|
||||
# URL for logo. A small image that represents an individual or organization associated with the
|
||||
# resource. It is added to the IIIF manifest.
|
||||
iiif.logo.image = ${dspace.ui.url}/assets/images/dspace-logo.svg
|
||||
|
||||
# (optional) one of individuals, paged or continuous. Can be overridden at the item level via
|
||||
|
@@ -55,6 +55,7 @@
|
||||
<bean class="org.dspace.content.EntityServiceImpl"/>
|
||||
<bean class="org.dspace.content.RelationshipTypeServiceImpl"/>
|
||||
<bean class="org.dspace.content.RelationshipMetadataServiceImpl"/>
|
||||
<bean class="org.dspace.content.FeedbackServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.scripts.ProcessServiceImpl"/>
|
||||
<bean class="org.dspace.scripts.ScriptServiceImpl"/>
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
<!-- HelpDesk to instead get RequestItem emails-->
|
||||
<!--<bean class="org.dspace.app.requestitem.RequestItemHelpdeskStrategy"
|
||||
id="org.dspace.app.requestitem.RequestItemAuthorExtractor"></bean>-->
|
||||
id="org.dspace.app.requestitem.RequestItemAuthorExtractor"
|
||||
autowire-candidate='true'></bean>-->
|
||||
|
||||
</beans>
|
||||
|
Reference in New Issue
Block a user