[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
*/
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);
} else {
String helpdeskName = I18nUtil.getMessage(
"org.dspace.app.requestitem.RequestItemHelpdeskStrategy.helpdeskname",
context);
"org.dspace.app.requestitem.helpdeskname", context);
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.core.Context;
import org.dspace.core.I18nUtil;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
@@ -38,6 +39,7 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
@Override
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
throws SQLException {
RequestItemAuthor author = null;
if (emailMetadata != null) {
List<MetadataValue> vals = itemService.getMetadataByMetadataString(item, emailMetadata);
if (vals.size() > 0) {
@@ -49,19 +51,37 @@ public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy {
fullname = nameVals.iterator().next().getValue();
}
}
if (StringUtils.isBlank(fullname)) {
fullname = I18nUtil
.getMessage(
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
context);
.getMessage(
"org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed",
context);
}
RequestItemAuthor author = new RequestItemAuthor(
fullname, email);
author = new RequestItemAuthor(fullname, email);
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) {

View File

@@ -23,13 +23,22 @@ public class RequestItemSubmitterStrategy implements RequestItemAuthorExtractor
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
public RequestItemAuthor getRequestItemAuthor(Context context, Item item)
throws SQLException {
EPerson submitter = item.getSubmitter();
RequestItemAuthor author = new RequestItemAuthor(
submitter.getFullName(), submitter.getEmail());
RequestItemAuthor author = null;
if (null != submitter) {
author = new RequestItemAuthor(
submitter.getFullName(), submitter.getEmail());
}
return author;
}
}

View File

@@ -606,6 +606,12 @@ public class AuthorizeServiceImpl implements AuthorizeService {
resourcePolicyService.removeDsoEPersonPolicies(c, o, e);
}
@Override
public void removeAllEPersonPolicies(Context c, EPerson e)
throws SQLException, AuthorizeException {
resourcePolicyService.removeAllEPersonPolicies(c, e);
}
@Override
public List<Group> getAuthorizedGroups(Context c, DSpaceObject o,
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);
}
@Override
public List<ResourcePolicy> find(Context context, EPerson ePerson) throws SQLException {
return resourcePolicyDAO.findByEPerson(context, ePerson);
}
@Override
public List<ResourcePolicy> findByTypeGroupActionExceptId(Context context, DSpaceObject dso, Group group,
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
public void removeGroupPolicies(Context c, Group group) throws SQLException {
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)
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> 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 deleteAllEPersonPolicies(Context context, EPerson ePerson) 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);
}
@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
public List<ResourcePolicy> findByGroup(Context context, Group group) throws SQLException {
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
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;
/**
* 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
* 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 c, EPerson ePerson) throws SQLException;
public List<ResourcePolicy> find(Context c, EPerson e, List<Group> groups, int action, int type_id)
throws SQLException;
@@ -71,6 +73,8 @@ public interface ResourcePolicyService extends DSpaceCRUDService<ResourcePolicy>
public void removeDsoEPersonPolicies(Context context, DSpaceObject dso, EPerson ePerson)
throws SQLException, AuthorizeException;
public void removeAllEPersonPolicies(Context context, EPerson ePerson) throws SQLException, AuthorizeException;
public void removeGroupPolicies(Context c, Group group) throws SQLException;
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);
}
@Override
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, boolean retrieveAllItems)
throws SQLException {
return itemDAO.findBySubmitter(context, eperson, retrieveAllItems);
}
@Override
public Iterator<Item> findBySubmitterDateSorted(Context context, EPerson eperson, Integer limit)
throws SQLException {

View File

@@ -208,9 +208,8 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
*/
Item item = workspaceItem.getItem();
if (!authorizeService.isAdmin(context)
&& ((context.getCurrentUser() == null) || (context
.getCurrentUser().getID() != item.getSubmitter()
.getID()))) {
&& (item.getSubmitter() == null || (context.getCurrentUser() == null)
|| (context.getCurrentUser().getID() != item.getSubmitter().getID()))) {
// Not an admit, not the submitter
throw new AuthorizeException("Must be an administrator or the "
+ "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, boolean retrieveAllItems)
throws SQLException;
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, MetadataField metadataField, int limit)
throws SQLException;

View File

@@ -104,6 +104,17 @@ public class ItemDAOImpl extends AbstractHibernateDSODAO<Item> implements ItemDA
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
public Iterator<Item> findBySubmitter(Context context, EPerson eperson, MetadataField metadataField, int limit)
throws SQLException {

View File

@@ -110,6 +110,19 @@ public interface ItemService extends DSpaceObjectService<Item>, DSpaceObjectLega
public Iterator<Item> findBySubmitter(Context context, EPerson eperson)
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
*

View File

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

View File

@@ -9,6 +9,8 @@ package org.dspace.eperson;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
/**
* Exception indicating that an EPerson may not be deleted due to the presence
* of the EPerson's ID in certain tables
@@ -33,7 +35,10 @@ public class EPersonDeletionException extends Exception {
* deleted if it exists in these tables.
*/
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;
}

View File

@@ -7,9 +7,11 @@
*/
package org.dspace.eperson;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -21,11 +23,16 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.DSpaceObjectServiceImpl;
import org.dspace.content.Item;
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.WorkspaceItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
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.SubscribeService;
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.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;
/**
* Service implementation for the EPerson object.
* This class is responsible for all business logic calls for the EPerson object and is autowired by spring.
* Service implementation for the EPerson object. This class is responsible for
* all business logic calls for the EPerson object and is autowired by spring.
* This class should never be accessed directly.
*
* @author kevinvandevelde at atmire.com
@@ -61,6 +91,8 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
protected ItemService itemService;
@Autowired(required = true)
protected SubscribeService subscribeService;
@Autowired(required = true)
protected VersionDAO versionDAO;
protected EPersonServiceImpl() {
super();
@@ -129,7 +161,7 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
query = null;
}
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?
if (!authorizeService.isAdmin(context)) {
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
EPerson e = ePersonDAO.create(context, new EPerson());
log.info(LogManager.getHeader(context, "create_eperson", "eperson_id="
+ e.getID()));
+ e.getID()));
context.addEvent(new Event(Event.CREATE, Constants.EPERSON, e.getID(),
null, getIdentifiers(context, e)));
null, getIdentifiers(context, e)));
return e;
}
@Override
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?
if (!authorizeService.isAdmin(context)) {
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
// have constraints on eperson_id
List<String> constraintList = getDeleteConstraints(context, ePerson);
// if eperson exists in tables that have constraints
// on eperson, throw an exception
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(),
getIdentifiers(context, ePerson)));
getIdentifiers(context, ePerson)));
// XXX FIXME: This sidesteps the object model code so it won't
// generate REMOVE events on the affected Groups.
// Remove any group memberships first
// Remove any group memberships first
Iterator<Group> groups = ePerson.getGroups().iterator();
@@ -234,7 +413,7 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
ePersonDAO.delete(context, ePerson);
log.info(LogManager.getHeader(context, "delete_eperson",
"eperson_id=" + ePerson.getID()));
"eperson_id=" + ePerson.getID()));
}
@Override
@@ -268,8 +447,8 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
PasswordHash hash = null;
try {
hash = new PasswordHash(ePerson.getDigestAlgorithm(),
ePerson.getSalt(),
ePerson.getPassword());
ePerson.getSalt(),
ePerson.getPassword());
} catch (DecoderException ex) {
log.error("Problem decoding stored salt or hash: " + ex.getMessage());
}
@@ -281,9 +460,9 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
PasswordHash myHash;
try {
myHash = new PasswordHash(
ePerson.getDigestAlgorithm(),
ePerson.getSalt(),
ePerson.getPassword());
ePerson.getDigestAlgorithm(),
ePerson.getSalt(),
ePerson.getPassword());
} catch (DecoderException ex) {
log.error(ex.getMessage());
return false;
@@ -312,8 +491,8 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
// Check authorisation - if you're not the eperson
// see if the authorization system says you can
if (!context.ignoreAuthorization()
&& ((context.getCurrentUser() == null) || (ePerson.getID() != context
.getCurrentUser().getID()))) {
&& ((context.getCurrentUser() == null) || (ePerson.getID() != context
.getCurrentUser().getID()))) {
authorizeService.authorizeAction(context, ePerson, Constants.WRITE);
}
@@ -322,11 +501,11 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
ePersonDAO.save(context, ePerson);
log.info(LogManager.getHeader(context, "update_eperson",
"eperson_id=" + ePerson.getID()));
"eperson_id=" + ePerson.getID()));
if (ePerson.isModified()) {
context.addEvent(new Event(Event.MODIFY, Constants.EPERSON,
ePerson.getID(), null, getIdentifiers(context, ePerson)));
ePerson.getID(), null, getIdentifiers(context, ePerson)));
ePerson.clearModified();
}
if (ePerson.isMetadataModified()) {
@@ -339,11 +518,22 @@ public class EPersonServiceImpl extends DSpaceObjectServiceImpl<EPerson> impleme
List<String> tableList = new ArrayList<String>();
// check for eperson in item table
Iterator<Item> itemsBySubmitter = itemService.findBySubmitter(context, ePerson);
Iterator<Item> itemsBySubmitter = itemService.findBySubmitter(context, ePerson, true);
if (itemsBySubmitter.hasNext()) {
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();
List<String> workflowConstraints = workflowService.getEPersonDeleteConstraints(context, ePerson);
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;
/**
* 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,
String rejection_message)
throws SQLException, AuthorizeException, IOException;

View File

@@ -798,33 +798,38 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
try {
// Get submitter
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
String handle = handleService.findHandle(context, item);
// send the notification only if the person was not deleted in the
// 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
String title = item.getName();
if (StringUtils.isBlank(title)) {
try {
title = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled");
} catch (MissingResourceException e) {
title = "Untitled";
// Get the item handle to email to user
String handle = handleService.findHandle(context, item);
// Get title
String title = item.getName();
if (StringUtils.isBlank(title)) {
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) {
log.warn(LogManager.getHeader(context, "notifyOfArchive",
"cannot email user; item_id=" + item.getID()
+ ": " + e.getMessage()));
"cannot email user; item_id=" + item.getID()
+ ": " + e.getMessage()));
}
}
@@ -866,6 +871,24 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
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
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,
String reason) {
try {
// Get the item title
String title = getItemTitle(workflowItem);
// Get submitter
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
Collection coll = workflowItem.getCollection();
// Get the collection
Collection coll = workflowItem.getCollection();
// Get rejector's name
String rejector = getEPersonName(e);
Locale supportedLocale = I18nUtil.getEPersonLocale(e);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject"));
// Get rejector's name
String rejector = getEPersonName(e);
Locale supportedLocale = I18nUtil.getEPersonLocale(e);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject"));
email.addRecipient(workflowItem.getSubmitter().getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(rejector);
email.addArgument(reason);
email.addArgument(getMyDSpaceLink());
email.addRecipient(ep.getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(rejector);
email.addArgument(reason);
email.addArgument(getMyDSpaceLink());
email.send();
email.send();
}
} catch (RuntimeException re) {
// log this email error
log.warn(LogManager.getHeader(context, "notify_of_reject",
@@ -1101,7 +1129,9 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService {
@Override
public String getSubmitterName(BasicWorkflowItem wi) throws SQLException {
EPerson e = wi.getSubmitter();
if (e == null) {
return null;
}
return getEPersonName(e);
}

View File

@@ -46,6 +46,17 @@ public class TaskListItemServiceImpl implements TaskListItemService {
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
public void update(Context context, TaskListItem taskListItem) throws SQLException {
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 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;
}

View File

@@ -42,6 +42,24 @@ public class TaskListItemDAOImpl extends AbstractHibernateDAO<TaskListItem> impl
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
public List<TaskListItem> findByEPerson(Context context, EPerson ePerson) throws SQLException {
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);

View File

@@ -28,6 +28,11 @@ public interface TaskListItemService {
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 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 {
//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();
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());
if (null != submitter) {
//A list of policies the user has for this item
List<Integer> userHasPolicies = new ArrayList<>();
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 {
// Get submitter
EPerson ep = item.getSubmitter();
// Get the Locale
Locale supportedLocale = I18nUtil.getEPersonLocale(ep);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive"));
// send the notification only if the person was not deleted in the
// meantime between submission and archiving.
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
String handle = handleService.findHandle(context, item);
// Get the item handle to email to user
String handle = handleService.findHandle(context, item);
// Get title
List<MetadataValue> titles = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "title", null, Item.ANY);
String title = "";
try {
title = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled");
} catch (MissingResourceException e) {
title = "Untitled";
// Get title
List<MetadataValue> titles = itemService
.getMetadata(item, MetadataSchema.DC_SCHEMA, "title", null, Item.ANY);
String title = "";
try {
title = I18nUtil.getMessage("org.dspace.workflow.WorkflowManager.untitled");
} catch (MissingResourceException e) {
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) {
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 {
if (e != null) {
if (e != null && item.getSubmitter() != null) {
//Also remove any lingering authorizations from this user
authorizeService.removeEPersonPolicies(context, item, e);
//Remove the bundle rights
@@ -825,7 +831,7 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
protected void removeGroupItemPolicies(Context context, Item item, Group e)
throws SQLException, AuthorizeException {
if (e != null) {
if (e != null && item.getSubmitter() != null) {
//Also remove any lingering authorizations from this user
authorizeService.removeGroupPolicies(context, item, e);
//Remove the bundle rights
@@ -841,7 +847,32 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
}
@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 rejection_message)
throws SQLException, AuthorizeException,
@@ -1009,31 +1040,38 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
protected void notifyOfReject(Context c, XmlWorkflowItem wi, EPerson e,
String reason) {
try {
// Get the item title
String title = wi.getItem().getName();
// send the notification only if the person was not deleted in the
// meantime between submission and archiving.
EPerson eperson = wi.getSubmitter();
if (eperson != null) {
// Get the item title
String title = wi.getItem().getName();
// Get the collection
Collection coll = wi.getCollection();
// Get the collection
Collection coll = wi.getCollection();
// Get rejector's name
String rejector = getEPersonName(e);
Locale supportedLocale = I18nUtil.getEPersonLocale(e);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject"));
// Get rejector's name
String rejector = getEPersonName(e);
Locale supportedLocale = I18nUtil.getEPersonLocale(e);
Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_reject"));
email.addRecipient(wi.getSubmitter().getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(rejector);
email.addArgument(reason);
email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/mydspace");
email.addRecipient(eperson.getEmail());
email.addArgument(title);
email.addArgument(coll.getName());
email.addArgument(rejector);
email.addArgument(reason);
email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/mydspace");
email.send();
email.send();
} else {
// DO nothing
}
} catch (Exception ex) {
// log this email error
log.warn(LogManager.getHeader(c, "notify_of_reject",
"cannot email user" + " eperson_id" + e.getID()
+ " eperson_email" + e.getEmail()
+ " workflow_item_id" + wi.getID()));
"cannot email user" + " eperson_id" + e.getID()
+ " eperson_email" + e.getEmail()
+ " 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 REJECT_PAGE = 1;
public static final int SUBMITTER_IS_DELETED_PAGE = 2;
//TODO: rename to AcceptAndEditMetadataAction
@@ -52,6 +53,8 @@ public class AcceptEditRejectAction extends ProcessingAction {
return processMainPage(c, wfi, step, request);
case REJECT_PAGE:
return processRejectPage(c, wfi, step, request);
case SUBMITTER_IS_DELETED_PAGE:
return processSubmitterIsDeletedPage(c, wfi, request);
default:
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 {
//Add the provenance for the accept
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 REJECT_PAGE = 1;
public static final int SUBMITTER_IS_DELETED_PAGE = 2;
@Override
@@ -50,6 +51,8 @@ public class ReviewAction extends ProcessingAction {
return processMainPage(c, wfi, step, request);
case REJECT_PAGE:
return processRejectPage(c, wfi, step, request);
case SUBMITTER_IS_DELETED_PAGE:
return processSubmitterIsDeletedPage(c, wfi, request);
default:
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
}
@@ -114,4 +117,21 @@ public class ReviewAction extends ProcessingAction {
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 REJECT_PAGE = 1;
public static final int SUBMITTER_IS_DELETED_PAGE = 2;
public static final int OUTCOME_REJECT = 1;
@@ -53,6 +54,8 @@ public class SingleUserReviewAction extends ProcessingAction {
return processMainPage(c, wfi, step, request);
case REJECT_PAGE:
return processRejectPage(c, wfi, step, request);
case SUBMITTER_IS_DELETED_PAGE:
return processSubmitterIsDeletedPage(c, wfi, request);
default:
return new ActionResult(ActionResult.TYPE.TYPE_CANCEL);
}
@@ -120,4 +123,21 @@ public class SingleUserReviewAction extends ProcessingAction {
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
public void alertUsersOnActivation(Context c, XmlWorkflowItem wfi, RoleMembers roleMembers)
throws IOException, SQLException {
try {
XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService();
xmlWorkflowService.alertUsersOnTaskActivation(c, wfi, "submit_task", Arrays.asList(wfi.getSubmitter()),
//The arguments
wfi.getItem().getName(),
wfi.getCollection().getName(),
wfi.getSubmitter().getFullName(),
//TODO: message
"New task available.",
xmlWorkflowService.getMyDSpaceLink()
);
} catch (MessagingException e) {
log.info(LogManager.getHeader(c, "error emailing user(s) for claimed task",
if (wfi.getSubmitter() != null) {
try {
XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService();
xmlWorkflowService.alertUsersOnTaskActivation(c, wfi, "submit_task", Arrays.asList(wfi.getSubmitter()),
//The arguments
wfi.getItem().getName(),
wfi.getCollection().getName(),
wfi.getSubmitter().getFullName(),
//TODO: message
"New task available.",
xmlWorkflowService.getMyDSpaceLink()
);
} catch (MessagingException e) {
log.info(LogManager.getHeader(c, "error emailing user(s) for claimed task",
"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.");
throw new IllegalStateException();
}
createTaskForEPerson(c, wfi, step, nextAction, submitter);
if (submitter != null) {
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
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)
throws IOException, SQLException {
try {
EPerson ep = wfi.getSubmitter();
String submitterName = null;
if (ep != null) {
submitterName = ep.getFullName();
}
XmlWorkflowService xmlWorkflowService = XmlWorkflowServiceFactory.getInstance().getXmlWorkflowService();
xmlWorkflowService.alertUsersOnTaskActivation(c, wfi, "submit_task", roleMembers.getAllUniqueMembers(c),
//The arguments
wfi.getItem().getName(),
wfi.getCollection().getName(),
wfi.getSubmitter().getFullName(),
//TODO: message
"New task available.",
xmlWorkflowService.getMyDSpaceLink()
//The arguments
wfi.getItem().getName(),
wfi.getCollection().getName(),
submitterName,
//TODO: message
"New task available.",
xmlWorkflowService.getMyDSpaceLink()
);
} 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()));
}
}
@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
public List<PoolTask> findByEPerson(Context context, EPerson ePerson) throws SQLException {
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
public List<WorkflowItemRole> findByEPerson(Context context, EPerson ePerson) throws SQLException {
return workflowItemRoleDAO.findByEPerson(context, ePerson);

View File

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

View File

@@ -6,6 +6,8 @@
# http://www.dspace.org/license/
#
admin.name = DSpace Administrator
browse.page-title = Browsing DSpace
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.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.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.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):
@@ -576,7 +584,6 @@ jsp.general.without-contributor
jsp.general.without-date = No date given
jsp.help = <span class="glyphicon glyphicon-question-sign"></span>
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.extensions = Extensions
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.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-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.confirmation = Are you sure you want to remove the following incomplete 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.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.deleted-submitter = Unknown (deleted submitter)
search.order.asc = Ascending
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\
{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.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\
@@ -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!\n\
{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.problem = You must fill all the missing fields.
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.email = E-mail:
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
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.public", item.isPublic());
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.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).