mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-18 15:33:09 +00:00
Merge pull request #2115 from mwoodiupui/DS-3951
[DS-3951] Send Request Copy email to multiple recipients, and some new recipient strategies
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive request recipients from groups of the Collection which owns an Item.
|
||||||
|
* The list will include all members of the administrators group. If the
|
||||||
|
* resulting list is empty, delegates to {@link RequestItemHelpdeskStrategy}.
|
||||||
|
*
|
||||||
|
* @author Mark H. Wood <mwood@iupui.edu>
|
||||||
|
*/
|
||||||
|
public class CollectionAdministratorsRequestItemStrategy
|
||||||
|
extends RequestItemHelpdeskStrategy {
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context,
|
||||||
|
Item item)
|
||||||
|
throws SQLException {
|
||||||
|
List<RequestItemAuthor> recipients = new ArrayList<>();
|
||||||
|
Collection collection = item.getOwningCollection();
|
||||||
|
for (EPerson admin : collection.getAdministrators().getMembers()) {
|
||||||
|
recipients.add(new RequestItemAuthor(admin));
|
||||||
|
}
|
||||||
|
if (recipients.isEmpty()) {
|
||||||
|
return super.getRequestItemAuthor(context, item);
|
||||||
|
} else {
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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.app.requestitem;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assemble a list of recipients from the results of other strategies.
|
||||||
|
* The list of strategy classes is injected as the constructor argument
|
||||||
|
* {@code strategies}.
|
||||||
|
* If the strategy list is not configured, returns an empty List.
|
||||||
|
*
|
||||||
|
* @author Mark H. Wood <mwood@iupui.edu>
|
||||||
|
*/
|
||||||
|
public class CombiningRequestItemStrategy
|
||||||
|
implements RequestItemAuthorExtractor {
|
||||||
|
/** The strategies to combine. */
|
||||||
|
private final List<RequestItemAuthorExtractor> strategies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a combination of strategies.
|
||||||
|
* @param strategies the author extraction strategies to combine.
|
||||||
|
*/
|
||||||
|
public CombiningRequestItemStrategy(@NonNull List<RequestItemAuthorExtractor> strategies) {
|
||||||
|
Assert.notNull(strategies, "Strategy list may not be null");
|
||||||
|
this.strategies = strategies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call.
|
||||||
|
* @throws IllegalArgumentException always
|
||||||
|
*/
|
||||||
|
private CombiningRequestItemStrategy() {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
|
throws SQLException {
|
||||||
|
List<RequestItemAuthor> recipients = new ArrayList<>();
|
||||||
|
|
||||||
|
for (RequestItemAuthorExtractor strategy : strategies) {
|
||||||
|
recipients.addAll(strategy.getRequestItemAuthor(context, item));
|
||||||
|
}
|
||||||
|
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
}
|
@@ -27,7 +27,7 @@ import org.dspace.core.Context;
|
|||||||
import org.dspace.core.ReloadableEntity;
|
import org.dspace.core.ReloadableEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object representing an Item Request
|
* Object representing an Item Request.
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "requestitem")
|
@Table(name = "requestitem")
|
||||||
@@ -94,6 +94,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.allfiles = allfiles;
|
this.allfiles = allfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if all of the Item's files are requested.
|
||||||
|
*/
|
||||||
public boolean isAllfiles() {
|
public boolean isAllfiles() {
|
||||||
return allfiles;
|
return allfiles;
|
||||||
}
|
}
|
||||||
@@ -102,6 +105,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.reqMessage = reqMessage;
|
this.reqMessage = reqMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a message from the requester.
|
||||||
|
*/
|
||||||
public String getReqMessage() {
|
public String getReqMessage() {
|
||||||
return reqMessage;
|
return reqMessage;
|
||||||
}
|
}
|
||||||
@@ -110,6 +116,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.reqName = reqName;
|
this.reqName = reqName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Human-readable name of the user requesting access.
|
||||||
|
*/
|
||||||
public String getReqName() {
|
public String getReqName() {
|
||||||
return reqName;
|
return reqName;
|
||||||
}
|
}
|
||||||
@@ -118,6 +127,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.reqEmail = reqEmail;
|
this.reqEmail = reqEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return address of the user requesting access.
|
||||||
|
*/
|
||||||
public String getReqEmail() {
|
public String getReqEmail() {
|
||||||
return reqEmail;
|
return reqEmail;
|
||||||
}
|
}
|
||||||
@@ -126,6 +138,9 @@ public class RequestItem implements ReloadableEntity<Integer> {
|
|||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a unique request identifier which can be emailed.
|
||||||
|
*/
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
@@ -11,20 +11,31 @@ import org.dspace.eperson.EPerson;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple DTO to transfer data about the corresponding author for the Request
|
* Simple DTO to transfer data about the corresponding author for the Request
|
||||||
* Copy feature
|
* Copy feature.
|
||||||
*
|
*
|
||||||
* @author Andrea Bollini
|
* @author Andrea Bollini
|
||||||
*/
|
*/
|
||||||
public class RequestItemAuthor {
|
public class RequestItemAuthor {
|
||||||
private String fullName;
|
private final String fullName;
|
||||||
private String email;
|
private final String email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an author record from given data.
|
||||||
|
*
|
||||||
|
* @param fullName the author's full name.
|
||||||
|
* @param email the author's email address.
|
||||||
|
*/
|
||||||
public RequestItemAuthor(String fullName, String email) {
|
public RequestItemAuthor(String fullName, String email) {
|
||||||
super();
|
super();
|
||||||
this.fullName = fullName;
|
this.fullName = fullName;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an author from an EPerson's metadata.
|
||||||
|
*
|
||||||
|
* @param ePerson the EPerson.
|
||||||
|
*/
|
||||||
public RequestItemAuthor(EPerson ePerson) {
|
public RequestItemAuthor(EPerson ePerson) {
|
||||||
super();
|
super();
|
||||||
this.fullName = ePerson.getFullName();
|
this.fullName = ePerson.getFullName();
|
||||||
|
@@ -8,26 +8,28 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to abstract the strategy for select the author to contact for
|
* Interface to abstract the strategy for selecting the author to contact for
|
||||||
* request copy
|
* request copy.
|
||||||
*
|
*
|
||||||
* @author Andrea Bollini
|
* @author Andrea Bollini
|
||||||
*/
|
*/
|
||||||
public interface RequestItemAuthorExtractor {
|
public interface RequestItemAuthorExtractor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the auhtor to contact for a request copy of the give item.
|
* Retrieve the author to contact for requesting a copy of the given item.
|
||||||
*
|
*
|
||||||
* @param context DSpace context object
|
* @param context DSpace context object
|
||||||
* @param item item to request
|
* @param item item to request
|
||||||
* @return An object containing name an email address to send the request to
|
* @return Names and email addresses to send the request to.
|
||||||
* or null if no valid email address was found.
|
|
||||||
* @throws SQLException if database error
|
* @throws SQLException if database error
|
||||||
*/
|
*/
|
||||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException;
|
@NonNull
|
||||||
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
|
throws SQLException;
|
||||||
}
|
}
|
||||||
|
@@ -72,28 +72,48 @@ public class RequestItemEmailNotifier {
|
|||||||
static public void sendRequest(Context context, RequestItem ri, String responseLink)
|
static public void sendRequest(Context context, RequestItem ri, String responseLink)
|
||||||
throws IOException, SQLException {
|
throws IOException, SQLException {
|
||||||
// Who is making this request?
|
// Who is making this request?
|
||||||
RequestItemAuthor author = requestItemAuthorExtractor
|
List<RequestItemAuthor> authors = requestItemAuthorExtractor
|
||||||
.getRequestItemAuthor(context, ri.getItem());
|
.getRequestItemAuthor(context, ri.getItem());
|
||||||
String authorEmail = author.getEmail();
|
|
||||||
String authorName = author.getFullName();
|
|
||||||
|
|
||||||
// Build an email to the approver.
|
// Build an email to the approver.
|
||||||
Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(),
|
Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(),
|
||||||
"request_item.author"));
|
"request_item.author"));
|
||||||
email.addRecipient(authorEmail);
|
for (RequestItemAuthor author : authors) {
|
||||||
|
email.addRecipient(author.getEmail());
|
||||||
|
}
|
||||||
email.setReplyTo(ri.getReqEmail()); // Requester's address
|
email.setReplyTo(ri.getReqEmail()); // Requester's address
|
||||||
|
|
||||||
email.addArgument(ri.getReqName()); // {0} Requester's name
|
email.addArgument(ri.getReqName()); // {0} Requester's name
|
||||||
|
|
||||||
email.addArgument(ri.getReqEmail()); // {1} Requester's address
|
email.addArgument(ri.getReqEmail()); // {1} Requester's address
|
||||||
|
|
||||||
email.addArgument(ri.isAllfiles() // {2} All bitstreams or just one?
|
email.addArgument(ri.isAllfiles() // {2} All bitstreams or just one?
|
||||||
? I18nUtil.getMessage("itemRequest.all") : ri.getBitstream().getName());
|
? I18nUtil.getMessage("itemRequest.all") : ri.getBitstream().getName());
|
||||||
email.addArgument(handleService.getCanonicalForm(ri.getItem().getHandle()));
|
|
||||||
|
email.addArgument(handleService.getCanonicalForm(ri.getItem().getHandle())); // {3}
|
||||||
|
|
||||||
email.addArgument(ri.getItem().getName()); // {4} requested item's title
|
email.addArgument(ri.getItem().getName()); // {4} requested item's title
|
||||||
|
|
||||||
email.addArgument(ri.getReqMessage()); // {5} message from requester
|
email.addArgument(ri.getReqMessage()); // {5} message from requester
|
||||||
|
|
||||||
email.addArgument(responseLink); // {6} Link back to DSpace for action
|
email.addArgument(responseLink); // {6} Link back to DSpace for action
|
||||||
email.addArgument(authorName); // {7} corresponding author name
|
|
||||||
email.addArgument(authorEmail); // {8} corresponding author email
|
StringBuilder names = new StringBuilder();
|
||||||
email.addArgument(configurationService.getProperty("dspace.name"));
|
StringBuilder addresses = new StringBuilder();
|
||||||
email.addArgument(configurationService.getProperty("mail.helpdesk"));
|
for (RequestItemAuthor author : authors) {
|
||||||
|
if (names.length() > 0) {
|
||||||
|
names.append("; ");
|
||||||
|
addresses.append("; ");
|
||||||
|
}
|
||||||
|
names.append(author.getFullName());
|
||||||
|
addresses.append(author.getEmail());
|
||||||
|
}
|
||||||
|
email.addArgument(names.toString()); // {7} corresponding author name
|
||||||
|
email.addArgument(addresses.toString()); // {8} corresponding author email
|
||||||
|
|
||||||
|
email.addArgument(configurationService.getProperty("dspace.name")); // {9}
|
||||||
|
|
||||||
|
email.addArgument(configurationService.getProperty("mail.helpdesk")); // {10}
|
||||||
|
|
||||||
// Send the email.
|
// Send the email.
|
||||||
try {
|
try {
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
@@ -16,11 +18,11 @@ import org.dspace.core.I18nUtil;
|
|||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.service.EPersonService;
|
import org.dspace.eperson.service.EPersonService;
|
||||||
import org.dspace.services.ConfigurationService;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RequestItem strategy to allow DSpace support team's helpdesk to receive requestItem request
|
* RequestItem strategy to allow DSpace support team's helpdesk to receive requestItem request.
|
||||||
* With this enabled, then the Item author/submitter doesn't receive the request, but the helpdesk instead does.
|
* With this enabled, then the Item author/submitter doesn't receive the request, but the helpdesk instead does.
|
||||||
*
|
*
|
||||||
* Failover to the RequestItemSubmitterStrategy, which means the submitter would get the request if there is no
|
* Failover to the RequestItemSubmitterStrategy, which means the submitter would get the request if there is no
|
||||||
@@ -33,19 +35,24 @@ public class RequestItemHelpdeskStrategy extends RequestItemSubmitterStrategy {
|
|||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected EPersonService ePersonService;
|
protected EPersonService ePersonService;
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
private ConfigurationService configuration;
|
||||||
|
|
||||||
public RequestItemHelpdeskStrategy() {
|
public RequestItemHelpdeskStrategy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException {
|
@NonNull
|
||||||
ConfigurationService configurationService
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
= DSpaceServicesFactory.getInstance().getConfigurationService();
|
throws SQLException {
|
||||||
boolean helpdeskOverridesSubmitter = configurationService
|
boolean helpdeskOverridesSubmitter = configuration
|
||||||
.getBooleanProperty("request.item.helpdesk.override", false);
|
.getBooleanProperty("request.item.helpdesk.override", false);
|
||||||
String helpDeskEmail = configurationService.getProperty("mail.helpdesk");
|
String helpDeskEmail = configuration.getProperty("mail.helpdesk");
|
||||||
|
|
||||||
if (helpdeskOverridesSubmitter && StringUtils.isNotBlank(helpDeskEmail)) {
|
if (helpdeskOverridesSubmitter && StringUtils.isNotBlank(helpDeskEmail)) {
|
||||||
return getHelpDeskPerson(context, helpDeskEmail);
|
List<RequestItemAuthor> authors = new ArrayList<>(1);
|
||||||
|
authors.add(getHelpDeskPerson(context, helpDeskEmail));
|
||||||
|
return authors;
|
||||||
} else {
|
} else {
|
||||||
//Fallback to default logic (author of Item) if helpdesk isn't fully enabled or setup
|
//Fallback to default logic (author of Item) if helpdesk isn't fully enabled or setup
|
||||||
return super.getRequestItemAuthor(context, item);
|
return super.getRequestItemAuthor(context, item);
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -16,12 +18,13 @@ import org.dspace.content.MetadataValue;
|
|||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.core.I18nUtil;
|
import org.dspace.core.I18nUtil;
|
||||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
import org.dspace.services.ConfigurationService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to look to an item metadata for the corresponding author name and email.
|
* Try to look to an item metadata for the corresponding author name and email.
|
||||||
* Failover to the RequestItemSubmitterStrategy
|
* Failover to the RequestItemSubmitterStrategy.
|
||||||
*
|
*
|
||||||
* @author Andrea Bollini
|
* @author Andrea Bollini
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +33,9 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
|
|||||||
protected String emailMetadata;
|
protected String emailMetadata;
|
||||||
protected String fullNameMetadata;
|
protected String fullNameMetadata;
|
||||||
|
|
||||||
|
@Autowired(required = true)
|
||||||
|
protected ConfigurationService configurationService;
|
||||||
|
|
||||||
@Autowired(required = true)
|
@Autowired(required = true)
|
||||||
protected ItemService itemService;
|
protected ItemService itemService;
|
||||||
|
|
||||||
@@ -37,59 +43,72 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
|
@NonNull
|
||||||
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
RequestItemAuthor author = null;
|
List<RequestItemAuthor> authors;
|
||||||
if (emailMetadata != null) {
|
if (emailMetadata != null) {
|
||||||
List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata);
|
List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata);
|
||||||
if (vals.size() > 0) {
|
List<MetadataValue> nameVals;
|
||||||
String email = vals.iterator().next().getValue();
|
if (null != fullNameMetadata) {
|
||||||
String fullname = null;
|
nameVals = itemService.getMetadataByMetadataString(item, fullNameMetadata);
|
||||||
if (fullNameMetadata != null) {
|
} else {
|
||||||
List<MetadataValue> nameVals = itemService.getMetadataByMetadataString(item, fullNameMetadata);
|
nameVals = Collections.EMPTY_LIST;
|
||||||
if (nameVals.size() > 0) {
|
}
|
||||||
fullname = nameVals.iterator().next().getValue();
|
boolean useNames = vals.size() == nameVals.size();
|
||||||
|
if (!vals.isEmpty()) {
|
||||||
|
authors = new ArrayList<>(vals.size());
|
||||||
|
for (int authorIndex = 0; authorIndex < vals.size(); authorIndex++) {
|
||||||
|
String email = vals.get(authorIndex).getValue();
|
||||||
|
String fullname = null;
|
||||||
|
if (useNames) {
|
||||||
|
fullname = nameVals.get(authorIndex).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(fullname)) {
|
||||||
|
fullname = I18nUtil.getMessage(
|
||||||
|
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
RequestItemAuthor author = new RequestItemAuthor(
|
||||||
|
fullname, email);
|
||||||
|
authors.add(author);
|
||||||
}
|
}
|
||||||
if (StringUtils.isBlank(fullname)) {
|
return authors;
|
||||||
fullname = I18nUtil
|
} else {
|
||||||
.getMessage(
|
return Collections.EMPTY_LIST;
|
||||||
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
|
|
||||||
context);
|
|
||||||
}
|
|
||||||
author = new RequestItemAuthor(fullname, email);
|
|
||||||
return author;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Uses the basic strategy to look for the original submitter
|
// Uses the basic strategy to look for the original submitter
|
||||||
author = super.getRequestItemAuthor(context, item);
|
authors = super.getRequestItemAuthor(context, item);
|
||||||
// Is the author or their email null. If so get the help desk or admin name and email
|
|
||||||
if (null == author || null == author.getEmail()) {
|
// Remove from the list authors that do not have email addresses.
|
||||||
String email = null;
|
for (RequestItemAuthor author : authors) {
|
||||||
String name = null;
|
if (null == author.getEmail()) {
|
||||||
|
authors.remove(author);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authors.isEmpty()) { // No author email addresses! Fall back
|
||||||
//First get help desk name and email
|
//First get help desk name and email
|
||||||
email = DSpaceServicesFactory.getInstance()
|
String email = configurationService.getProperty("mail.helpdesk");
|
||||||
.getConfigurationService().getProperty("mail.helpdesk");
|
String name = configurationService.getProperty("mail.helpdesk.name");
|
||||||
name = DSpaceServicesFactory.getInstance()
|
|
||||||
.getConfigurationService().getProperty("mail.helpdesk.name");
|
|
||||||
// If help desk mail is null get the mail and name of admin
|
// If help desk mail is null get the mail and name of admin
|
||||||
if (email == null) {
|
if (email == null) {
|
||||||
email = DSpaceServicesFactory.getInstance()
|
email = configurationService.getProperty("mail.admin");
|
||||||
.getConfigurationService().getProperty("mail.admin");
|
name = configurationService.getProperty("mail.admin.name");
|
||||||
name = DSpaceServicesFactory.getInstance()
|
|
||||||
.getConfigurationService().getProperty("mail.admin.name");
|
|
||||||
}
|
}
|
||||||
author = new RequestItemAuthor(name, email);
|
authors.add(new RequestItemAuthor(name, email));
|
||||||
}
|
}
|
||||||
|
return authors;
|
||||||
}
|
}
|
||||||
return author;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEmailMetadata(String emailMetadata) {
|
public void setEmailMetadata(@NonNull String emailMetadata) {
|
||||||
this.emailMetadata = emailMetadata;
|
this.emailMetadata = emailMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFullNameMetadata(String fullNameMetadata) {
|
public void setFullNameMetadata(@NonNull String fullNameMetadata) {
|
||||||
this.fullNameMetadata = fullNameMetadata;
|
this.fullNameMetadata = fullNameMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,10 +8,13 @@
|
|||||||
package org.dspace.app.requestitem;
|
package org.dspace.app.requestitem;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic strategy that looks to the original submitter.
|
* Basic strategy that looks to the original submitter.
|
||||||
@@ -24,21 +27,23 @@ public class RequestItemSubmitterStrategy implements RequestItemAuthorExtractor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the submitter of an Item as RequestItemAuthor or null if the
|
* Returns the submitter of an Item as RequestItemAuthor or an empty List if
|
||||||
* Submitter is deleted.
|
* the Submitter is deleted.
|
||||||
*
|
*
|
||||||
* @return The submitter of the item or null if the submitter is deleted
|
* @return The submitter of the item or empty List if the submitter is deleted
|
||||||
* @throws SQLException if database error
|
* @throws SQLException if database error
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
|
@NonNull
|
||||||
|
public List<RequestItemAuthor> getRequestItemAuthor(Context context, Item item)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
EPerson submitter = item.getSubmitter();
|
EPerson submitter = item.getSubmitter();
|
||||||
RequestItemAuthor author = null;
|
List<RequestItemAuthor> authors = new ArrayList<>(1);
|
||||||
if (null != submitter) {
|
if (null != submitter) {
|
||||||
author = new RequestItemAuthor(
|
RequestItemAuthor author = new RequestItemAuthor(
|
||||||
submitter.getFullName(), submitter.getEmail());
|
submitter.getFullName(), submitter.getEmail());
|
||||||
|
authors.add(author);
|
||||||
}
|
}
|
||||||
return author;
|
return authors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* 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.requestitem;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.eperson.Group;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Mark H. Wood <mwood@iupui.edu>
|
||||||
|
*/
|
||||||
|
public class CollectionAdministratorsRequestItemStrategyTest {
|
||||||
|
private static final String NAME = "John Q. Public";
|
||||||
|
private static final String EMAIL = "jqpublic@example.com";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of getRequestItemAuthor method, of class CollectionAdministratorsRequestItemStrategy.
|
||||||
|
* @throws java.lang.Exception passed through.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetRequestItemAuthor()
|
||||||
|
throws Exception {
|
||||||
|
System.out.println("getRequestItemAuthor");
|
||||||
|
|
||||||
|
Context context = Mockito.mock(Context.class);
|
||||||
|
|
||||||
|
EPerson eperson1 = Mockito.mock(EPerson.class);
|
||||||
|
Mockito.when(eperson1.getEmail()).thenReturn(EMAIL);
|
||||||
|
Mockito.when(eperson1.getFullName()).thenReturn(NAME);
|
||||||
|
|
||||||
|
Group group1 = Mockito.mock(Group.class);
|
||||||
|
Mockito.when(group1.getMembers()).thenReturn(List.of(eperson1));
|
||||||
|
|
||||||
|
Collection collection1 = Mockito.mock(Collection.class);
|
||||||
|
Mockito.when(collection1.getAdministrators()).thenReturn(group1);
|
||||||
|
|
||||||
|
Item item = Mockito.mock(Item.class);
|
||||||
|
Mockito.when(item.getOwningCollection()).thenReturn(collection1);
|
||||||
|
Mockito.when(item.getSubmitter()).thenReturn(eperson1);
|
||||||
|
|
||||||
|
CollectionAdministratorsRequestItemStrategy instance = new CollectionAdministratorsRequestItemStrategy();
|
||||||
|
List<RequestItemAuthor> result = instance.getRequestItemAuthor(context,
|
||||||
|
item);
|
||||||
|
assertEquals("Should be one author", 1, result.size());
|
||||||
|
assertEquals("Name should match " + NAME, NAME, result.get(0).getFullName());
|
||||||
|
assertEquals("Email should match " + EMAIL, EMAIL, result.get(0).getEmail());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* 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.requestitem;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Mark H. Wood <mwood@iupui.edu>
|
||||||
|
*/
|
||||||
|
public class CombiningRequestItemStrategyTest {
|
||||||
|
/**
|
||||||
|
* Test of getRequestItemAuthor method, of class CombiningRequestItemStrategy.
|
||||||
|
* @throws java.lang.Exception passed through.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetRequestItemAuthor()
|
||||||
|
throws Exception {
|
||||||
|
System.out.println("getRequestItemAuthor");
|
||||||
|
Context context = null;
|
||||||
|
|
||||||
|
Item item = Mockito.mock(Item.class);
|
||||||
|
RequestItemAuthor author1 = new RequestItemAuthor("Pat Paulsen", "ppaulsen@example.com");
|
||||||
|
RequestItemAuthor author2 = new RequestItemAuthor("Alfred E. Neuman", "aeneuman@example.com");
|
||||||
|
RequestItemAuthor author3 = new RequestItemAuthor("Alias Undercover", "aundercover@example.com");
|
||||||
|
|
||||||
|
RequestItemAuthorExtractor strategy1 = Mockito.mock(RequestItemHelpdeskStrategy.class);
|
||||||
|
Mockito.when(strategy1.getRequestItemAuthor(context, item)).thenReturn(List.of(author1));
|
||||||
|
|
||||||
|
RequestItemAuthorExtractor strategy2 = Mockito.mock(RequestItemMetadataStrategy.class);
|
||||||
|
Mockito.when(strategy2.getRequestItemAuthor(context, item)).thenReturn(List.of(author2, author3));
|
||||||
|
|
||||||
|
List<RequestItemAuthorExtractor> strategies = List.of(strategy1, strategy2);
|
||||||
|
|
||||||
|
CombiningRequestItemStrategy instance = new CombiningRequestItemStrategy(strategies);
|
||||||
|
List<RequestItemAuthor> result = instance.getRequestItemAuthor(context,
|
||||||
|
item);
|
||||||
|
assertThat(result, containsInAnyOrder(author1, author2, author3));
|
||||||
|
}
|
||||||
|
}
|
@@ -15,7 +15,9 @@ import java.net.MalformedURLException;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@@ -229,14 +231,20 @@ public class RequestItemRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for authorized user
|
// Check for authorized user
|
||||||
RequestItemAuthor authorizer;
|
List<RequestItemAuthor> authorizers;
|
||||||
try {
|
try {
|
||||||
authorizer = requestItemAuthorExtractor.getRequestItemAuthor(context, ri.getItem());
|
authorizers = requestItemAuthorExtractor.getRequestItemAuthor(context, ri.getItem());
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOG.warn("Failed to find an authorizer: {}", ex.getMessage());
|
LOG.warn("Failed to find an authorizer: {}", ex.getMessage());
|
||||||
authorizer = new RequestItemAuthor("", "");
|
authorizers = Collections.EMPTY_LIST;
|
||||||
}
|
}
|
||||||
if (!authorizer.getEmail().equals(context.getCurrentUser().getEmail())) {
|
|
||||||
|
boolean authorized = false;
|
||||||
|
String requester = context.getCurrentUser().getEmail();
|
||||||
|
for (RequestItemAuthor authorizer : authorizers) {
|
||||||
|
authorized |= authorizer.getEmail().equals(requester);
|
||||||
|
}
|
||||||
|
if (!authorized) {
|
||||||
throw new AuthorizeException("Not authorized to approve this request");
|
throw new AuthorizeException("Not authorized to approve this request");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -142,10 +142,10 @@ public class DeleteEPersonSubmitterIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
|
|
||||||
Item item = itemService.find(context, installItem.getID());
|
Item item = itemService.find(context, installItem.getID());
|
||||||
RequestItemAuthor requestItemAuthor = requestItemAuthorExtractor.getRequestItemAuthor(context, item);
|
List<RequestItemAuthor> requestItemAuthor = requestItemAuthorExtractor.getRequestItemAuthor(context, item);
|
||||||
|
|
||||||
assertEquals("Help Desk", requestItemAuthor.getFullName());
|
assertEquals("Help Desk", requestItemAuthor.get(0).getFullName());
|
||||||
assertEquals("dspace-help@myu.edu", requestItemAuthor.getEmail());
|
assertEquals("dspace-help@myu.edu", requestItemAuthor.get(0).getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +171,7 @@ public class DeleteEPersonSubmitterIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
Item item = installItemService.installItem(context, wsi);
|
Item item = installItemService.installItem(context, wsi);
|
||||||
|
|
||||||
List<Operation> opsToWithDraw = new ArrayList<Operation>();
|
List<Operation> opsToWithDraw = new ArrayList<>();
|
||||||
ReplaceOperation replaceOperationToWithDraw = new ReplaceOperation("/withdrawn", true);
|
ReplaceOperation replaceOperationToWithDraw = new ReplaceOperation("/withdrawn", true);
|
||||||
opsToWithDraw.add(replaceOperationToWithDraw);
|
opsToWithDraw.add(replaceOperationToWithDraw);
|
||||||
String patchBodyToWithdraw = getPatchContent(opsToWithDraw);
|
String patchBodyToWithdraw = getPatchContent(opsToWithDraw);
|
||||||
@@ -191,7 +191,7 @@ public class DeleteEPersonSubmitterIT extends AbstractControllerIntegrationTest
|
|||||||
|
|
||||||
assertNull(retrieveItemSubmitter(item.getID()));
|
assertNull(retrieveItemSubmitter(item.getID()));
|
||||||
|
|
||||||
List<Operation> opsToReinstate = new ArrayList<Operation>();
|
List<Operation> opsToReinstate = new ArrayList<>();
|
||||||
ReplaceOperation replaceOperationToReinstate = new ReplaceOperation("/withdrawn", false);
|
ReplaceOperation replaceOperationToReinstate = new ReplaceOperation("/withdrawn", false);
|
||||||
opsToReinstate.add(replaceOperationToReinstate);
|
opsToReinstate.add(replaceOperationToReinstate);
|
||||||
String patchBodyToReinstate = getPatchContent(opsToReinstate);
|
String patchBodyToReinstate = getPatchContent(opsToReinstate);
|
||||||
|
@@ -8,25 +8,65 @@
|
|||||||
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
|
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
|
||||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Strategies for determining who receives Request Copy emails.
|
||||||
|
A copy request "strategy" class produces a list of addresses to which a
|
||||||
|
request email should be sent. Each strategy gets its addresses from a
|
||||||
|
different source. Select the one that meets your need, or use the
|
||||||
|
CombiningRequestItemStrategy to meld the lists from two or more other
|
||||||
|
strategies.
|
||||||
|
</description>
|
||||||
|
|
||||||
<context:annotation-config /> <!-- allows us to use Spring annotations in beans -->
|
<context:annotation-config /> <!-- allows us to use Spring annotations in beans -->
|
||||||
|
|
||||||
<bean class="org.dspace.app.requestitem.RequestItemMetadataStrategy"
|
<!-- Select the implementation to be used. -->
|
||||||
id="org.dspace.app.requestitem.RequestItemAuthorExtractor"
|
<alias alias='org.dspace.app.requestitem.RequestItemAuthorExtractor'
|
||||||
autowire-candidate='true'>
|
name='org.dspace.app.requestitem.RequestItemMetadataStrategy'/>
|
||||||
<!--
|
|
||||||
Uncomment these properties if you want lookup in metadata the email and
|
|
||||||
the name of the author to contact for request copy.
|
|
||||||
If you don't configure that or if the requested item doesn't have these
|
|
||||||
metadata, the submitter data are used as fail over.
|
|
||||||
|
|
||||||
<property name="emailMetadata" value="schema.element.qualifier" />
|
<!-- Get recipients from an item metadata field. -->
|
||||||
<property name="fullNameMetadata" value="schema.element.qualifier" />
|
<bean class="org.dspace.app.requestitem.RequestItemMetadataStrategy"
|
||||||
-->
|
id="org.dspace.app.requestitem.RequestItemMetadataStrategy"
|
||||||
|
autowire-candidate="true">
|
||||||
|
<!--
|
||||||
|
Uncomment these properties if you want lookup in metadata the email
|
||||||
|
and the name of the author to contact for request copy.
|
||||||
|
If you don't configure that or if the requested item doesn't have
|
||||||
|
these metadata, the submitter data are used as fail over.
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
|
||||||
|
<property name="emailMetadata"
|
||||||
|
value="schema.element.qualifier" />
|
||||||
|
<property name="fullNameMetadata"
|
||||||
|
value="schema.element.qualifier" />
|
||||||
|
-->
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- HelpDesk to instead get RequestItem emails-->
|
<!-- HelpDesk to instead get RequestItem emails-->
|
||||||
<!--<bean class="org.dspace.app.requestitem.RequestItemHelpdeskStrategy"
|
<!--
|
||||||
id="org.dspace.app.requestitem.RequestItemAuthorExtractor"
|
<bean class="org.dspace.app.requestitem.RequestItemHelpdeskStrategy"
|
||||||
autowire-candidate='true'></bean>-->
|
id="org.dspace.app.requestitem.RequestItemHelpdeskStrategy"/>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Send request emails to administrators of an Item's owning Collection. -->
|
||||||
|
<!--
|
||||||
|
<bean class='org.dspace.app.requestitem.CollectionAdministratorsRequestItemStrategy'
|
||||||
|
id='org.dspace.app.requestitem.CollectionAdministratorsRequestItemStrategy'/>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Execute multiple strategies and concatenate their lists of recipients.
|
||||||
|
Mail will go to all members of the combined list. -->
|
||||||
|
<!--
|
||||||
|
<bean class='org.dspace.app.requestitem.CombiningRequestItemStrategy'
|
||||||
|
id='org.dspace.app.requestitem.CombiningRequestItemStrategy'
|
||||||
|
autowire='no'>
|
||||||
|
<constructor-arg>
|
||||||
|
<description>A list of references to RequestItemAuthorExtractor beans</description>
|
||||||
|
<list>
|
||||||
|
<ref bean='org.dspace.app.requestitem.RequestItemMetadataStrategy'/>
|
||||||
|
<ref bean='org.dspace.app.requestitem.CollectionAdministratorsRequestItemStrategy'/>
|
||||||
|
</list>
|
||||||
|
</constructor-arg>
|
||||||
|
</bean>
|
||||||
|
-->
|
||||||
</beans>
|
</beans>
|
||||||
|
Reference in New Issue
Block a user