[DS-4036] Delete EPersons even if they are referenced

DSpace references EPersons in different database tables like the
submitter of an item or like the EPerson that gets special rights
granted in the resourcepolicy table. This PR changes DSpace so it can
handle references that are set null instead of referencing an actual
EPerson. This is important to be able to delete EPersons which is
demanded by several data protection laws like GDPR in the European
Union.
This commit is contained in:
marsa
2017-10-18 15:48:25 +02:00
committed by Pascal-Nicolas Becker
parent 769398d6fb
commit 9a41e6fece
38 changed files with 1199 additions and 836 deletions

View File

@@ -19,6 +19,15 @@ import org.dspace.core.Context;
* @author Andrea Bollini * @author Andrea Bollini
*/ */
public interface RequestItemAuthorExtractor { public interface RequestItemAuthorExtractor {
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
throws SQLException; /**
* Retrieve the auhtor to contact for a request copy of the give item.
*
* @param context DSpace context object
* @param item item to request
* @return An object containing name an email address to send the request to
* or null if no valid email address was found.
* @throws SQLException if database error
*/
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) throws SQLException;
} }

View File

@@ -74,8 +74,7 @@ public class RequestItemHelpdeskStrategy extends RequestItemSubmitterStrategy {
return new RequestItemAuthor(helpdeskEPerson); return new RequestItemAuthor(helpdeskEPerson);
} else { } else {
String helpdeskName = I18nUtil.getMessage( String helpdeskName = I18nUtil.getMessage(
"org.dspace.app.requestitem.RequestItemHelpdeskStrategy.helpdeskname", "org.dspace.app.requestitem.helpdeskname", context);
context);
return new RequestItemAuthor(helpdeskName, helpDeskEmail); return new RequestItemAuthor(helpdeskName, helpDeskEmail);
} }
} }

View File

@@ -16,6 +16,7 @@ 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.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
/** /**
@@ -38,6 +39,7 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
@Override @Override
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
throws SQLException { throws SQLException {
RequestItemAuthor author = null;
if (emailMetadata != null) { if (emailMetadata != null) {
List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata); List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata);
if (vals.size() > 0) { if (vals.size() > 0) {
@@ -49,19 +51,37 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
fullname = nameVals.iterator().next().getValue(); fullname = nameVals.iterator().next().getValue();
} }
} }
if (StringUtils.isBlank(fullname)) { if (StringUtils.isBlank(fullname)) {
fullname = I18nUtil fullname = I18nUtil
.getMessage( .getMessage(
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed", "org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
context); context);
} }
RequestItemAuthor author = new RequestItemAuthor( author = new RequestItemAuthor(fullname, email);
fullname, email);
return author; return author;
} }
} else {
// Uses the basic strategy to look for the original submitter
author = super.getRequestItemAuthor(context, item);
// Is the author or his email null, so get the help desk or admin name and email
if (null == author || null == author.getEmail()) {
String email = null;
String name = null;
//First get help desk name and email
email = DSpaceServicesFactory.getInstance()
.getConfigurationService().getProperty("mail.helpdesk");
name = I18nUtil.getMessage("org.dspace.app.requestitem.helpdeskname", context);
// If help desk mail is null get the mail and name of admin
if (email == null) {
email = DSpaceServicesFactory.getInstance()
.getConfigurationService().getProperty("mail.admin");
name = DSpaceServicesFactory.getInstance()
.getConfigurationService().getProperty("admin.name");
}
author = new RequestItemAuthor(name, email);
}
} }
return super.getRequestItemAuthor(context, item); return author;
} }
public void setEmailMetadata(String emailMetadata) { public void setEmailMetadata(String emailMetadata) {

View File

@@ -23,13 +23,22 @@ public class RequestItemSubmitterStrategy implements RequestItemAuthorExtractor
public RequestItemSubmitterStrategy() { public RequestItemSubmitterStrategy() {
} }
/**
* Returns the submitter of an Item as RequestItemAuthor or null if the
* Submitter is deleted.
*
* @return The submitter of the item or null if the submitter is deleted
* @throws SQLException if database error
*/
@Override @Override
public RequestItemAuthor getRequestItemAuthor(Context context, Item item) public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
throws SQLException { throws SQLException {
EPerson submitter = item.getSubmitter(); EPerson submitter = item.getSubmitter();
RequestItemAuthor author = new RequestItemAuthor( RequestItemAuthor author = null;
submitter.getFullName(), submitter.getEmail()); if (null != submitter) {
author = new RequestItemAuthor(
submitter.getFullName(), submitter.getEmail());
}
return author; return author;
} }
} }

View File

@@ -606,6 +606,12 @@ public class AuthorizeServiceImpl implements AuthorizeService {
resourcePolicyService.removeDsoEPersonPolicies(c, o, e); resourcePolicyService.removeDsoEPersonPolicies(c, o, e);
} }
@Override
public void removeAllEPersonPolicies(Context c, EPerson e)
throws SQLException, AuthorizeException {
resourcePolicyService.removeAllEPersonPolicies(c, e);
}
@Override @Override
public List<Group> getAuthorizedGroups(Context c, DSpaceObject o, public List<Group> getAuthorizedGroups(Context c, DSpaceObject o,
int actionID) throws java.sql.SQLException { int actionID) throws java.sql.SQLException {

View File

@@ -109,6 +109,11 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService {
return resourcePolicyDAO.findByEPersonGroupTypeIdAction(c, e, groups, action, type_id); return resourcePolicyDAO.findByEPersonGroupTypeIdAction(c, e, groups, action, type_id);
} }
@Override
public List<ResourcePolicy> find(Context context, EPerson ePerson) throws SQLException {
return resourcePolicyDAO.findByEPerson(context, ePerson);
}
@Override @Override
public List<ResourcePolicy> findByTypeGroupActionExceptId(Context context, DSpaceObject dso, Group group, public List<ResourcePolicy> findByTypeGroupActionExceptId(Context context, DSpaceObject dso, Group group,
int action, int notPolicyID) int action, int notPolicyID)
@@ -241,6 +246,11 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService {
} }
@Override
public void removeAllEPersonPolicies(Context context, EPerson ePerson) throws SQLException, AuthorizeException {
resourcePolicyDAO.deleteAllEPersonPolicies(context, ePerson);
}
@Override @Override
public void removeGroupPolicies(Context c, Group group) throws SQLException { public void removeGroupPolicies(Context c, Group group) throws SQLException {
resourcePolicyDAO.deleteByGroup(c, group); resourcePolicyDAO.deleteByGroup(c, group);

View File

@@ -32,6 +32,8 @@ public interface ResourcePolicyDAO extends GenericDAO<ResourcePolicy> {
public List<ResourcePolicy> findByDsoAndType(Context context, DSpaceObject dSpaceObject, String type) public List<ResourcePolicy> findByDsoAndType(Context context, DSpaceObject dSpaceObject, String type)
throws SQLException; throws SQLException;
public List<ResourcePolicy> findByEPerson(Context context, EPerson ePerson) throws SQLException;
public List<ResourcePolicy> findByGroup(Context context, Group group) throws SQLException; public List<ResourcePolicy> findByGroup(Context context, Group group) throws SQLException;
public List<ResourcePolicy> findByDSoAndAction(Context context, DSpaceObject dso, int actionId) throws SQLException; public List<ResourcePolicy> findByDSoAndAction(Context context, DSpaceObject dso, int actionId) throws SQLException;
@@ -65,5 +67,7 @@ public interface ResourcePolicyDAO extends GenericDAO<ResourcePolicy> {
public void deleteByDsoEPersonPolicies(Context context, DSpaceObject dso, EPerson ePerson) throws SQLException; public void deleteByDsoEPersonPolicies(Context context, DSpaceObject dso, EPerson ePerson) throws SQLException;
public void deleteAllEPersonPolicies(Context context, EPerson ePerson) throws SQLException;
public void deleteByDsoAndTypeNotEqualsTo(Context c, DSpaceObject o, String type) throws SQLException; public void deleteByDsoAndTypeNotEqualsTo(Context c, DSpaceObject o, String type) throws SQLException;
} }

View File

@@ -60,6 +60,16 @@ public class ResourcePolicyDAOImpl extends AbstractHibernateDAO<ResourcePolicy>
return list(context, criteriaQuery, false, ResourcePolicy.class, -1, -1); return list(context, criteriaQuery, false, ResourcePolicy.class, -1, -1);
} }
@Override
public List<ResourcePolicy> findByEPerson(Context context, EPerson ePerson) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, ResourcePolicy.class);
Root<ResourcePolicy> resourcePolicyRoot = criteriaQuery.from(ResourcePolicy.class);
criteriaQuery.select(resourcePolicyRoot);
criteriaQuery.where(criteriaBuilder.equal(resourcePolicyRoot.get(ResourcePolicy_.eperson), ePerson));
return list(context, criteriaQuery, false, ResourcePolicy.class, -1, -1);
}
@Override @Override
public List<ResourcePolicy> findByGroup(Context context, Group group) throws SQLException { public List<ResourcePolicy> findByGroup(Context context, Group group) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
@@ -192,6 +202,15 @@ public class ResourcePolicyDAOImpl extends AbstractHibernateDAO<ResourcePolicy>
} }
@Override
public void deleteAllEPersonPolicies(Context context, EPerson ePerson) throws SQLException {
String queryString = "delete from ResourcePolicy where eperson= :eperson";
Query query = createQuery(context, queryString);
query.setParameter("eperson", ePerson);
query.executeUpdate();
}
@Override @Override
public void deleteByDsoAndTypeNotEqualsTo(Context context, DSpaceObject dso, String type) throws SQLException { public void deleteByDsoAndTypeNotEqualsTo(Context context, DSpaceObject dso, String type) throws SQLException {

View File

@@ -417,6 +417,16 @@ public interface AuthorizeService {
*/ */
public void removeEPersonPolicies(Context c, DSpaceObject o, EPerson e) throws SQLException, AuthorizeException; public void removeEPersonPolicies(Context c, DSpaceObject o, EPerson e) throws SQLException, AuthorizeException;
/**
* Removes all policies from an eperson that belong to an EPerson.
*
* @param c current context
* @param e the eperson
* @throws SQLException if there's a database problem
* @throws AuthorizeException if authorization error
*/
public void removeAllEPersonPolicies(Context c, EPerson e) throws SQLException, AuthorizeException;
/** /**
* Returns all groups authorized to perform an action on an object. Returns * Returns all groups authorized to perform an action on an object. Returns
* empty array if no matches. * empty array if no matches.

View File

@@ -38,6 +38,8 @@ public interface ResourcePolicyService extends DSpaceCRUDService<ResourcePolicy>
public List<ResourcePolicy> find(Context context, Group group) throws SQLException; public List<ResourcePolicy> find(Context context, Group group) throws SQLException;
public List<ResourcePolicy> find(Context c, EPerson ePerson) throws SQLException;
public List<ResourcePolicy> find(Context c, EPerson e, List<Group> groups, int action, int type_id) public List<ResourcePolicy> find(Context c, EPerson e, List<Group> groups, int action, int type_id)
throws SQLException; throws SQLException;
@@ -71,6 +73,8 @@ public interface ResourcePolicyService extends DSpaceCRUDService<ResourcePolicy>
public void removeDsoEPersonPolicies(Context context, DSpaceObject dso, EPerson ePerson) public void removeDsoEPersonPolicies(Context context, DSpaceObject dso, EPerson ePerson)
throws SQLException, AuthorizeException; throws SQLException, AuthorizeException;
public void removeAllEPersonPolicies(Context context, EPerson ePerson) throws SQLException, AuthorizeException;
public void removeGroupPolicies(Context c, Group group) throws SQLException; public void removeGroupPolicies(Context c, Group group) throws SQLException;
public void removeDsoAndTypeNotEqualsToPolicies(Context c, DSpaceObject o, String type) public void removeDsoAndTypeNotEqualsToPolicies(Context c, DSpaceObject o, String type)

View File

@@ -214,6 +214,12 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
return itemDAO.findBySubmitter(context, eperson); return itemDAO.findBySubmitter(context, eperson);
} }
@Override
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, boolean retrieveAllItems)
throws SQLException {
return itemDAO.findBySubmitter(context, eperson, retrieveAllItems);
}
@Override @Override
public Iterator<Item> findBySubmitterDateSorted(Context context, EPerson eperson, Integer limit) public Iterator<Item> findBySubmitterDateSorted(Context context, EPerson eperson, Integer limit)
throws SQLException { throws SQLException {

View File

@@ -208,9 +208,8 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
*/ */
Item item = workspaceItem.getItem(); Item item = workspaceItem.getItem();
if (!authorizeService.isAdmin(context) if (!authorizeService.isAdmin(context)
&& ((context.getCurrentUser() == null) || (context && (item.getSubmitter() == null || (context.getCurrentUser() == null)
.getCurrentUser().getID() != item.getSubmitter() || (context.getCurrentUser().getID() != item.getSubmitter().getID()))) {
.getID()))) {
// Not an admit, not the submitter // Not an admit, not the submitter
throw new AuthorizeException("Must be an administrator or the " throw new AuthorizeException("Must be an administrator or the "
+ "original submitter to delete a workspace item"); + "original submitter to delete a workspace item");

View File

@@ -46,6 +46,9 @@ public interface ItemDAO extends DSpaceObjectLegacySupportDAO<Item> {
public Iterator<Item> findBySubmitter(Context context, EPerson eperson) throws SQLException; public Iterator<Item> findBySubmitter(Context context, EPerson eperson) throws SQLException;
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, boolean retrieveAllItems)
throws SQLException;
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, MetadataField metadataField, int limit) public Iterator<Item> findBySubmitter(Context context, EPerson eperson, MetadataField metadataField, int limit)
throws SQLException; throws SQLException;

View File

@@ -104,6 +104,17 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
return iterate(query); return iterate(query);
} }
@Override
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, boolean retrieveAllItems)
throws SQLException {
Query query = createQuery(context, "FROM Item WHERE submitter= :submitter");
if (!retrieveAllItems) {
return findBySubmitter(context, eperson);
}
query.setParameter("submitter", eperson);
return iterate(query);
}
@Override @Override
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, MetadataField metadataField, int limit) public Iterator<Item> findBySubmitter(Context context, EPerson eperson, MetadataField metadataField, int limit)
throws SQLException { throws SQLException {

View File

@@ -110,6 +110,19 @@ public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLega
public Iterator<Item> findBySubmitter(Context context, EPerson eperson) public Iterator<Item> findBySubmitter(Context context, EPerson eperson)
throws SQLException; throws SQLException;
/**
* Find all the items by a given submitter. The order is
* indeterminate. All items are included.
*
* @param context DSpace context object
* @param eperson the submitter
* @param retrieveAllItems flag to determine if only archive should be returned
* @return an iterator over the items submitted by eperson
* @throws SQLException if database error
*/
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, boolean retrieveAllItems)
throws SQLException;
/** /**
* Retrieve the list of items submitted by eperson, ordered by recently submitted, optionally limitable * Retrieve the list of items submitted by eperson, ordered by recently submitted, optionally limitable
* *

View File

@@ -7,8 +7,11 @@
*/ */
package org.dspace.eperson; package org.dspace.eperson;
import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
@@ -259,16 +262,27 @@ public class EPersonCLITool {
} }
try { try {
ePersonService.delete(context, eperson); List<String> tableList = ePersonService.getDeleteConstraints(context, eperson);
context.complete(); if (!tableList.isEmpty()) {
System.out.printf("Deleted EPerson %s\n", eperson.getID().toString()); System.out.printf("This EPerson with ID: %s is referring to this tables:%n ",
} catch (SQLException ex) { eperson.getID().toString());
System.err.println(ex.getMessage()); tableList.forEach((s) -> {
return 1; System.out.println(s);
} catch (AuthorizeException ex) { });
System.err.println(ex.getMessage()); }
return 1; System.out.printf("Are you sure you want to delete this EPerson with ID: %s? (y or n): ",
} catch (IOException ex) { eperson.getID().toString());
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
System.out.flush();
String s = input.readLine();
if (s != null && s.trim().toLowerCase().startsWith("y")) {
ePersonService.delete(context, eperson);
context.complete();
System.out.printf("%nDeleted EPerson with ID: %s", eperson.getID().toString());
} else {
System.out.printf("%nAbort Deletetion of EPerson with ID: %s %n", eperson.getID().toString());
}
} catch (SQLException | AuthorizeException | IOException ex) {
System.err.println(ex.getMessage()); System.err.println(ex.getMessage());
return 1; return 1;
} }

View File

@@ -9,6 +9,8 @@ package org.dspace.eperson;
import java.util.List; import java.util.List;
import org.apache.commons.lang.ArrayUtils;
/** /**
* Exception indicating that an EPerson may not be deleted due to the presence * Exception indicating that an EPerson may not be deleted due to the presence
* of the EPerson's ID in certain tables * of the EPerson's ID in certain tables
@@ -33,7 +35,10 @@ public class EPersonDeletionException extends Exception {
* deleted if it exists in these tables. * deleted if it exists in these tables.
*/ */
public EPersonDeletionException(List<String> tableList) { public EPersonDeletionException(List<String> tableList) {
super(); // this may not be the most beautiful way to print the tablenames as part or the error message.
// but it has to be a one liner, as the super() call must be the first statement in the constructor.
super("Cannot delete EPerson as it is referenced by the following database tables: "
+ ArrayUtils.toString(tableList.toArray()));
myTableList = tableList; myTableList = tableList;
} }

View File

@@ -7,9 +7,11 @@
*/ */
package org.dspace.eperson; package org.dspace.eperson;
import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@@ -21,11 +23,16 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.DSpaceObjectServiceImpl; import org.dspace.content.DSpaceObjectServiceImpl;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
@@ -34,13 +41,36 @@ import org.dspace.eperson.dao.EPersonDAO;
import org.dspace.eperson.service.EPersonService; import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.SubscribeService; import org.dspace.eperson.service.SubscribeService;
import org.dspace.event.Event; import org.dspace.event.Event;
import org.dspace.versioning.Version;
import org.dspace.versioning.VersionHistory;
import org.dspace.versioning.dao.VersionDAO;
import org.dspace.versioning.factory.VersionServiceFactory;
import org.dspace.versioning.service.VersionHistoryService;
import org.dspace.versioning.service.VersioningService;
import org.dspace.workflow.WorkflowService; import org.dspace.workflow.WorkflowService;
import org.dspace.workflow.factory.WorkflowServiceFactory; import org.dspace.workflow.factory.WorkflowServiceFactory;
import org.dspace.workflowbasic.BasicWorkflowItem;
import org.dspace.workflowbasic.BasicWorkflowServiceImpl;
import org.dspace.workflowbasic.factory.BasicWorkflowServiceFactory;
import org.dspace.workflowbasic.service.BasicWorkflowItemService;
import org.dspace.workflowbasic.service.BasicWorkflowService;
import org.dspace.workflowbasic.service.TaskListItemService;
import org.dspace.xmlworkflow.WorkflowConfigurationException;
import org.dspace.xmlworkflow.factory.XmlWorkflowServiceFactory;
import org.dspace.xmlworkflow.service.WorkflowRequirementsService;
import org.dspace.xmlworkflow.service.XmlWorkflowService;
import org.dspace.xmlworkflow.storedcomponents.ClaimedTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.dspace.xmlworkflow.storedcomponents.service.ClaimedTaskService;
import org.dspace.xmlworkflow.storedcomponents.service.PoolTaskService;
import org.dspace.xmlworkflow.storedcomponents.service.WorkflowItemRoleService;
import org.dspace.xmlworkflow.storedcomponents.service.XmlWorkflowItemService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
/** /**
* Service implementation for the EPerson object. * Service implementation for the EPerson object. This class is responsible for
* This class is responsible for all business logic calls for the EPerson object and is autowired by spring. * all business logic calls for the EPerson object and is autowired by spring.
* This class should never be accessed directly. * This class should never be accessed directly.
* *
* @author kevinvandevelde at atmire.com * @author kevinvandevelde at atmire.com
@@ -61,6 +91,8 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
protected ItemService itemService; protected ItemService itemService;
@Autowired(required = true) @Autowired(required = true)
protected SubscribeService subscribeService; protected SubscribeService subscribeService;
@Autowired(required = true)
protected VersionDAO versionDAO;
protected EPersonServiceImpl() { protected EPersonServiceImpl() {
super(); super();
@@ -129,7 +161,7 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
query = null; query = null;
} }
return ePersonDAO.search(context, query, Arrays.asList(firstNameField, lastNameField), return ePersonDAO.search(context, query, Arrays.asList(firstNameField, lastNameField),
Arrays.asList(firstNameField, lastNameField), offset, limit); Arrays.asList(firstNameField, lastNameField), offset, limit);
} }
} }
@@ -179,45 +211,192 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
// authorized? // authorized?
if (!authorizeService.isAdmin(context)) { if (!authorizeService.isAdmin(context)) {
throw new AuthorizeException( throw new AuthorizeException(
"You must be an admin to create an EPerson"); "You must be an admin to create an EPerson");
} }
// Create a table row // Create a table row
EPerson e = ePersonDAO.create(context, new EPerson()); EPerson e = ePersonDAO.create(context, new EPerson());
log.info(LogManager.getHeader(context, "create_eperson", "eperson_id=" log.info(LogManager.getHeader(context, "create_eperson", "eperson_id="
+ e.getID())); + e.getID()));
context.addEvent(new Event(Event.CREATE, Constants.EPERSON, e.getID(), context.addEvent(new Event(Event.CREATE, Constants.EPERSON, e.getID(),
null, getIdentifiers(context, e))); null, getIdentifiers(context, e)));
return e; return e;
} }
@Override @Override
public void delete(Context context, EPerson ePerson) throws SQLException, AuthorizeException { public void delete(Context context, EPerson ePerson) throws SQLException, AuthorizeException {
try {
delete(context, ePerson, true);
} catch (AuthorizeException ex) {
log.error("This AuthorizeException: " + ex + " occured while deleting Eperson with the ID: " +
ePerson.getID());
throw new AuthorizeException(ex.getMessage());
} catch (IOException ex) {
log.error("This IOException: " + ex + " occured while deleting Eperson with the ID: " + ePerson.getID());
throw new AuthorizeException(new EPersonDeletionException());
}
}
/**
* Deletes an EPerson. The argument cascade defines whether all references
* on an EPerson should be deleted as well (by either deleting the
* referencing object - e.g. WorkspaceItem, ResourcePolicy - or by setting
* the foreign key null - e.g. archived Items). If cascade is set to false
* and the EPerson is referenced somewhere, this leads to an
* AuthorizeException. EPersons may be referenced by Items, ResourcePolicies
* and workflow tasks.
*
* @param context DSpace context
* @param ePerson The EPerson to delete.
* @param cascade Whether to delete references on the EPerson (cascade =
* true) or to abort the deletion (cascade = false) if the EPerson is
* referenced within DSpace.
*
* @throws SQLException
* @throws AuthorizeException
* @throws IOException
*/
public void delete(Context context, EPerson ePerson, boolean cascade)
throws SQLException, AuthorizeException, IOException {
// authorized? // authorized?
if (!authorizeService.isAdmin(context)) { if (!authorizeService.isAdmin(context)) {
throw new AuthorizeException( throw new AuthorizeException(
"You must be an admin to delete an EPerson"); "You must be an admin to delete an EPerson");
} }
// check for presence of eperson in tables that // check for presence of eperson in tables that
// have constraints on eperson_id // have constraints on eperson_id
List<String> constraintList = getDeleteConstraints(context, ePerson); List<String> constraintList = getDeleteConstraints(context, ePerson);
// if eperson exists in tables that have constraints
// on eperson, throw an exception
if (constraintList.size() > 0) { if (constraintList.size() > 0) {
throw new AuthorizeException(new EPersonDeletionException(constraintList)); // Check if the constraints we found should be deleted
} if (cascade) {
boolean isBasicFramework = WorkflowServiceFactory.getInstance().getWorkflowService()
instanceof BasicWorkflowService;
boolean isXmlFramework = WorkflowServiceFactory.getInstance().getWorkflowService()
instanceof XmlWorkflowService;
Iterator<String> constraintsIterator = constraintList.iterator();
while (constraintsIterator.hasNext()) {
String tableName = constraintsIterator.next();
if (StringUtils.equals(tableName, "item") || StringUtils.equals(tableName, "workspaceitem")) {
Iterator<Item> itemIterator = itemService.findBySubmitter(context, ePerson, true);
VersionHistoryService versionHistoryService = VersionServiceFactory.getInstance()
.getVersionHistoryService();
VersioningService versioningService = VersionServiceFactory.getInstance().getVersionService();
while (itemIterator.hasNext()) {
Item item = itemIterator.next();
VersionHistory versionHistory = versionHistoryService.findByItem(context, item);
if (null != versionHistory) {
for (Version version : versioningService.getVersionsByHistory(context,
versionHistory)) {
version.setePerson(null);
versionDAO.save(context, version);
}
}
WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance()
.getWorkspaceItemService();
WorkspaceItem wsi = workspaceItemService.findByItem(context, item);
if (null != wsi) {
workspaceItemService.deleteAll(context, wsi);
} else {
// we can do that as dc.provenance still contains
// information about who submitted and who
// archived an item.
item.setSubmitter(null);
itemService.update(context, item);
}
}
} else if (StringUtils.equals(tableName, "cwf_claimtask") && isXmlFramework) {
// Unclaim all XmlWorkflow tasks
XmlWorkflowItemService xmlWorkflowItemService = XmlWorkflowServiceFactory
.getInstance().getXmlWorkflowItemService();
ClaimedTaskService claimedTaskService = XmlWorkflowServiceFactory
.getInstance().getClaimedTaskService();
XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory
.getInstance().getXmlWorkflowService();
WorkflowRequirementsService workflowRequirementsService = XmlWorkflowServiceFactory
.getInstance().getWorkflowRequirementsService();
List<XmlWorkflowItem> xmlWorkflowItems = xmlWorkflowItemService
.findBySubmitter(context, ePerson);
for (XmlWorkflowItem xmlWorkflowItem : xmlWorkflowItems) {
ClaimedTask pooledTask = claimedTaskService
.findByWorkflowIdAndEPerson(context, xmlWorkflowItem, ePerson);
xmlWorkflowService.deleteClaimedTask(context, xmlWorkflowItem, pooledTask);
try {
workflowRequirementsService.removeClaimedUser(context, xmlWorkflowItem,
ePerson, pooledTask.getStepID());
} catch (WorkflowConfigurationException ex) {
log.error("This WorkflowConfigurationException: " + ex +
" occured while deleting Eperson with the ID: " + ePerson.getID());
throw new AuthorizeException(new EPersonDeletionException(Collections
.singletonList(tableName)));
}
}
} else if (StringUtils.equals(tableName, "workflowitem") && isBasicFramework) {
// Remove basicWorkflow workflowitem and unclaim them
BasicWorkflowItemService basicWorkflowItemService = BasicWorkflowServiceFactory.getInstance()
.getBasicWorkflowItemService();
BasicWorkflowService basicWorkflowService = BasicWorkflowServiceFactory.getInstance()
.getBasicWorkflowService();
TaskListItemService taskListItemService = BasicWorkflowServiceFactory.getInstance()
.getTaskListItemService();
List<BasicWorkflowItem> workflowItems = basicWorkflowItemService.findByOwner(context, ePerson);
for (BasicWorkflowItem workflowItem : workflowItems) {
int state = workflowItem.getState();
// unclaim tasks that are in the pool.
if (state == BasicWorkflowServiceImpl.WFSTATE_STEP1
|| state == BasicWorkflowServiceImpl.WFSTATE_STEP2
|| state == BasicWorkflowServiceImpl.WFSTATE_STEP3) {
log.info(LogManager.getHeader(context, "unclaim_workflow",
"workflow_id=" + workflowItem.getID() + ", claiming EPerson is deleted"));
basicWorkflowService.unclaim(context, workflowItem, context.getCurrentUser());
// remove the EPerson from the list of persons that can (re-)claim the task
// while we are doing it below, we must do this here as well as the previously
// unclaimed tasks was put back into pool and we do not know the order the tables
// are checked.
taskListItemService.deleteByWorkflowItemAndEPerson(context, workflowItem, ePerson);
}
}
} else if (StringUtils.equals(tableName, "resourcepolicy")) {
// we delete the EPerson, it won't need any rights anymore.
authorizeService.removeAllEPersonPolicies(context, ePerson);
} else if (StringUtils.equals(tableName, "tasklistitem") && isBasicFramework) {
// remove EPerson from the list of EPersons that may claim some specific workflow tasks.
TaskListItemService taskListItemService = BasicWorkflowServiceFactory.getInstance()
.getTaskListItemService();
taskListItemService.deleteByEPerson(context, ePerson);
} else if (StringUtils.equals(tableName, "cwf_pooltask") && isXmlFramework) {
PoolTaskService poolTaskService = XmlWorkflowServiceFactory.getInstance().getPoolTaskService();
poolTaskService.deleteByEperson(context, ePerson);
} else if (StringUtils.equals(tableName, "cwf_workflowitemrole") && isXmlFramework) {
WorkflowItemRoleService workflowItemRoleService = XmlWorkflowServiceFactory.getInstance()
.getWorkflowItemRoleService();
workflowItemRoleService.deleteByEPerson(context, ePerson);
} else {
log.warn("EPerson is referenced in table '" + tableName
+ "'. Deletion of EPerson " + ePerson.getID() + " may fail "
+ "if the database does not handle this "
+ "reference.");
}
}
} else {
throw new AuthorizeException(new EPersonDeletionException(constraintList));
}
}
context.addEvent(new Event(Event.DELETE, Constants.EPERSON, ePerson.getID(), ePerson.getEmail(), context.addEvent(new Event(Event.DELETE, Constants.EPERSON, ePerson.getID(), ePerson.getEmail(),
getIdentifiers(context, ePerson))); getIdentifiers(context, ePerson)));
// XXX FIXME: This sidesteps the object model code so it won't // XXX FIXME: This sidesteps the object model code so it won't
// generate REMOVE events on the affected Groups. // generate REMOVE events on the affected Groups.
// Remove any group memberships first // Remove any group memberships first
// Remove any group memberships first // Remove any group memberships first
Iterator<Group> groups = ePerson.getGroups().iterator(); Iterator<Group> groups = ePerson.getGroups().iterator();
@@ -234,7 +413,7 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
ePersonDAO.delete(context, ePerson); ePersonDAO.delete(context, ePerson);
log.info(LogManager.getHeader(context, "delete_eperson", log.info(LogManager.getHeader(context, "delete_eperson",
"eperson_id=" + ePerson.getID())); "eperson_id=" + ePerson.getID()));
} }
@Override @Override
@@ -268,8 +447,8 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
PasswordHash hash = null; PasswordHash hash = null;
try { try {
hash = new PasswordHash(ePerson.getDigestAlgorithm(), hash = new PasswordHash(ePerson.getDigestAlgorithm(),
ePerson.getSalt(), ePerson.getSalt(),
ePerson.getPassword()); ePerson.getPassword());
} catch (DecoderException ex) { } catch (DecoderException ex) {
log.error("Problem decoding stored salt or hash: " + ex.getMessage()); log.error("Problem decoding stored salt or hash: " + ex.getMessage());
} }
@@ -281,9 +460,9 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
PasswordHash myHash; PasswordHash myHash;
try { try {
myHash = new PasswordHash( myHash = new PasswordHash(
ePerson.getDigestAlgorithm(), ePerson.getDigestAlgorithm(),
ePerson.getSalt(), ePerson.getSalt(),
ePerson.getPassword()); ePerson.getPassword());
} catch (DecoderException ex) { } catch (DecoderException ex) {
log.error(ex.getMessage()); log.error(ex.getMessage());
return false; return false;
@@ -312,8 +491,8 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
// Check authorisation - if you're not the eperson // Check authorisation - if you're not the eperson
// see if the authorization system says you can // see if the authorization system says you can
if (!context.ignoreAuthorization() if (!context.ignoreAuthorization()
&& ((context.getCurrentUser() == null) || (ePerson.getID() != context && ((context.getCurrentUser() == null) || (ePerson.getID() != context
.getCurrentUser().getID()))) { .getCurrentUser().getID()))) {
authorizeService.authorizeAction(context, ePerson, Constants.WRITE); authorizeService.authorizeAction(context, ePerson, Constants.WRITE);
} }
@@ -322,11 +501,11 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
ePersonDAO.save(context, ePerson); ePersonDAO.save(context, ePerson);
log.info(LogManager.getHeader(context, "update_eperson", log.info(LogManager.getHeader(context, "update_eperson",
"eperson_id=" + ePerson.getID())); "eperson_id=" + ePerson.getID()));
if (ePerson.isModified()) { if (ePerson.isModified()) {
context.addEvent(new Event(Event.MODIFY, Constants.EPERSON, context.addEvent(new Event(Event.MODIFY, Constants.EPERSON,
ePerson.getID(), null, getIdentifiers(context, ePerson))); ePerson.getID(), null, getIdentifiers(context, ePerson)));
ePerson.clearModified(); ePerson.clearModified();
} }
if (ePerson.isMetadataModified()) { if (ePerson.isMetadataModified()) {
@@ -339,11 +518,22 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
List<String> tableList = new ArrayList<String>(); List<String> tableList = new ArrayList<String>();
// check for eperson in item table // check for eperson in item table
Iterator<Item> itemsBySubmitter = itemService.findBySubmitter(context, ePerson); Iterator<Item> itemsBySubmitter = itemService.findBySubmitter(context, ePerson, true);
if (itemsBySubmitter.hasNext()) { if (itemsBySubmitter.hasNext()) {
tableList.add("item"); tableList.add("item");
} }
WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
List<WorkspaceItem> workspaceBySubmitter = workspaceItemService.findByEPerson(context, ePerson);
if (workspaceBySubmitter.size() > 0) {
tableList.add("workspaceitem");
}
ResourcePolicyService resourcePolicyService = AuthorizeServiceFactory.getInstance().getResourcePolicyService();
if (resourcePolicyService.find(context, ePerson).size() > 0) {
tableList.add("resourcepolicy");
}
WorkflowService workflowService = WorkflowServiceFactory.getInstance().getWorkflowService(); WorkflowService workflowService = WorkflowServiceFactory.getInstance().getWorkflowService();
List<String> workflowConstraints = workflowService.getEPersonDeleteConstraints(context, ePerson); List<String> workflowConstraints = workflowService.getEPersonDeleteConstraints(context, ePerson);
tableList.addAll(workflowConstraints); tableList.addAll(workflowConstraints);

View File

@@ -80,6 +80,20 @@ public interface WorkflowService<T extends WorkflowItem> {
*/ */
public WorkspaceItem abort(Context c, T wi, EPerson e) throws SQLException, AuthorizeException, IOException; public WorkspaceItem abort(Context c, T wi, EPerson e) throws SQLException, AuthorizeException, IOException;
/**
* Deletes workflow task item in correct order.
*
* @param c The relevant DSpace Context.
* @param wi The WorkflowItem that shall be deleted.
* @param e Admin that deletes this workflow task and item (for logging
* @throws SQLException An exception that provides information on a database access error or other errors.
* @throws AuthorizeException Exception indicating the current user of the context does not have permission
* to perform a particular action.
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
*/
public void deleteWorkflowByWorkflowItem(Context c, T wi, EPerson e)
throws SQLException, AuthorizeException, IOException;
public WorkspaceItem sendWorkflowItemBackSubmission(Context c, T workflowItem, EPerson e, String provenance, public WorkspaceItem sendWorkflowItemBackSubmission(Context c, T workflowItem, EPerson e, String provenance,
String rejection_message) String rejection_message)
throws SQLException, AuthorizeException, IOException; throws SQLException, AuthorizeException, IOException;

View File

@@ -798,33 +798,38 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
try { try {
// Get submitter // Get submitter
EPerson ep = item.getSubmitter(); EPerson ep = item.getSubmitter();
// Get the Locale
Locale supportedLocale = I18nUtil.getEPersonLocale(ep);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive"));
// Get the item handle to email to user // send the notification only if the person was not deleted in the
String handle = handleService.findHandle(context, item); // meantime between submission and archiving.
if (ep != null) {
// Get the Locale
Locale supportedLocale = I18nUtil.getEPersonLocale(ep);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive"));
// Get title // Get the item handle to email to user
String title = item.getName(); String handle = handleService.findHandle(context, item);
if (StringUtils.isBlank(title)) {
try { // Get title
title = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled"); String title = item.getName();
} catch (MissingResourceException e) { if (StringUtils.isBlank(title)) {
title = "Untitled"; try {
title = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled");
} catch (MissingResourceException e) {
title = "Untitled";
}
} }
email.addRecipient(ep.getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(handleService.getCanonicalForm(handle));
email.send();
} }
email.addRecipient(ep.getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(handleService.getCanonicalForm(handle));
email.send();
} catch (MessagingException e) { } catch (MessagingException e) {
log.warn(LogManager.getHeader(context, "notifyOfArchive", log.warn(LogManager.getHeader(context, "notifyOfArchive",
"cannot email user; item_id=" + item.getID() "cannot email user; item_id=" + item.getID()
+ ": " + e.getMessage())); + ": " + e.getMessage()));
} }
} }
@@ -866,6 +871,24 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
return workspaceItem; return workspaceItem;
} }
@Override
public void deleteWorkflowByWorkflowItem(Context context, BasicWorkflowItem wi, EPerson e)
throws SQLException, AuthorizeException, IOException {
Item myitem = wi.getItem();
UUID itemID = myitem.getID();
Integer workflowID = wi.getID();
UUID collID = wi.getCollection().getID();
// stop workflow
taskListItemService.deleteByWorkflowItem(context, wi);
// Now remove the workflow object manually from the database
workflowItemService.deleteWrapper(context, wi);
// Now delete the item
itemService.delete(context, myitem);
log.info(LogManager.getHeader(context, "delete_workflow", "workflow_item_id="
+ workflowID + "item_id=" + itemID
+ "collection_id=" + collID + "eperson_id="
+ e.getID()));
}
@Override @Override
public WorkspaceItem sendWorkflowItemBackSubmission(Context context, BasicWorkflowItem workflowItem, public WorkspaceItem sendWorkflowItemBackSubmission(Context context, BasicWorkflowItem workflowItem,
@@ -1047,25 +1070,30 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
protected void notifyOfReject(Context context, BasicWorkflowItem workflowItem, EPerson e, protected void notifyOfReject(Context context, BasicWorkflowItem workflowItem, EPerson e,
String reason) { String reason) {
try { try {
// Get the item title // Get submitter
String title = getItemTitle(workflowItem); EPerson ep = workflowItem.getSubmitter();
// send the notification only if the person was not deleted in the meantime
if (ep != null) {
// Get the item title
String title = getItemTitle(workflowItem);
// Get the collection // Get the collection
Collection coll = workflowItem.getCollection(); Collection coll = workflowItem.getCollection();
// Get rejector's name // Get rejector's name
String rejector = getEPersonName(e); String rejector = getEPersonName(e);
Locale supportedLocale = I18nUtil.getEPersonLocale(e); Locale supportedLocale = I18nUtil.getEPersonLocale(e);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject")); Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject"));
email.addRecipient(workflowItem.getSubmitter().getEmail()); email.addRecipient(ep.getEmail());
email.addArgument(title); email.addArgument(title);
email.addArgument(coll.getName()); email.addArgument(coll.getName());
email.addArgument(rejector); email.addArgument(rejector);
email.addArgument(reason); email.addArgument(reason);
email.addArgument(getMyDSpaceLink()); email.addArgument(getMyDSpaceLink());
email.send(); email.send();
}
} catch (RuntimeException re) { } catch (RuntimeException re) {
// log this email error // log this email error
log.warn(LogManager.getHeader(context, "notify_of_reject", log.warn(LogManager.getHeader(context, "notify_of_reject",
@@ -1101,7 +1129,9 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
@Override @Override
public String getSubmitterName(BasicWorkflowItem wi) throws SQLException { public String getSubmitterName(BasicWorkflowItem wi) throws SQLException {
EPerson e = wi.getSubmitter(); EPerson e = wi.getSubmitter();
if (e == null) {
return null;
}
return getEPersonName(e); return getEPersonName(e);
} }

View File

@@ -46,6 +46,17 @@ public class TaskListItemServiceImpl implements TaskListItemService {
taskListItemDAO.deleteByWorkflowItem(context, workflowItem); taskListItemDAO.deleteByWorkflowItem(context, workflowItem);
} }
@Override
public void deleteByWorkflowItemAndEPerson(Context context, BasicWorkflowItem workflowItem, EPerson ePerson)
throws SQLException {
taskListItemDAO.deleteByWorkflowItemAndEPerson(context, workflowItem, ePerson);
}
@Override
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException {
taskListItemDAO.deleteByEPerson(context, ePerson);
}
@Override @Override
public void update(Context context, TaskListItem taskListItem) throws SQLException { public void update(Context context, TaskListItem taskListItem) throws SQLException {
taskListItemDAO.save(context, taskListItem); taskListItemDAO.save(context, taskListItem);

View File

@@ -28,5 +28,10 @@ public interface TaskListItemDAO extends GenericDAO<TaskListItem> {
public void deleteByWorkflowItem(Context context, BasicWorkflowItem workflowItem) throws SQLException; public void deleteByWorkflowItem(Context context, BasicWorkflowItem workflowItem) throws SQLException;
public void deleteByWorkflowItemAndEPerson(Context context, BasicWorkflowItem workflowItem, EPerson ePerson)
throws SQLException;
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException;
public List<TaskListItem> findByEPerson(Context context, EPerson ePerson) throws SQLException; public List<TaskListItem> findByEPerson(Context context, EPerson ePerson) throws SQLException;
} }

View File

@@ -42,6 +42,24 @@ public class TaskListItemDAOImpl extends AbstractHibernateDAO<TaskListItem> impl
query.executeUpdate(); query.executeUpdate();
} }
@Override
public void deleteByWorkflowItemAndEPerson(Context context, BasicWorkflowItem workflowItem, EPerson ePerson)
throws SQLException {
String queryString = "delete from TaskListItem where workflowItem = :workflowItem AND ePerson = :ePerson";
Query query = createQuery(context, queryString);
query.setParameter("workflowItem", workflowItem);
query.setParameter("ePerson", ePerson);
query.executeUpdate();
}
@Override
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException {
String queryString = "delete from TaskListItem where ePerson = :ePerson";
Query query = createQuery(context, queryString);
query.setParameter("ePerson", ePerson);
query.executeUpdate();
}
@Override @Override
public List<TaskListItem> findByEPerson(Context context, EPerson ePerson) throws SQLException { public List<TaskListItem> findByEPerson(Context context, EPerson ePerson) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context); CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);

View File

@@ -28,6 +28,11 @@ public interface TaskListItemService {
public void deleteByWorkflowItem(Context context, BasicWorkflowItem workflowItem) throws SQLException; public void deleteByWorkflowItem(Context context, BasicWorkflowItem workflowItem) throws SQLException;
public void deleteByWorkflowItemAndEPerson(Context context, BasicWorkflowItem workflowItem, EPerson ePerson)
throws SQLException;
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException;
public void update(Context context, TaskListItem taskListItem) throws SQLException; public void update(Context context, TaskListItem taskListItem) throws SQLException;
public List<TaskListItem> findByEPerson(Context context, EPerson ePerson) throws SQLException; public List<TaskListItem> findByEPerson(Context context, EPerson ePerson) throws SQLException;

View File

@@ -251,19 +251,21 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
} }
protected void grantSubmitterReadPolicies(Context context, Item item) throws SQLException, AuthorizeException { protected void grantSubmitterReadPolicies(Context context, Item item) throws SQLException, AuthorizeException {
//A list of policies the user has for this item
List<Integer> userHasPolicies = new ArrayList<Integer>();
List<ResourcePolicy> itempols = authorizeService.getPolicies(context, item);
EPerson submitter = item.getSubmitter(); EPerson submitter = item.getSubmitter();
for (ResourcePolicy resourcePolicy : itempols) { if (null != submitter) {
if (submitter.equals(resourcePolicy.getEPerson())) { //A list of policies the user has for this item
//The user has already got this policy so add it to the list List<Integer> userHasPolicies = new ArrayList<>();
userHasPolicies.add(resourcePolicy.getAction()); List<ResourcePolicy> itempols = authorizeService.getPolicies(context, item);
for (ResourcePolicy resourcePolicy : itempols) {
if (submitter.equals(resourcePolicy.getEPerson())) {
//The user has already got this policy so add it to the list
userHasPolicies.add(resourcePolicy.getAction());
}
}
//Make sure we don't add duplicate policies
if (!userHasPolicies.contains(Constants.READ)) {
addPolicyToItem(context, item, Constants.READ, submitter, ResourcePolicy.TYPE_SUBMISSION);
} }
}
//Make sure we don't add duplicate policies
if (!userHasPolicies.contains(Constants.READ)) {
addPolicyToItem(context, item, Constants.READ, submitter, ResourcePolicy.TYPE_SUBMISSION);
} }
} }
@@ -564,35 +566,39 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
try { try {
// Get submitter // Get submitter
EPerson ep = item.getSubmitter(); EPerson ep = item.getSubmitter();
// Get the Locale // send the notification only if the person was not deleted in the
Locale supportedLocale = I18nUtil.getEPersonLocale(ep); // meantime between submission and archiving.
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive")); if (null != ep) {
// Get the Locale
Locale supportedLocale = I18nUtil.getEPersonLocale(ep);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive"));
// Get the item handle to email to user // Get the item handle to email to user
String handle = handleService.findHandle(context, item); String handle = handleService.findHandle(context, item);
// Get title // Get title
List<MetadataValue> titles = itemService List<MetadataValue> titles = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "title", null, Item.ANY); .getMetadata(item, MetadataSchema.DC_SCHEMA, "title", null, Item.ANY);
String title = ""; String title = "";
try { try {
title = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled"); title = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled");
} catch (MissingResourceException e) { } catch (MissingResourceException e) {
title = "Untitled"; title = "Untitled";
}
if (titles.size() > 0) {
title = titles.iterator().next().getValue();
}
email.addRecipient(ep.getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(handleService.getCanonicalForm(handle));
email.send();
} }
if (titles.size() > 0) {
title = titles.iterator().next().getValue();
}
email.addRecipient(ep.getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(handleService.getCanonicalForm(handle));
email.send();
} catch (MessagingException e) { } catch (MessagingException e) {
log.warn(LogManager.getHeader(context, "notifyOfArchive", log.warn(LogManager.getHeader(context, "notifyOfArchive",
"cannot email user" + " item_id=" + item.getID())); "cannot email user" + " item_id=" + item.getID()));
} }
} }
@@ -803,7 +809,7 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
} }
public void removeUserItemPolicies(Context context, Item item, EPerson e) throws SQLException, AuthorizeException { public void removeUserItemPolicies(Context context, Item item, EPerson e) throws SQLException, AuthorizeException {
if (e != null) { if (e != null && item.getSubmitter() != null) {
//Also remove any lingering authorizations from this user //Also remove any lingering authorizations from this user
authorizeService.removeEPersonPolicies(context, item, e); authorizeService.removeEPersonPolicies(context, item, e);
//Remove the bundle rights //Remove the bundle rights
@@ -825,7 +831,7 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
protected void removeGroupItemPolicies(Context context, Item item, Group e) protected void removeGroupItemPolicies(Context context, Item item, Group e)
throws SQLException, AuthorizeException { throws SQLException, AuthorizeException {
if (e != null) { if (e != null && item.getSubmitter() != null) {
//Also remove any lingering authorizations from this user //Also remove any lingering authorizations from this user
authorizeService.removeGroupPolicies(context, item, e); authorizeService.removeGroupPolicies(context, item, e);
//Remove the bundle rights //Remove the bundle rights
@@ -841,7 +847,32 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
} }
@Override @Override
public WorkspaceItem sendWorkflowItemBackSubmission(Context context, XmlWorkflowItem wi, EPerson e, public void deleteWorkflowByWorkflowItem(Context context, XmlWorkflowItem wi, EPerson e)
throws SQLException, AuthorizeException, IOException {
Item myitem = wi.getItem();
UUID itemID = myitem.getID();
Integer workflowID = wi.getID();
UUID collID = wi.getCollection().getID();
// stop workflow
deleteAllTasks(context, wi);
context.turnOffAuthorisationSystem();
//Also clear all info for this step
workflowRequirementsService.clearInProgressUsers(context, wi);
// Remove (if any) the workflowItemroles for this item
workflowItemRoleService.deleteForWorkflowItem(context, wi);
// Now remove the workflow object manually from the database
xmlWorkflowItemService.deleteWrapper(context, wi);
// Now delete the item
itemService.delete(context, myitem);
log.info(LogManager.getHeader(context, "delete_workflow", "workflow_item_id="
+ workflowID + "item_id=" + itemID
+ "collection_id=" + collID + "eperson_id="
+ e.getID()));
context.restoreAuthSystemState();
}
@Override
public WorkspaceItem sendWorkflowItemBackSubmission(Context context, XmlWorkflowItem wi, EPerson e,
String provenance, String provenance,
String rejection_message) String rejection_message)
throws SQLException, AuthorizeException, throws SQLException, AuthorizeException,
@@ -1009,31 +1040,38 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
protected void notifyOfReject(Context c, XmlWorkflowItem wi, EPerson e, protected void notifyOfReject(Context c, XmlWorkflowItem wi, EPerson e,
String reason) { String reason) {
try { try {
// Get the item title // send the notification only if the person was not deleted in the
String title = wi.getItem().getName(); // meantime between submission and archiving.
EPerson eperson = wi.getSubmitter();
if (eperson != null) {
// Get the item title
String title = wi.getItem().getName();
// Get the collection // Get the collection
Collection coll = wi.getCollection(); Collection coll = wi.getCollection();
// Get rejector's name // Get rejector's name
String rejector = getEPersonName(e); String rejector = getEPersonName(e);
Locale supportedLocale = I18nUtil.getEPersonLocale(e); Locale supportedLocale = I18nUtil.getEPersonLocale(e);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject")); Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject"));
email.addRecipient(wi.getSubmitter().getEmail()); email.addRecipient(eperson.getEmail());
email.addArgument(title); email.addArgument(title);
email.addArgument(coll.getName()); email.addArgument(coll.getName());
email.addArgument(rejector); email.addArgument(rejector);
email.addArgument(reason); email.addArgument(reason);
email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/mydspace"); email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/mydspace");
email.send(); email.send();
} else {
// DO nothing
}
} catch (Exception ex) { } catch (Exception ex) {
// log this email error // log this email error
log.warn(LogManager.getHeader(c, "notify_of_reject", log.warn(LogManager.getHeader(c, "notify_of_reject",
"cannot email user" + " eperson_id" + e.getID() "cannot email user" + " eperson_id" + e.getID()
+ " eperson_email" + e.getEmail() + " eperson_email" + e.getEmail()
+ " workflow_item_id" + wi.getID())); + " workflow_item_id" + wi.getID()));
} }
} }

View File

@@ -34,6 +34,7 @@ public class AcceptEditRejectAction extends ProcessingAction {
public static final int MAIN_PAGE = 0; public static final int MAIN_PAGE = 0;
public static final int REJECT_PAGE = 1; public static final int REJECT_PAGE = 1;
public static final int SUBMITTER_IS_DELETED_PAGE = 2;
//TODO: rename to AcceptAndEditMetadataAction //TODO: rename to AcceptAndEditMetadataAction
@@ -52,6 +53,8 @@ public class AcceptEditRejectAction extends ProcessingAction {
return processMainPage(c, wfi, step, request); return processMainPage(c, wfi, step, request);
case REJECT_PAGE: case REJECT_PAGE:
return processRejectPage(c, wfi, step, request); return processRejectPage(c, wfi, step, request);
case SUBMITTER_IS_DELETED_PAGE:
return processSubmitterIsDeletedPage(c, wfi, request);
default: default:
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL); return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
} }
@@ -100,6 +103,23 @@ public class AcceptEditRejectAction extends ProcessingAction {
} }
} }
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
if (request.getParameter("submit_delete") != null) {
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
.deleteWorkflowByWorkflowItem(c, wfi, c.getCurrentUser());
// Delete and send user back to myDspace page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else if (request.getParameter("submit_keep_it") != null) {
// Do nothing, just send it back to myDspace page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else {
//Cancel, go back to the main task page
request.setAttribute("page", MAIN_PAGE);
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
}
}
private void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException { private void addApprovedProvenance(Context c, XmlWorkflowItem wfi) throws SQLException, AuthorizeException {
//Add the provenance for the accept //Add the provenance for the accept
String now = DCDate.getCurrent().toString(); String now = DCDate.getCurrent().toString();

View File

@@ -33,6 +33,7 @@ public class ReviewAction extends ProcessingAction {
public static final int MAIN_PAGE = 0; public static final int MAIN_PAGE = 0;
public static final int REJECT_PAGE = 1; public static final int REJECT_PAGE = 1;
public static final int SUBMITTER_IS_DELETED_PAGE = 2;
@Override @Override
@@ -50,6 +51,8 @@ public class ReviewAction extends ProcessingAction {
return processMainPage(c, wfi, step, request); return processMainPage(c, wfi, step, request);
case REJECT_PAGE: case REJECT_PAGE:
return processRejectPage(c, wfi, step, request); return processRejectPage(c, wfi, step, request);
case SUBMITTER_IS_DELETED_PAGE:
return processSubmitterIsDeletedPage(c, wfi, request);
default: default:
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL); return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
} }
@@ -114,4 +117,21 @@ public class ReviewAction extends ProcessingAction {
return new ActionResult(ActionResult.TYPE.TYPE_PAGE); return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
} }
} }
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
if (request.getParameter("submit_delete") != null) {
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
.deleteWorkflowByWorkflowItem(c, wfi, c.getCurrentUser());
// Delete and send user back to myDspace page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else if (request.getParameter("submit_keep_it") != null) {
// Do nothing, just send it back to myDspace page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else {
//Cancel, go back to the main task page
request.setAttribute("page", MAIN_PAGE);
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
}
}
} }

View File

@@ -35,6 +35,7 @@ public class SingleUserReviewAction extends ProcessingAction {
public static final int MAIN_PAGE = 0; public static final int MAIN_PAGE = 0;
public static final int REJECT_PAGE = 1; public static final int REJECT_PAGE = 1;
public static final int SUBMITTER_IS_DELETED_PAGE = 2;
public static final int OUTCOME_REJECT = 1; public static final int OUTCOME_REJECT = 1;
@@ -53,6 +54,8 @@ public class SingleUserReviewAction extends ProcessingAction {
return processMainPage(c, wfi, step, request); return processMainPage(c, wfi, step, request);
case REJECT_PAGE: case REJECT_PAGE:
return processRejectPage(c, wfi, step, request); return processRejectPage(c, wfi, step, request);
case SUBMITTER_IS_DELETED_PAGE:
return processSubmitterIsDeletedPage(c, wfi, request);
default: default:
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL); return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
} }
@@ -120,4 +123,21 @@ public class SingleUserReviewAction extends ProcessingAction {
return new ActionResult(ActionResult.TYPE.TYPE_PAGE); return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
} }
} }
public ActionResult processSubmitterIsDeletedPage(Context c, XmlWorkflowItem wfi, HttpServletRequest request)
throws SQLException, AuthorizeException, IOException {
if (request.getParameter("submit_delete") != null) {
XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService()
.deleteWorkflowByWorkflowItem(c, wfi, c.getCurrentUser());
// Delete and send user back to myDspace page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else if (request.getParameter("submit_keep_it") != null) {
// Do nothing, just send it back to myDspace page
return new ActionResult(ActionResult.TYPE.TYPE_SUBMISSION_PAGE);
} else {
//Cancel, go back to the main task page
request.setAttribute("page", MAIN_PAGE);
return new ActionResult(ActionResult.TYPE.TYPE_PAGE);
}
}
} }

View File

@@ -72,20 +72,22 @@ public class AssignOriginalSubmitterAction extends UserSelectionAction {
@Override @Override
public void alertUsersOnActivation(Context c, XmlWorkflowItem wfi, RoleMembers roleMembers) public void alertUsersOnActivation(Context c, XmlWorkflowItem wfi, RoleMembers roleMembers)
throws IOException, SQLException { throws IOException, SQLException {
try { if (wfi.getSubmitter() != null) {
XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService(); try {
xmlWorkflowService.alertUsersOnTaskActivation(c, wfi, "submit_task", Arrays.asList(wfi.getSubmitter()), XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService();
//The arguments xmlWorkflowService.alertUsersOnTaskActivation(c, wfi, "submit_task", Arrays.asList(wfi.getSubmitter()),
wfi.getItem().getName(), //The arguments
wfi.getCollection().getName(), wfi.getItem().getName(),
wfi.getSubmitter().getFullName(), wfi.getCollection().getName(),
//TODO: message wfi.getSubmitter().getFullName(),
"New task available.", //TODO: message
xmlWorkflowService.getMyDSpaceLink() "New task available.",
); xmlWorkflowService.getMyDSpaceLink()
} catch (MessagingException e) { );
log.info(LogManager.getHeader(c, "error emailing user(s) for claimed task", } catch (MessagingException e) {
log.info(LogManager.getHeader(c, "error emailing user(s) for claimed task",
"step: " + getParent().getStep().getId() + " workflowitem: " + wfi.getID())); "step: " + getParent().getStep().getId() + " workflowitem: " + wfi.getID()));
}
} }
} }
@@ -105,9 +107,9 @@ public class AssignOriginalSubmitterAction extends UserSelectionAction {
.getId() + " to assign a submitter to. Aborting the action."); .getId() + " to assign a submitter to. Aborting the action.");
throw new IllegalStateException(); throw new IllegalStateException();
} }
if (submitter != null) {
createTaskForEPerson(c, wfi, step, nextAction, submitter); createTaskForEPerson(c, wfi, step, nextAction, submitter);
}
//It is important that we return to the submission page since we will continue our actions with the submitter //It is important that we return to the submission page since we will continue our actions with the submitter
return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE); return new ActionResult(ActionResult.TYPE.TYPE_OUTCOME, ActionResult.OUTCOME_COMPLETE);
} }

View File

@@ -77,22 +77,25 @@ public class ClaimAction extends UserSelectionAction {
public void alertUsersOnActivation(Context c, XmlWorkflowItem wfi, RoleMembers roleMembers) public void alertUsersOnActivation(Context c, XmlWorkflowItem wfi, RoleMembers roleMembers)
throws IOException, SQLException { throws IOException, SQLException {
try { try {
EPerson ep = wfi.getSubmitter();
String submitterName = null;
if (ep != null) {
submitterName = ep.getFullName();
}
XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService(); XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService();
xmlWorkflowService.alertUsersOnTaskActivation(c, wfi, "submit_task", roleMembers.getAllUniqueMembers(c), xmlWorkflowService.alertUsersOnTaskActivation(c, wfi, "submit_task", roleMembers.getAllUniqueMembers(c),
//The arguments //The arguments
wfi.getItem().getName(), wfi.getItem().getName(),
wfi.getCollection().getName(), wfi.getCollection().getName(),
wfi.getSubmitter().getFullName(), submitterName,
//TODO: message //TODO: message
"New task available.", "New task available.",
xmlWorkflowService.getMyDSpaceLink() xmlWorkflowService.getMyDSpaceLink()
); );
} catch (MessagingException e) { } catch (MessagingException e) {
log.info(LogManager.getHeader(c, "error emailing user(s) for claimed task", log.info(LogManager.getHeader(c, "error emailing user(s) for claimed task",
"step: " + getParent().getStep().getId() + " workflowitem: " + wfi.getID())); "step: " + getParent().getStep().getId() + " workflowitem: " + wfi.getID()));
} }
} }
@Override @Override

View File

@@ -120,6 +120,19 @@ public class PoolTaskServiceImpl implements PoolTaskService {
} }
} }
@Override
public void deleteByEperson(Context context, EPerson ePerson)
throws SQLException, AuthorizeException, IOException {
List<PoolTask> tasks = findByEperson(context, ePerson);
//Use an iterator to remove the tasks !
Iterator<PoolTask> iterator = tasks.iterator();
while (iterator.hasNext()) {
PoolTask poolTask = iterator.next();
iterator.remove();
delete(context, poolTask);
}
}
@Override @Override
public List<PoolTask> findByEPerson(Context context, EPerson ePerson) throws SQLException { public List<PoolTask> findByEPerson(Context context, EPerson ePerson) throws SQLException {
return poolTaskDAO.findByEPerson(context, ePerson); return poolTaskDAO.findByEPerson(context, ePerson);

View File

@@ -58,6 +58,16 @@ public class WorkflowItemRoleServiceImpl implements WorkflowItemRoleService {
} }
} }
@Override
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException, AuthorizeException {
Iterator<WorkflowItemRole> workflowItemRoles = findByEPerson(context, ePerson).iterator();
while (workflowItemRoles.hasNext()) {
WorkflowItemRole workflowItemRole = workflowItemRoles.next();
workflowItemRoles.remove();
delete(context, workflowItemRole);
}
}
@Override @Override
public List<WorkflowItemRole> findByEPerson(Context context, EPerson ePerson) throws SQLException { public List<WorkflowItemRole> findByEPerson(Context context, EPerson ePerson) throws SQLException {
return workflowItemRoleDAO.findByEPerson(context, ePerson); return workflowItemRoleDAO.findByEPerson(context, ePerson);

View File

@@ -37,5 +37,7 @@ public interface PoolTaskService extends DSpaceCRUDService<PoolTask> {
public void deleteByWorkflowItem(Context context, XmlWorkflowItem xmlWorkflowItem) public void deleteByWorkflowItem(Context context, XmlWorkflowItem xmlWorkflowItem)
throws SQLException, AuthorizeException; throws SQLException, AuthorizeException;
public void deleteByEperson(Context context, EPerson ePerson) throws SQLException, AuthorizeException, IOException;
public List<PoolTask> findByEPerson(Context context, EPerson ePerson) throws SQLException; public List<PoolTask> findByEPerson(Context context, EPerson ePerson) throws SQLException;
} }

View File

@@ -33,5 +33,7 @@ public interface WorkflowItemRoleService extends DSpaceCRUDService<WorkflowItemR
public void deleteForWorkflowItem(Context context, XmlWorkflowItem wfi) throws SQLException, AuthorizeException; public void deleteForWorkflowItem(Context context, XmlWorkflowItem wfi) throws SQLException, AuthorizeException;
public void deleteByEPerson(Context context, EPerson ePerson) throws SQLException, AuthorizeException;
public List<WorkflowItemRole> findByEPerson(Context context, EPerson ePerson) throws SQLException; public List<WorkflowItemRole> findByEPerson(Context context, EPerson ePerson) throws SQLException;
} }

View File

@@ -6,6 +6,8 @@
# http://www.dspace.org/license/ # http://www.dspace.org/license/
# #
admin.name = DSpace Administrator
browse.page-title = Browsing DSpace browse.page-title = Browsing DSpace
browse.et-al = et al browse.et-al = et al
@@ -252,6 +254,12 @@ jsp.dspace-admin.eperson-browse.phone = Telephone
jsp.dspace-admin.eperson-browse.self = Self Registered jsp.dspace-admin.eperson-browse.self = Self Registered
jsp.dspace-admin.eperson-browse.title = E-People jsp.dspace-admin.eperson-browse.title = E-People
jsp.dspace-admin.eperson-confirm-delete.confirm = Are you sure this e-person should be deleted? jsp.dspace-admin.eperson-confirm-delete.confirm = Are you sure this e-person should be deleted?
jsp.dspace-admin.eperson-confirm-delete.confirm.constraint = This EPerson
jsp.dspace-admin.eperson-confirm-delete.confirm.item = has submitted one or more items which will be kept
jsp.dspace-admin.eperson-confirm-delete.confirm.workspaceitem = has unsubmitted workspace items which will be deleted
jsp.dspace-admin.eperson-confirm-delete.confirm.workflowitem = has an active submission workflow which will be put back into the pool
jsp.dspace-admin.eperson-confirm-delete.confirm.resourcepolicy = has resource policies associated with him which will be deleted
jsp.dspace-admin.eperson-confirm-delete.confirm.tasklistitem = has a workflow task awaiting their attention
jsp.dspace-admin.eperson-confirm-delete.heading = Delete e-person: {0} ({1}) jsp.dspace-admin.eperson-confirm-delete.heading = Delete e-person: {0} ({1})
jsp.dspace-admin.eperson-confirm-delete.title = Delete E-Person jsp.dspace-admin.eperson-confirm-delete.title = Delete E-Person
jsp.dspace-admin.eperson-deletion-error.errormsg = The EPerson {0} cannot be deleted because a reference to it exists in the following table(s): jsp.dspace-admin.eperson-deletion-error.errormsg = The EPerson {0} cannot be deleted because a reference to it exists in the following table(s):
@@ -576,7 +584,6 @@ jsp.general.without-contributor
jsp.general.without-date = No date given jsp.general.without-date = No date given
jsp.help = <span class="glyphicon glyphicon-question-sign"></span> jsp.help = <span class="glyphicon glyphicon-question-sign"></span>
jsp.help.formats.contact1 = Please contact your jsp.help.formats.contact1 = Please contact your
jsp.help.formats.contact2 = DSpace Administrator
jsp.help.formats.contact3 = if you have questions about a particular format. jsp.help.formats.contact3 = if you have questions about a particular format.
jsp.help.formats.extensions = Extensions jsp.help.formats.extensions = Extensions
jsp.help.formats.here = (Your Site's Format Support Policy Here) jsp.help.formats.here = (Your Site's Format Support Policy Here)
@@ -741,6 +748,12 @@ jsp.mydspace.reject-reason.cancel.button = Cancel Rejecti
jsp.mydspace.reject-reason.reject.button = Reject Item jsp.mydspace.reject-reason.reject.button = Reject Item
jsp.mydspace.reject-reason.text1 = Please enter the reason you are rejecting the submission into the box below. Please indicate in your message whether the submitter should fix a problem and resubmit. jsp.mydspace.reject-reason.text1 = Please enter the reason you are rejecting the submission into the box below. Please indicate in your message whether the submitter should fix a problem and resubmit.
jsp.mydspace.reject-reason.title = Enter Reason for Rejection jsp.mydspace.reject-reason.title = Enter Reason for Rejection
jsp.mydspace.reject-deleted-submitter.title = The Submitter of this item has been deleted
jsp.mydspace.reject-deleted-submitter.message = Do you want to delete the document, keep it as a task and work on it later or cancel the rejection process?
jsp.mydspace.reject-deleted-submitter-keep-it.button = Keep it I will work on it later
jsp.mydspace.reject-deleted-submitter-delete.button = Delete Item
jsp.mydspace.reject-deleted-submitter-delete.title = Delete successfully
jsp.mydspace.reject-deleted-submitter-delete.info = Reviewing task is done, the submitted item has been successfully removed from the system.
jsp.mydspace.remove-item.cancel.button = Cancel Removal jsp.mydspace.remove-item.cancel.button = Cancel Removal
jsp.mydspace.remove-item.confirmation = Are you sure you want to remove the following incomplete item? jsp.mydspace.remove-item.confirmation = Are you sure you want to remove the following incomplete item?
jsp.mydspace.remove-item.remove.button = Remove the Item jsp.mydspace.remove-item.remove.button = Remove the Item
@@ -1643,6 +1656,7 @@ org.dspace.workflow.WorkflowManager.step1
org.dspace.workflow.WorkflowManager.step2 = The submission must be checked before inclusion in the archive. org.dspace.workflow.WorkflowManager.step2 = The submission must be checked before inclusion in the archive.
org.dspace.workflow.WorkflowManager.step3 = The metadata needs to be checked to ensure compliance with the collection's standards, and edited if necessary. org.dspace.workflow.WorkflowManager.step3 = The metadata needs to be checked to ensure compliance with the collection's standards, and edited if necessary.
org.dspace.workflow.WorkflowManager.untitled = Untitled org.dspace.workflow.WorkflowManager.untitled = Untitled
org.dspace.workflow.WorkflowManager.deleted-submitter = Unknown (deleted submitter)
search.order.asc = Ascending search.order.asc = Ascending
search.order.desc = Descending search.order.desc = Descending
@@ -1824,6 +1838,11 @@ In response to your request I have the pleasure to send you in attachment a copy
Best regards,\n\ Best regards,\n\
{3} <{4}> {3} <{4}>
itemRequest.admin.response.body.approve = Dear {0},\n\
In response to your request I have the pleasure to send you in attachment a copy of the file(s) concerning the document: "{2}" ({1}).\n\n\
Best regards,\n\
{3}
itemRequest.response.subject.reject = Request copy of document itemRequest.response.subject.reject = Request copy of document
itemRequest.response.body.reject = Dear {0},\n\ itemRequest.response.body.reject = Dear {0},\n\
In response to your request I regret to inform you that it''s not possible to send you a copy of the file(s) you have requested, concerning the document: "{2}" ({1}), of which I am author (or co-author).\n\n\ In response to your request I regret to inform you that it''s not possible to send you a copy of the file(s) you have requested, concerning the document: "{2}" ({1}), of which I am author (or co-author).\n\n\
@@ -1845,6 +1864,12 @@ itemRequest.response.body.contactRequester = Dear {0},\n\n\
Thanks for your interest! Since the author owns the copyright for this work, I will contact the author and ask permission to send you a copy. I''ll let you know as soon as I hear from the author.\n\n\ Thanks for your interest! Since the author owns the copyright for this work, I will contact the author and ask permission to send you a copy. I''ll let you know as soon as I hear from the author.\n\n\
Thanks!\n\ Thanks!\n\
{1} <{2}> {1} <{2}>
itemRequest.admin.response.body.reject = Dear {0},\n\
In response to your request I regret to inform you that it''s not possible to send you a copy of the file(s) you have requested, concerning the document: "{2}" ({1}).\n\n\
Best regards,\n\
{3}
jsp.request.item.request-form.info2 = Request a document copy: {0} jsp.request.item.request-form.info2 = Request a document copy: {0}
jsp.request.item.request-form.problem = You must fill all the missing fields. jsp.request.item.request-form.problem = You must fill all the missing fields.
jsp.request.item.request-form.reqname = Requester name: jsp.request.item.request-form.reqname = Requester name:
@@ -1886,7 +1911,8 @@ jsp.request.item.request-free-acess.free = Change to Open Access
jsp.request.item.request-free-acess.name = Name: jsp.request.item.request-free-acess.name = Name:
jsp.request.item.request-free-acess.email = E-mail: jsp.request.item.request-free-acess.email = E-mail:
org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed = Corresponding Author org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed = Corresponding Author
org.dspace.app.requestitem.RequestItemHelpdeskStrategy.helpdeskname = Help Desk org.dspace.app.requestitem.helpdeskname = Help Desk
org.dspace.app.requestitem.default-author-name = DSpace User
org.dspace.app.webui.jsptag.ItemTag.restrict = Request a copy org.dspace.app.webui.jsptag.ItemTag.restrict = Request a copy
jsp.layout.navbar-admin.batchimport = Batch import jsp.layout.navbar-admin.batchimport = Batch import

File diff suppressed because it is too large Load Diff

View File

@@ -51,7 +51,9 @@ public class ItemRepositoryBuilder {
doc.addField("item.id", item.getId()); doc.addField("item.id", item.getId());
doc.addField("item.public", item.isPublic()); doc.addField("item.public", item.isPublic());
doc.addField("item.lastmodified", item.getLastModifiedDate()); doc.addField("item.lastmodified", item.getLastModifiedDate());
doc.addField("item.submitter", item.getSubmitter()); if (item.getSubmitter() != null) {
doc.addField("item.submitter", item.getSubmitter());
}
doc.addField("item.handle", item.getHandle()); doc.addField("item.handle", item.getHandle());
doc.addField("item.deleted", item.isDeleted()); doc.addField("item.deleted", item.isDeleted());

View File

@@ -0,0 +1,13 @@
Subject: Request copy of document
Dear Administrator,
A user of {7}, named {0} and using the email {1}, requested a copy of the file(s) associated with the document: "{4}" ({3}).
This request came along with the following message:
"{5}"
To answer, click {6}.
PLEASE REDIRECT THIS MESSAGE TO THE AUTHOR(S).