[DS-3431] Harden DSpace's BasicWorfklowService

This commit is contained in:
Pascal-Nicolas Becker
2017-04-18 17:06:55 +02:00
committed by Tim Donohue
parent b0ed059ab5
commit 04ec199ff3
23 changed files with 4740 additions and 290 deletions

View File

@@ -18,6 +18,7 @@ import org.hibernate.proxy.HibernateProxyHelper;
import javax.persistence.*; import javax.persistence.*;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
import org.dspace.authorize.AuthorizeException;
/** /**
* Class representing a collection. * Class representing a collection.
@@ -335,9 +336,10 @@ public class Collection extends DSpaceObject implements DSpaceObjectLegacySuppor
return Constants.COLLECTION; return Constants.COLLECTION;
} }
public void setWorkflowGroup(int step, Group g) public void setWorkflowGroup(Context context, int step, Group g)
throws SQLException, AuthorizeException
{ {
getCollectionService().setWorkflowGroup(this, step, g); getCollectionService().setWorkflowGroup(context, this, step, g);
} }
@Override @Override

View File

@@ -32,6 +32,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
import org.dspace.authorize.service.ResourcePolicyService;
/** /**
* Service implementation for the Collection object. * Service implementation for the Collection object.
@@ -51,6 +52,8 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl<Collection> i
@Autowired(required = true) @Autowired(required = true)
protected AuthorizeService authorizeService; protected AuthorizeService authorizeService;
@Autowired(required = true) @Autowired(required = true)
protected ResourcePolicyService resourcePolicyService;
@Autowired(required = true)
protected BitstreamService bitstreamService; protected BitstreamService bitstreamService;
@Autowired(required = true) @Autowired(required = true)
protected ItemService itemService; protected ItemService itemService;
@@ -334,30 +337,77 @@ public class CollectionServiceImpl extends DSpaceObjectServiceImpl<Collection> i
groupService.setName(g, groupService.setName(g,
"COLLECTION_" + collection.getID() + "_WORKFLOW_STEP_" + step); "COLLECTION_" + collection.getID() + "_WORKFLOW_STEP_" + step);
groupService.update(context, g); groupService.update(context, g);
setWorkflowGroup(collection, step, g); setWorkflowGroup(context, collection, step, g);
authorizeService.addPolicy(context, collection, Constants.ADD, g);
} }
return getWorkflowGroup(collection, step); return getWorkflowGroup(collection, step);
} }
@Override @Override
public void setWorkflowGroup(Collection collection, int step, Group group) { public void setWorkflowGroup(Context context, Collection collection, int step, Group group)
throws SQLException, AuthorizeException
{
// we need to store the old group to be able to revoke permissions if granted before
Group oldGroup = null;
int action;
switch (step) switch (step)
{ {
case 1: case 1:
oldGroup = collection.getWorkflowStep1();
action = Constants.WORKFLOW_STEP_1;
collection.setWorkflowStep1(group); collection.setWorkflowStep1(group);
break; break;
case 2: case 2:
oldGroup = collection.getWorkflowStep2();
action = Constants.WORKFLOW_STEP_2;
collection.setWorkflowStep2(group); collection.setWorkflowStep2(group);
break; break;
case 3: case 3:
oldGroup = collection.getWorkflowStep3();
action = Constants.WORKFLOW_STEP_3;
collection.setWorkflowStep3(group); collection.setWorkflowStep3(group);
break; break;
default: default:
throw new IllegalArgumentException("Illegal step count: " + step); throw new IllegalArgumentException("Illegal step count: " + step);
} }
// deal with permissions.
try
{
context.turnOffAuthorisationSystem();
// remove the policies for the old group
if (oldGroup != null)
{
Iterator<ResourcePolicy> oldPolicies =
resourcePolicyService.find(context, collection, oldGroup, action).iterator();
while (oldPolicies.hasNext())
{
resourcePolicyService.delete(context, oldPolicies.next());
}
oldPolicies = resourcePolicyService.find(context, collection, oldGroup, Constants.ADD).iterator();
while (oldPolicies.hasNext())
{
ResourcePolicy rp = oldPolicies.next();
if (rp.getRpType() == ResourcePolicy.TYPE_WORKFLOW)
{
resourcePolicyService.delete(context, rp);
}
}
}
// group can be null to delete workflow step.
// we need to grant permissions if group is not null
if (group != null)
{
authorizeService.addPolicy(context, collection, action, group, ResourcePolicy.TYPE_WORKFLOW);
authorizeService.addPolicy(context, collection, Constants.ADD, group, ResourcePolicy.TYPE_WORKFLOW);
}
} finally {
context.restoreAuthSystemState();
}
collection.setModified();
} }
@Override @Override

View File

@@ -93,11 +93,8 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
Item item = itemService.create(context, workspaceItem); Item item = itemService.create(context, workspaceItem);
item.setSubmitter(context.getCurrentUser()); item.setSubmitter(context.getCurrentUser());
// Now create the policies for the submitter and workflow // Now create the policies for the submitter to modify item and contents
// users to modify item and contents
// contents = bitstreams, bundles // contents = bitstreams, bundles
// FIXME: icky hardcoded workflow steps
workflowService.addInitialWorkspaceItemPolicies(context, workspaceItem);
// read permission // read permission
authorizeService.addPolicy(context, item, Constants.READ, item.getSubmitter(), ResourcePolicy.TYPE_SUBMISSION); authorizeService.addPolicy(context, item, Constants.READ, item.getSubmitter(), ResourcePolicy.TYPE_SUBMISSION);
// write permission // write permission

View File

@@ -164,7 +164,8 @@ public interface CollectionService extends DSpaceObjectService<Collection>, DSpa
* @param group * @param group
* the new workflow group, or <code>null</code> * the new workflow group, or <code>null</code>
*/ */
public void setWorkflowGroup(Collection collection, int step, Group group); public void setWorkflowGroup(Context context, Collection collection, int step, Group group)
throws SQLException, AuthorizeException;
/** /**
* Get the the workflow group corresponding to a particular workflow step. * Get the the workflow group corresponding to a particular workflow step.

View File

@@ -190,7 +190,7 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
//If we have an ePerson, check we can find membership in the database //If we have an ePerson, check we can find membership in the database
if(ePerson != null) { if(ePerson != null) {
//lookup eperson in normal groups and subgroups with 1 query //lookup eperson in normal groups and subgroups with 1 query
isMember = isEPersonInGroup(context, group.getName(), ePerson); isMember = isEPersonInGroup(context, group, ePerson);
} }
//If we did not find the group membership in the database, check the special groups. //If we did not find the group membership in the database, check the special groups.
@@ -539,10 +539,10 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
protected boolean isEPersonInGroup(Context context, String groupName, EPerson ePerson) protected boolean isEPersonInGroup(Context context, Group group, EPerson ePerson)
throws SQLException throws SQLException
{ {
return groupDAO.findByNameAndMembership(context, groupName, ePerson) != null; return groupDAO.findByIdAndMembership(context, group.getID(), ePerson) != null;
} }

View File

@@ -129,11 +129,11 @@ public interface GroupDAO extends DSpaceObjectDAO<Group>, DSpaceObjectLegacySupp
/** /**
* Find a group by its name and the membership of the given EPerson * Find a group by its name and the membership of the given EPerson
* @param context The DSpace context * @param context The DSpace context
* @param groupName The name of the group to look for * @param id The id of the group to look for
* @param ePerson The EPerson which has to be a member * @param ePerson The EPerson which has to be a member
* @return The group with the specified name * @return The group with the specified name
* @throws SQLException if database error * @throws SQLException if database error
*/ */
Group findByNameAndMembership(Context context, String groupName, EPerson ePerson) throws SQLException; Group findByIdAndMembership(Context context, UUID id, EPerson ePerson) throws SQLException;
} }

View File

@@ -113,14 +113,14 @@ public class GroupDAOImpl extends AbstractHibernateDSODAO<Group> implements Grou
} }
@Override @Override
public Group findByNameAndMembership(Context context, String groupName, EPerson ePerson) throws SQLException { public Group findByIdAndMembership(Context context, UUID id, EPerson ePerson) throws SQLException {
if(groupName == null || ePerson == null) { if(id == null || ePerson == null) {
return null; return null;
} else { } else {
Query query = createQuery(context, Query query = createQuery(context,
"SELECT DISTINCT g FROM Group g " + "SELECT DISTINCT g FROM Group g " +
"LEFT JOIN g.epeople p " + "LEFT JOIN g.epeople p " +
"WHERE g.name = :name AND " + "WHERE g.id = :id AND " +
"(p.id = :eperson_id OR " + "(p.id = :eperson_id OR " +
"EXISTS ( " + "EXISTS ( " +
"SELECT 1 FROM Group2GroupCache gc " + "SELECT 1 FROM Group2GroupCache gc " +
@@ -131,7 +131,7 @@ public class GroupDAOImpl extends AbstractHibernateDSODAO<Group> implements Grou
") " + ") " +
")"); ")");
query.setParameter("name", groupName); query.setParameter("id", id);
query.setParameter("eperson_id", ePerson.getID()); query.setParameter("eperson_id", ePerson.getID());
query.setCacheable(true); query.setCacheable(true);

View File

@@ -0,0 +1,58 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.storage.rdbms.migration;
import org.dspace.core.Constants;
import org.dspace.storage.rdbms.DatabaseUtils;
import org.flywaydb.core.api.migration.MigrationChecksumProvider;
import org.flywaydb.core.api.migration.jdbc.JdbcMigration;
import org.flywaydb.core.internal.util.scanner.classpath.ClassPathResource;
import java.sql.Connection;
public class V5_7_2017_05_05__DS_3431_Add_Policies_for_BasicWorkflow
implements JdbcMigration, MigrationChecksumProvider
{
// Size of migration script run
Integer migration_file_size = -1;
@Override
public void migrate(Connection connection) throws Exception
{
// Based on type of DB, get path to SQL migration script
String dbtype = DatabaseUtils.getDbType(connection);
String dataMigrateSQL;
String sqlMigrationPath = "org/dspace/storage/rdbms/sqlmigration/workflow/" + dbtype +"/";
// Now, check if the XMLWorkflow table (cwf_workflowitem) already exists in this database
// If XMLWorkflow Table does NOT exist in this database, then lets do the migration!
// If XMLWorkflow Table ALREADY exists, then this migration is a noop, we assume you manually ran the sql scripts
if (DatabaseUtils.tableExists(connection, "cwf_workflowitem"))
{
return;
}else{
//Migrate the basic workflow
// Get the contents of our data migration script, based on path & DB type
dataMigrateSQL = new ClassPathResource(sqlMigrationPath + "basicWorkflow" + "/V5.7_2017.05.05__DS-3431.sql",
getClass().getClassLoader()).loadAsString(Constants.DEFAULT_ENCODING);
}
// Actually execute the Data migration SQL
// This will migrate all existing traditional workflows to the new XMLWorkflow system & tables
DatabaseUtils.executeSql(connection, dataMigrateSQL);
migration_file_size = dataMigrateSQL.length();
}
@Override
public Integer getChecksum() {
return migration_file_size;
}
}

View File

@@ -0,0 +1,58 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.storage.rdbms.migration;
import org.dspace.core.Constants;
import org.dspace.storage.rdbms.DatabaseUtils;
import org.flywaydb.core.api.migration.MigrationChecksumProvider;
import org.flywaydb.core.api.migration.jdbc.JdbcMigration;
import org.flywaydb.core.internal.util.scanner.classpath.ClassPathResource;
import java.sql.Connection;
public class V6_1_2017_01_03__DS_3431_Add_Policies_for_BasicWorkflow
implements JdbcMigration, MigrationChecksumProvider
{
// Size of migration script run
Integer migration_file_size = -1;
@Override
public void migrate(Connection connection) throws Exception
{
// Based on type of DB, get path to SQL migration script
String dbtype = DatabaseUtils.getDbType(connection);
String dataMigrateSQL;
String sqlMigrationPath = "org/dspace/storage/rdbms/sqlmigration/workflow/" + dbtype +"/";
// Now, check if the XMLWorkflow table (cwf_workflowitem) already exists in this database
// If XMLWorkflow Table does NOT exist in this database, then lets do the migration!
// If XMLWorkflow Table ALREADY exists, then this migration is a noop, we assume you manually ran the sql scripts
if (DatabaseUtils.tableExists(connection, "cwf_workflowitem"))
{
return;
}else{
//Migrate the basic workflow
// Get the contents of our data migration script, based on path & DB type
dataMigrateSQL = new ClassPathResource(sqlMigrationPath + "basicWorkflow" + "/V6.1_2017.01.03__DS-3431.sql",
getClass().getClassLoader()).loadAsString(Constants.DEFAULT_ENCODING);
}
// Actually execute the Data migration SQL
// This will migrate all existing traditional workflows to the new XMLWorkflow system & tables
DatabaseUtils.executeSql(connection, dataMigrateSQL);
migration_file_size = dataMigrateSQL.length();
}
@Override
public Integer getChecksum() {
return migration_file_size;
}
}

View File

@@ -30,7 +30,6 @@ import java.util.List;
*/ */
public interface WorkflowService<T extends WorkflowItem> { public interface WorkflowService<T extends WorkflowItem> {
public void addInitialWorkspaceItemPolicies(Context context, WorkspaceItem workspaceItem) throws SQLException, AuthorizeException;
/** /**
* startWorkflow() begins a workflow - in a single transaction do away with * startWorkflow() begins a workflow - in a single transaction do away with
@@ -73,8 +72,6 @@ public interface WorkflowService<T extends WorkflowItem> {
*/ */
public T startWithoutNotify(Context c, WorkspaceItem wsi) throws SQLException, AuthorizeException, IOException, WorkflowException; public T startWithoutNotify(Context c, WorkspaceItem wsi) throws SQLException, AuthorizeException, IOException, WorkflowException;
public Item archive(Context context, T workflowItem) throws SQLException, IOException, AuthorizeException;
/** /**
* abort() aborts a workflow, completely deleting it (administrator do this) * abort() aborts a workflow, completely deleting it (administrator do this)
* (it will basically do a reject from any state - the item ends up back in * (it will basically do a reject from any state - the item ends up back in

View File

@@ -13,18 +13,28 @@ import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.*; import org.dspace.content.DCDate;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.CollectionService; import org.dspace.content.service.CollectionService;
import org.dspace.content.service.InstallItemService; import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.content.service.WorkspaceItemService; import org.dspace.content.service.WorkspaceItemService;
import org.dspace.core.*; import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.Email;
import org.dspace.core.I18nUtil;
import org.dspace.core.LogManager;
import org.dspace.curate.service.WorkflowCuratorService; import org.dspace.curate.service.WorkflowCuratorService;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService; import org.dspace.eperson.service.GroupService;
import org.dspace.handle.service.HandleService; import org.dspace.handle.service.HandleService;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.usage.UsageWorkflowEvent; import org.dspace.usage.UsageWorkflowEvent;
import org.dspace.workflowbasic.service.BasicWorkflowItemService; import org.dspace.workflowbasic.service.BasicWorkflowItemService;
@@ -35,7 +45,15 @@ import org.springframework.beans.factory.annotation.Autowired;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.UUID;
public class BasicWorkflowServiceImpl implements BasicWorkflowService public class BasicWorkflowServiceImpl implements BasicWorkflowService
{ {
@@ -60,6 +78,8 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
protected BasicWorkflowItemService workflowItemService; protected BasicWorkflowItemService workflowItemService;
@Autowired(required = true) @Autowired(required = true)
protected WorkspaceItemService workspaceItemService; protected WorkspaceItemService workspaceItemService;
@Autowired(required = true)
protected ConfigurationService configurationService;
protected BasicWorkflowServiceImpl() protected BasicWorkflowServiceImpl()
{ {
@@ -98,99 +118,121 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
return -1; return -1;
} }
@Override /**
public void addInitialWorkspaceItemPolicies(Context context, WorkspaceItem workspaceItem) throws SQLException, AuthorizeException { * This methods grants the appropriate permissions to reviewers so that they
// Now create the policies for the submitter and workflow * can read and edit metadata and read files and edit files if allowed by
// users to modify item and contents * configuration.
// contents = bitstreams, bundles * In most cases this method must be called within a try-finally-block that
// FIXME: icky hardcoded workflow steps * temporary disables the authentication system. This is not done by this
Collection collection = workspaceItem.getCollection(); * method as it should be done carefully and only in contexts in which
Group step1group = collectionService.getWorkflowGroup(collection, 1); * granting the permissions is authorized by some previous checks.
Group step2group = collectionService.getWorkflowGroup(collection, 2); *
Group step3group = collectionService.getWorkflowGroup(collection, 3); * @param context
* @param wfi While all policies are granted on item, bundle or bitstream
Item item = workspaceItem.getItem(); * level, this method takes an workflowitem for convenience and
* uses wfi.getItem() to get the actual item.
if (step1group != null) * @param reviewer EPerson to grant the rights to.
* @throws SQLException
* @throws AuthorizeException
*/
protected void grantReviewerPolicies(Context context, BasicWorkflowItem wfi, EPerson reviewer) throws SQLException, AuthorizeException
{ {
authorizeService.addPolicy(context, item, Constants.READ, step1group, ResourcePolicy.TYPE_WORKFLOW); if(reviewer == null) {
return;
} }
if (step2group != null) // get item and bundle "ORIGINAL"
{ Item item = wfi.getItem();
authorizeService.addPolicy(context, item, Constants.READ, step2group, ResourcePolicy.TYPE_WORKFLOW); Bundle originalBundle;
try {
originalBundle = itemService.getBundles(item, "ORIGINAL").get(0);
} catch (IndexOutOfBoundsException ex) {
originalBundle = null;
} }
if (step3group != null) // grant item level policies
for (int action : new int[] {Constants.READ, Constants.WRITE, Constants.ADD, Constants.REMOVE, Constants.DELETE})
{ {
authorizeService.addPolicy(context, item, Constants.READ, step3group, ResourcePolicy.TYPE_WORKFLOW); authorizeService.addPolicy(context, item, action, reviewer, ResourcePolicy.TYPE_WORKFLOW);
} }
if (step1group != null) // set bitstream and bundle policies
if (originalBundle != null)
{ {
authorizeService.addPolicy(context, item, Constants.WRITE, step1group, ResourcePolicy.TYPE_WORKFLOW); authorizeService.addPolicy(context, originalBundle, Constants.READ, reviewer, ResourcePolicy.TYPE_WORKFLOW);
// shall reviewers be able to edit files?
boolean editFiles = configurationService.getBooleanProperty("workflow.reviewer.file-edit", false);
// if a reviewer should be able to edit bitstreams, we need add
// permissions regarding the bundle "ORIGINAL" and its bitstreams
if (editFiles)
{
authorizeService.addPolicy(context, originalBundle, Constants.ADD, reviewer, ResourcePolicy.TYPE_WORKFLOW);
authorizeService.addPolicy(context, originalBundle, Constants.REMOVE, reviewer, ResourcePolicy.TYPE_WORKFLOW);
// Whenever a new bitstream is added, it inherit the policies of the bundle.
// So we need to add all policies newly created bitstreams should get.
authorizeService.addPolicy(context, originalBundle, Constants.WRITE, reviewer, ResourcePolicy.TYPE_WORKFLOW);
authorizeService.addPolicy(context, originalBundle, Constants.DELETE, reviewer, ResourcePolicy.TYPE_WORKFLOW);
}
for (Bitstream bitstream : originalBundle.getBitstreams())
{
authorizeService.addPolicy(context, bitstream, Constants.READ, reviewer, ResourcePolicy.TYPE_WORKFLOW);
// add further rights if reviewer should be able to edit bitstreams
if (editFiles)
{
authorizeService.addPolicy(context, bitstream, Constants.WRITE, reviewer, ResourcePolicy.TYPE_WORKFLOW);
authorizeService.addPolicy(context, bitstream, Constants.DELETE, reviewer, ResourcePolicy.TYPE_WORKFLOW);
}
}
}
} }
if (step2group != null) /**
* This methods revokes any permission granted by the basic workflow systems
* on the item specified as attribute. At time of writing this method these
* permissions will all be granted by
* {@link #grantReviewerPolicies(org.dspace.core.Context, org.dspace.workflowbasic.BasicWorkflowItem, org.dspace.eperson.EPerson)}.
* In most cases this method must be called within a try-finally-block that
* temporary disables the authentication system. This is not done by this
* method as it should be done carefully and only in contexts in which
* revoking the permissions is authorized by some previous checks.
*
* @param context
* @param item
* @throws SQLException
* @throws AuthorizeException
*/
protected void revokeReviewerPolicies(Context context, Item item) throws SQLException, AuthorizeException
{ {
authorizeService.addPolicy(context, item, Constants.WRITE, step2group, ResourcePolicy.TYPE_WORKFLOW); // get bundle "ORIGINAL"
Bundle originalBundle;
try {
originalBundle = itemService.getBundles(item, "ORIGINAL").get(0);
} catch (IndexOutOfBoundsException ex) {
originalBundle = null;
} }
if (step3group != null) // remove bitstream and bundle level policies
if (originalBundle != null)
{ {
authorizeService.addPolicy(context, item, Constants.WRITE, step3group, ResourcePolicy.TYPE_WORKFLOW); // We added policies for Bitstreams of the bundle "original" only
for (Bitstream bitstream : originalBundle.getBitstreams())
{
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_WORKFLOW);
} }
if (step1group != null) authorizeService.removeAllPoliciesByDSOAndType(context, originalBundle, ResourcePolicy.TYPE_WORKFLOW);
{
authorizeService.addPolicy(context, item, Constants.ADD, step1group, ResourcePolicy.TYPE_WORKFLOW);
} }
if (step2group != null) // remove item level policies
{ authorizeService.removeAllPoliciesByDSOAndType(context, item, ResourcePolicy.TYPE_WORKFLOW);
authorizeService.addPolicy(context, item, Constants.ADD, step2group, ResourcePolicy.TYPE_WORKFLOW);
}
if (step3group != null)
{
authorizeService.addPolicy(context, item, Constants.ADD, step3group, ResourcePolicy.TYPE_WORKFLOW);
}
if (step1group != null)
{
authorizeService.addPolicy(context, item, Constants.REMOVE, step1group, ResourcePolicy.TYPE_WORKFLOW);
}
if (step2group != null)
{
authorizeService.addPolicy(context, item, Constants.REMOVE, step2group, ResourcePolicy.TYPE_WORKFLOW);
}
if (step3group != null)
{
authorizeService.addPolicy(context, item, Constants.REMOVE, step3group, ResourcePolicy.TYPE_WORKFLOW);
}
if (step1group != null)
{
authorizeService.addPolicy(context, item, Constants.DELETE, step1group, ResourcePolicy.TYPE_WORKFLOW);
}
if (step2group != null)
{
authorizeService.addPolicy(context, item, Constants.DELETE, step2group, ResourcePolicy.TYPE_WORKFLOW);
}
if (step3group != null)
{
authorizeService.addPolicy(context, item, Constants.DELETE, step3group, ResourcePolicy.TYPE_WORKFLOW);
}
} }
@Override @Override
public BasicWorkflowItem start(Context context, WorkspaceItem wsi) public BasicWorkflowItem start(Context context, WorkspaceItem wsi)
throws SQLException, AuthorizeException, IOException throws SQLException, AuthorizeException, IOException
{ {
// FIXME Check auth
Item myitem = wsi.getItem(); Item myitem = wsi.getItem();
Collection collection = wsi.getCollection(); Collection collection = wsi.getCollection();
@@ -254,27 +296,27 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
{ {
case WFSTATE_STEP1POOL: case WFSTATE_STEP1POOL:
// authorize DSpaceActions.SUBMIT_REVIEW authorizeService.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_1, true);
doState(context, workflowItem, WFSTATE_STEP1, e); doState(context, workflowItem, WFSTATE_STEP1, e);
break; break;
case WFSTATE_STEP2POOL: case WFSTATE_STEP2POOL:
// authorize DSpaceActions.SUBMIT_STEP2 authorizeService.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_2, true);
doState(context, workflowItem, WFSTATE_STEP2, e); doState(context, workflowItem, WFSTATE_STEP2, e);
break; break;
case WFSTATE_STEP3POOL: case WFSTATE_STEP3POOL:
// authorize DSpaceActions.SUBMIT_STEP3 authorizeService.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_3, true);
doState(context, workflowItem, WFSTATE_STEP3, e); doState(context, workflowItem, WFSTATE_STEP3, e);
break; break;
// if we got here, we weren't pooled... error? default:
// FIXME - log the error? throw new IllegalArgumentException("Workflow Step " + taskstate + " is out of range.");
} }
log.info(LogManager.getHeader(context, "claim_task", "workflow_item_id=" log.info(LogManager.getHeader(context, "claim_task", "workflow_item_id="
@@ -321,8 +363,14 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
break; break;
case WFSTATE_STEP1: case WFSTATE_STEP1:
// advance(...) will call itself if no workflow step group exists
// so we need to check permissions only if a workflow step group is
// in place.
if (workflowItem.getCollection().getWorkflowStep1() != null && e != null)
{
authorizeService.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_1, true);
}
// authorize DSpaceActions.SUBMIT_REVIEW
// Record provenance // Record provenance
if (record) if (record)
{ {
@@ -333,8 +381,14 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
break; break;
case WFSTATE_STEP2: case WFSTATE_STEP2:
// advance(...) will call itself if no workflow step group exists
// so we need to check permissions only if a workflow step group is
// in place.
if (workflowItem.getCollection().getWorkflowStep2() != null && e != null)
{
authorizeService.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_2, true);
}
// authorize DSpaceActions.SUBMIT_STEP2
// Record provenance // Record provenance
if (record) if (record)
{ {
@@ -345,8 +399,14 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
break; break;
case WFSTATE_STEP3: case WFSTATE_STEP3:
// advance(...) will call itself if no workflow step group exists
// so we need to check permissions only if a workflow step group is
// in place.
if (workflowItem.getCollection().getWorkflowStep3() != null && e != null)
{
authorizeService.authorizeAction(context, e, workflowItem.getCollection(), Constants.WORKFLOW_STEP_3, true);
}
// authorize DSpaceActions.SUBMIT_STEP3
// We don't record approval for editors, since they can't reject, // We don't record approval for editors, since they can't reject,
// and thus didn't actually make a decision // and thus didn't actually make a decision
archived = doState(context, workflowItem, WFSTATE_ARCHIVE, e); archived = doState(context, workflowItem, WFSTATE_ARCHIVE, e);
@@ -374,27 +434,23 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
{ {
case WFSTATE_STEP1: case WFSTATE_STEP1:
// authorize DSpaceActions.STEP1
doState(context, workflowItem, WFSTATE_STEP1POOL, e); doState(context, workflowItem, WFSTATE_STEP1POOL, e);
break; break;
case WFSTATE_STEP2: case WFSTATE_STEP2:
// authorize DSpaceActions.APPROVE
doState(context, workflowItem, WFSTATE_STEP2POOL, e); doState(context, workflowItem, WFSTATE_STEP2POOL, e);
break; break;
case WFSTATE_STEP3: case WFSTATE_STEP3:
// authorize DSpaceActions.STEP3
doState(context, workflowItem, WFSTATE_STEP3POOL, e); doState(context, workflowItem, WFSTATE_STEP3POOL, e);
break; break;
default:
// error handling? shouldn't get here throw new IllegalStateException("WorkflowItem reach an unknown state.");
// FIXME - what to do with error - log it?
} }
log.info(LogManager.getHeader(context, "unclaim_workflow", log.info(LogManager.getHeader(context, "unclaim_workflow",
@@ -427,14 +483,11 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
return returnToWorkspace(context, workflowItem); return returnToWorkspace(context, workflowItem);
} }
// returns true if archived
protected boolean doState(Context context, BasicWorkflowItem workflowItem, int newstate, protected boolean doState(Context context, BasicWorkflowItem workflowItem, int newstate,
EPerson newowner) throws SQLException, IOException, EPerson newowner) throws SQLException, IOException,
AuthorizeException AuthorizeException
{ {
Collection mycollection = workflowItem.getCollection(); Collection collection = workflowItem.getCollection();
Group mygroup = null;
boolean archived = false;
//Gather our old data for launching the workflow event //Gather our old data for launching the workflow event
int oldState = workflowItem.getState(); int oldState = workflowItem.getState();
@@ -444,169 +497,252 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
// before. => keep this information before setting the new owner. // before. => keep this information before setting the new owner.
EPerson oldOwner = workflowItem.getOwner(); EPerson oldOwner = workflowItem.getOwner();
workflowItem.setState(newstate);
switch (newstate) switch (newstate)
{ {
case WFSTATE_STEP1POOL: case WFSTATE_STEP1POOL:
return pool(context, workflowItem, 1);
// any reviewers?
// if so, add them to the tasklist
workflowItem.setOwner(null);
// get reviewers (group 1 )
mygroup = collectionService.getWorkflowGroup(mycollection, 1);
if ((mygroup != null) && !(groupService.isEmpty(mygroup)))
{
// get a list of all epeople in group (or any subgroups)
List<EPerson> epa = groupService.allMembers(context, mygroup);
// there were reviewers, change the state
// and add them to the list
createTasks(context, workflowItem, epa);
workflowItemService.update(context, workflowItem);
if (ConfigurationManager.getBooleanProperty("workflow", "notify.returned.tasks", true)
|| oldState != WFSTATE_STEP1
|| oldOwner == null)
{
// email notification
notifyGroupOfTask(context, workflowItem, mygroup, epa);
}
}
else
{
// no reviewers, skip ahead
workflowItem.setState(WFSTATE_STEP1);
archived = advance(context, workflowItem, null, true, false);
}
break;
case WFSTATE_STEP1: case WFSTATE_STEP1:
assignToReviewer(context, workflowItem, 1, newowner);
// remove reviewers from tasklist return false;
// assign owner
taskListItemService.deleteByWorkflowItem(context, workflowItem);
workflowItem.setOwner(newowner);
break;
case WFSTATE_STEP2POOL: case WFSTATE_STEP2POOL:
return pool(context, workflowItem, 2);
// clear owner
// any approvers?
// if so, add them to tasklist
// if not, skip to next state
workflowItem.setOwner(null);
// get approvers (group 2)
mygroup = collectionService.getWorkflowGroup(mycollection, 2);
if ((mygroup != null) && !(groupService.isEmpty(mygroup)))
{
//get a list of all epeople in group (or any subgroups)
List<EPerson> epa = groupService.allMembers(context, mygroup);
// there were approvers, change the state
// timestamp, and add them to the list
createTasks(context, workflowItem, epa);
if (ConfigurationManager.getBooleanProperty("workflow", "notify.returned.tasks", true)
|| oldState != WFSTATE_STEP2
|| oldOwner == null)
{
// email notification
notifyGroupOfTask(context, workflowItem, mygroup, epa);
}
}
else
{
// no reviewers, skip ahead
workflowItem.setState(WFSTATE_STEP2);
archived = advance(context, workflowItem, null, true, false);
}
break;
case WFSTATE_STEP2: case WFSTATE_STEP2:
assignToReviewer(context, workflowItem, 2, newowner);
// remove admins from tasklist return false;
// assign owner
taskListItemService.deleteByWorkflowItem(context, workflowItem);
workflowItem.setOwner(newowner);
break;
case WFSTATE_STEP3POOL: case WFSTATE_STEP3POOL:
return pool(context, workflowItem, 3);
// any editors?
// if so, add them to tasklist
workflowItem.setOwner(null);
mygroup = collectionService.getWorkflowGroup(mycollection, 3);
if ((mygroup != null) && !(groupService.isEmpty(mygroup)))
{
// get a list of all epeople in group (or any subgroups)
List<EPerson> epa = groupService.allMembers(context, mygroup);
// there were editors, change the state
// timestamp, and add them to the list
createTasks(context, workflowItem, epa);
if (ConfigurationManager.getBooleanProperty("workflow", "notify.returned.tasks", true)
|| oldState != WFSTATE_STEP3
|| oldOwner == null)
{
// email notification
notifyGroupOfTask(context, workflowItem, mygroup, epa);
}
}
else
{
// no editors, skip ahead
workflowItem.setState(WFSTATE_STEP3);
archived = advance(context, workflowItem, null, true, false);
}
break;
case WFSTATE_STEP3: case WFSTATE_STEP3:
assignToReviewer(context, workflowItem, 3, newowner);
// remove editors from tasklist return false;
// assign owner
taskListItemService.deleteByWorkflowItem(context, workflowItem);
workflowItem.setOwner(newowner);
break;
case WFSTATE_ARCHIVE: case WFSTATE_ARCHIVE:
// put in archive in one transaction // put in archive in one transaction
// remove workflow tasks // remove workflow tasks
taskListItemService.deleteByWorkflowItem(context, workflowItem); taskListItemService.deleteByWorkflowItem(context, workflowItem);
mycollection = workflowItem.getCollection(); collection = workflowItem.getCollection();
Item myitem = archive(context, workflowItem); Item myitem = archive(context, workflowItem);
// now email notification // now email notification
notifyOfArchive(context, myitem, mycollection); notifyOfArchive(context, myitem, collection);
archived = true;
break; // remove any workflow policies left
} try
logWorkflowEvent(context, workflowItem.getItem(), workflowItem, context.getCurrentUser(), newstate, newowner, mycollection, oldState, mygroup);
if (!archived)
{ {
workflowItemService.update(context, workflowItem); context.turnOffAuthorisationSystem();
revokeReviewerPolicies(context, myitem);
} finally {
context.restoreAuthSystemState();
} }
logWorkflowEvent(context, workflowItem.getItem(), workflowItem, context.getCurrentUser(), newstate, newowner, collection, oldState, null);
return true;
default:
throw new IllegalArgumentException("BasicWorkflowService cannot handle workflowItemState " + newstate);
}
}
/**
* Helper method to take an item out of the pool, to assign it to a reviewer and to deal with reviewer policies.
* Don't use this method directly. Instead: use {@link #start(Context, WorkspaceItem)} to start a workflow and
* {@link #claim(Context, BasicWorkflowItem, EPerson)} as those methods handles the internal states and checks for
* the appropriate permissions.
* @param context DSpace context object
* @param workflowItem The item that shall be pooled.
* @param step The step (1-3) of the pool the item should be put to.
* @param newowner The EPerson that should do the review.
* @return True if the item was archived because no reviewers were assigned to any of the following workflow steps, false otherwise.
* @throws SQLException
* @throws AuthorizeException
* @throws IOException
* @throws IllegalArgumentException If {@code param} has another value than either 1, 2, or 3.
*/
protected void assignToReviewer(Context context, BasicWorkflowItem workflowItem, int step, EPerson newowner)
throws AuthorizeException, SQLException
{
// shortcut to the collection
Collection collection = workflowItem.getCollection();
// from the step we can recoginze the new state and the corresponding policy action.
int newState;
int correspondingAction;
if (step == 1) {
newState = WFSTATE_STEP1;
correspondingAction = Constants.WORKFLOW_STEP_1;
} else if (step == 2) {
newState = WFSTATE_STEP2;
correspondingAction = Constants.WORKFLOW_STEP_2;
} else if (step == 3) {
newState = WFSTATE_STEP3;
correspondingAction = Constants.WORKFLOW_STEP_3;
} else {
throw new IllegalArgumentException("Got a task to pool with an improperly or unknown state.");
}
// Gather the old state for logging
int oldState = workflowItem.getState();
// if there is a workflow state group and it contains any members,
// then we have to check permissions first
if ((collectionService.getWorkflowGroup(collection, step) != null)
&& !(groupService.isEmpty(collectionService.getWorkflowGroup(collection, step)))
&& newowner != null)
{
authorizeService.authorizeAction(context, newowner, collection, correspondingAction, true);
}
// give the owner the appropriate permissions
try {
context.turnOffAuthorisationSystem();
// maybe unnecessary, but revoke any previously granted permissions
revokeReviewerPolicies(context, workflowItem.getItem());
// finally grant the new permissions
grantReviewerPolicies(context, workflowItem, newowner);
} finally {
context.restoreAuthSystemState();
}
// remove task from tasklist as someone is working on it now
taskListItemService.deleteByWorkflowItem(context, workflowItem);
// assign new owner
workflowItem.setState(newState);
workflowItem.setOwner(newowner);
logWorkflowEvent(context, workflowItem.getItem(), workflowItem, context.getCurrentUser(), newState, newowner, collection, oldState, null);
}
/**
* Helper method that manages state, policies, owner, notifies, tasklistitems and so on whenever an WorkflowItem
* should be added to a workflow step pool. Don't use this method directly. Either use
* {@link #unclaim(Context, BasicWorkflowItem, EPerson)} if the item is claimed,
* {@link #start(Context, WorkspaceItem)} to start the workflow or {@link #advance(Context, BasicWorkflowItem, EPerson)}
* to move an item to the next state.
* @param context DSpace context object
* @param workflowItem The item that shall be pooled.
* @param step The step (1-3) of the pool the item should be put to.
* @return True if the item was archived because no reviewers were assigned to any of the following workflow steps, false otherwise.
* @throws SQLException
* @throws AuthorizeException
* @throws IOException
* @throws IllegalArgumentException If {@code param} has another value than either 1, 2, or 3.
*/
protected boolean pool(Context context, BasicWorkflowItem workflowItem, int step)
throws SQLException, AuthorizeException, IOException
{
// shortcut to the collection
Collection collection = workflowItem.getCollection();
// from the step we can recoginze the new state and the corresponding state.
// the new state is the pool of the step
// the corresponding state is the state an item gets when it gets claimed. That is important to recognize if we
// have to send notifications and if we have to skip a pool.
int newState;
int correspondingState;
if (step == 1) {
newState = WFSTATE_STEP1POOL;
correspondingState = WFSTATE_STEP1;
} else if (step == 2) {
newState = WFSTATE_STEP2POOL;
correspondingState = WFSTATE_STEP2;
} else if (step == 3) {
newState = WFSTATE_STEP3POOL;
correspondingState = WFSTATE_STEP3;
} else {
throw new IllegalArgumentException("Got a task to pool with an improperly or unknown state.");
}
// Gather our old owner and state as we need those as well to determine if we have to send notifies
int oldState = workflowItem.getState();
EPerson oldOwner = workflowItem.getOwner();
// clear owner
workflowItem.setOwner(null);
// don't revoke the reviewer policies yet, they may be needed to advance the item
// any approvers?
// if so, add them to tasklist
// if not, skip to next state
Group workflowStepGroup = collectionService.getWorkflowGroup(collection, step);
if ((workflowStepGroup != null) && !(groupService.isEmpty(workflowStepGroup)))
{
// set new item state
workflowItem.setState(newState);
// revoke previously granted reviewer policies and grant read permissions
try
{
context.turnOffAuthorisationSystem();
// revoke previously granted policies
revokeReviewerPolicies(context, workflowItem.getItem());
// JSPUI offers a preview to every task before a reviewer claims it.
// So we need to grant permissions in advance, so that all possible reviewers can read the item and all
// bitstreams in the bundle "ORIGINAL".
authorizeService.addPolicy(context, workflowItem.getItem(), Constants.READ, workflowStepGroup, ResourcePolicy.TYPE_WORKFLOW);
Bundle originalBundle;
try {
originalBundle = itemService.getBundles(workflowItem.getItem(), "ORIGINAL").get(0);
} catch (IndexOutOfBoundsException ex) {
originalBundle = null;
}
if (originalBundle != null)
{
authorizeService.addPolicy(context, originalBundle, Constants.READ, workflowStepGroup, ResourcePolicy.TYPE_WORKFLOW);
for (Bitstream bitstream : originalBundle.getBitstreams())
{
authorizeService.addPolicy(context, bitstream, Constants.READ, workflowStepGroup, ResourcePolicy.TYPE_WORKFLOW);
}
}
} finally {
context.restoreAuthSystemState();
}
// get a list of all epeople in group (or any subgroups)
List<EPerson> epa = groupService.allMembers(context, workflowStepGroup);
// there were reviewers, change the state
// and add them to the list
createTasks(context, workflowItem, epa);
if (configurationService.getBooleanProperty("workflow.notify.returned.tasks", true)
|| oldState != correspondingState
|| oldOwner == null)
{
// email notification
notifyGroupOfTask(context, workflowItem, workflowStepGroup, epa);
}
logWorkflowEvent(context, workflowItem.getItem(), workflowItem, context.getCurrentUser(), newState, null, collection, oldState, workflowStepGroup);
return false;
}
else
{
// no reviewers, skip ahead
workflowItem.setState(correspondingState);
boolean archived = advance(context, workflowItem, null, true, false);
if (archived)
{
// remove any workflow policies that may have left over
try {
context.turnOffAuthorisationSystem();
revokeReviewerPolicies(context, workflowItem.getItem());
} finally {
context.restoreAuthSystemState();
}
}
return archived; return archived;
} }
}
protected void logWorkflowEvent(Context context, Item item, BasicWorkflowItem workflowItem, EPerson actor, int newstate, EPerson newOwner, Collection mycollection, int oldState, Group newOwnerGroup) { protected void logWorkflowEvent(Context context, Item item, BasicWorkflowItem workflowItem, EPerson actor, int newstate, EPerson newOwner, Collection mycollection, int oldState, Group newOwnerGroup) {
if(newstate == WFSTATE_ARCHIVE || newstate == WFSTATE_STEP1POOL || newstate == WFSTATE_STEP2POOL || newstate == WFSTATE_STEP3POOL){ if(newstate == WFSTATE_ARCHIVE || newstate == WFSTATE_STEP1POOL || newstate == WFSTATE_STEP2POOL || newstate == WFSTATE_STEP3POOL){
@@ -652,11 +788,9 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
* Exception indicating the current user of the context does not have permission * Exception indicating the current user of the context does not have permission
* to perform a particular action. * to perform a particular action.
*/ */
@Override protected Item archive(Context context, BasicWorkflowItem workflowItem)
public Item archive(Context context, BasicWorkflowItem workflowItem)
throws SQLException, IOException, AuthorizeException throws SQLException, IOException, AuthorizeException
{ {
// FIXME: Check auth
Item item = workflowItem.getItem(); Item item = workflowItem.getItem();
Collection collection = workflowItem.getCollection(); Collection collection = workflowItem.getCollection();
@@ -750,6 +884,8 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
protected WorkspaceItem returnToWorkspace(Context c, BasicWorkflowItem wfi) protected WorkspaceItem returnToWorkspace(Context c, BasicWorkflowItem wfi)
throws SQLException, IOException, AuthorizeException throws SQLException, IOException, AuthorizeException
{ {
// Regarding auth: this method is protected.
// Authorization should be checked in all public methods calling this one.
// FIXME: How should this interact with the workflow system? // FIXME: How should this interact with the workflow system?
// FIXME: Remove license // FIXME: Remove license
// FIXME: Provenance statement? // FIXME: Provenance statement?
@@ -779,9 +915,24 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
String provenancePrefix, String rejection_message) throws SQLException, AuthorizeException, String provenancePrefix, String rejection_message) throws SQLException, AuthorizeException,
IOException IOException
{ {
int oldState = workflowItem.getState(); int oldState = workflowItem.getState();
// authorize a DSpaceActions.REJECT
switch(oldState)
{
case WFSTATE_STEP1:
authorizeService.authorizeActionBoolean(context, ePerson, workflowItem.getItem(), Constants.WORKFLOW_STEP_1, true);
break;
case WFSTATE_STEP2:
authorizeService.authorizeActionBoolean(context, ePerson, workflowItem.getItem(), Constants.WORKFLOW_STEP_2, true);
break;
case WFSTATE_STEP3:
authorizeService.authorizeActionBoolean(context, ePerson, workflowItem.getItem(), Constants.WORKFLOW_STEP_3, true);
break;
default:
throw new IllegalArgumentException("Workflow Step " + oldState + " is out of range.");
}
// stop workflow // stop workflow
taskListItemService.deleteByWorkflowItem(context, workflowItem); taskListItemService.deleteByWorkflowItem(context, workflowItem);
@@ -945,7 +1096,7 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
@Override @Override
public String getMyDSpaceLink() public String getMyDSpaceLink()
{ {
return ConfigurationManager.getProperty("dspace.url") + "/mydspace"; return configurationService.getProperty("dspace.url") + "/mydspace";
} }
protected void notifyOfReject(Context context, BasicWorkflowItem workflowItem, EPerson e, protected void notifyOfReject(Context context, BasicWorkflowItem workflowItem, EPerson e,
@@ -1022,6 +1173,10 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
protected String getEPersonName(EPerson e) throws SQLException protected String getEPersonName(EPerson e) throws SQLException
{ {
if (e == null)
{
return "Unknown";
}
String submitter = e.getFullName(); String submitter = e.getFullName();
submitter = submitter + " (" + e.getEmail() + ")"; submitter = submitter + " (" + e.getEmail() + ")";
@@ -1086,9 +1241,10 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
@Override @Override
public void deleteCollection(Context context, Collection collection) throws SQLException, IOException, AuthorizeException { public void deleteCollection(Context context, Collection collection) throws SQLException, IOException, AuthorizeException {
collection.setWorkflowGroup(1, null); authorizeService.authorizeAction(context, collection, Constants.WRITE);
collection.setWorkflowGroup(2, null); collection.setWorkflowGroup(context, 1, null);
collection.setWorkflowGroup(3, null); collection.setWorkflowGroup(context, 2, null);
collection.setWorkflowGroup(context, 3, null);
workflowItemService.deleteByCollection(context, collection); workflowItemService.deleteByCollection(context, collection);
} }
@@ -1136,5 +1292,5 @@ public class BasicWorkflowServiceImpl implements BasicWorkflowService
@Override @Override
public List<String> getFlywayMigrationLocations() { public List<String> getFlywayMigrationLocations() {
return Collections.emptyList(); return Collections.emptyList();
} } // TODO
} }

View File

@@ -92,11 +92,6 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
} }
@Override
public void addInitialWorkspaceItemPolicies(Context context, WorkspaceItem workspaceItem) throws SQLException, AuthorizeException {
//Not used, rights are added dynamically.
}
@Override @Override
public void deleteCollection(Context context, Collection collection) throws SQLException, IOException, AuthorizeException { public void deleteCollection(Context context, Collection collection) throws SQLException, IOException, AuthorizeException {
xmlWorkflowItemService.deleteByCollection(context, collection); xmlWorkflowItemService.deleteByCollection(context, collection);
@@ -474,8 +469,7 @@ public class XmlWorkflowServiceImpl implements XmlWorkflowService {
* Exception indicating the current user of the context does not have permission * Exception indicating the current user of the context does not have permission
* to perform a particular action. * to perform a particular action.
*/ */
@Override protected Item archive(Context context, XmlWorkflowItem wfi)
public Item archive(Context context, XmlWorkflowItem wfi)
throws SQLException, IOException, AuthorizeException { throws SQLException, IOException, AuthorizeException {
// FIXME: Check auth // FIXME: Check auth
Item item = wfi.getItem(); Item item = wfi.getItem();

View File

@@ -0,0 +1,15 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-------------------------------------------------------------------------
-- DS-3431 Workflow system is vulnerable to unauthorized manipulations --
-------------------------------------------------------------------------
-- H2 is used only for testing. In test, the database is always
-- empty to start with, so there is nothing to migrate here.

View File

@@ -0,0 +1,15 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-------------------------------------------------------------------------
-- DS-3431 Workflow system is vulnerable to unauthorized manipulations --
-------------------------------------------------------------------------
-- H2 is used only for testing. In test, the database is always
-- empty to start with, so there is nothing to migrate here.

View File

@@ -0,0 +1,503 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-------------------------------------------------------------------------
-- DS-3431 Workflow system is vulnerable to unauthorized manipulations --
-------------------------------------------------------------------------
-----------------------------------------------------------------------
-- grant claiming permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'5' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
collection_id AS dspace_object
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 5 AND epersongroup_id = workflow_step_1 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'6' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
collection_id AS dspace_object
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 6 AND epersongroup_id = workflow_step_2 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'7' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
collection_id AS dspace_object
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 7 AND epersongroup_id = workflow_step_3 and resource_id = collection_id
);
-----------------------------------------------------------------------
-- grant add permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
collection_id AS dspace_object
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_1 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
collection_id AS dspace_object
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_2 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
collection_id AS dspace_object
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_3 and resource_id = collection_id
);
----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on workflow items to reviewers --
----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 0 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 1 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 2 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 3 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 4 AND eperson_id = owner AND resource_id = item_id
);
-----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on Bundle ORIGINAL to reviewers --
-----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
-------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on all Bitstreams of Bundle --
-- ORIGINAL to reviewers --
-------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL policy_id,
'0' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);

View File

@@ -0,0 +1,503 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-------------------------------------------------------------------------
-- DS-3431 Workflow system is vulnerable to unauthorized manipulations --
-------------------------------------------------------------------------
-----------------------------------------------------------------------
-- grant claiming permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'5' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 5 AND epersongroup_id = workflow_step_1 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'6' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 6 AND epersongroup_id = workflow_step_2 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'7' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 7 AND epersongroup_id = workflow_step_3 and dspace_object = uuid
);
-----------------------------------------------------------------------
-- grant add permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_1 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_2 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_3 and dspace_object = uuid
);
----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on workflow items to reviewers --
----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 0 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 1 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 2 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 3 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'2' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 4 AND eperson_id = owner AND dspace_object = item_id
);
-----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on Bundle ORIGINAL to reviewers --
-----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'1' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
-------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on all Bitstreams of Bundle --
-- ORIGINAL to reviewers --
-------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL policy_id,
'0' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
resourcepolicy_seq.NEXTVAL AS policy_id,
'0' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem wfi
JOIN item2bundle i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value LIKE 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);

View File

@@ -0,0 +1,503 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-------------------------------------------------------------------------
-- DS-3431 Workflow system is vulnerable to unauthorized manipulations --
-------------------------------------------------------------------------
-----------------------------------------------------------------------
-- grant claiming permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'5' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
collection_id
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 5 AND epersongroup_id = workflow_step_1 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'6' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
collection_id
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 6 AND epersongroup_id = workflow_step_2 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'7' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
collection_id
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 7 AND epersongroup_id = workflow_step_3 and resource_id = collection_id
);
-----------------------------------------------------------------------
-- grant add permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
collection_id
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_1 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
collection_id
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_2 and resource_id = collection_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
collection_id
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_3 and resource_id = collection_id
);
----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on workflow items to reviewers --
----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 0 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 1 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 2 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 3 AND eperson_id = owner AND resource_id = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 4 AND eperson_id = owner AND resource_id = item_id
);
-----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on Bundle ORIGINAL to reviewers --
-----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = i2b.bundle_id
);
-------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on all Bitstreams of Bundle --
-- ORIGINAL to reviewers --
-------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, resource_id)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.resource_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.resource_id = b2b.bitstream_id
);

View File

@@ -0,0 +1,503 @@
--
-- The contents of this file are subject to the license and copyright
-- detailed in the LICENSE and NOTICE files at the root of the source
-- tree and available online at
--
-- http://www.dspace.org/license/
--
-------------------------------------------------------------------------
-- DS-3431 Workflow system is vulnerable to unauthorized manipulations --
-------------------------------------------------------------------------
-----------------------------------------------------------------------
-- grant claiming permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'5' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 5 AND epersongroup_id = workflow_step_1 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'6' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 6 AND epersongroup_id = workflow_step_2 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'7' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 7 AND epersongroup_id = workflow_step_3 and dspace_object = uuid
);
-----------------------------------------------------------------------
-- grant add permissions to all workflow step groups (step 1-3) --
-----------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_1 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_1 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_1 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_2 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_2 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_2 and dspace_object = uuid
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, epersongroup_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'3' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
workflow_step_3 AS epersongroup_id,
uuid AS dspace_object
FROM collection
WHERE workflow_step_3 IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 3 AND action_id = 3 AND epersongroup_id = workflow_step_3 and dspace_object = uuid
);
----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on workflow items to reviewers --
----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 0 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 1 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 2 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 3 AND eperson_id = owner AND dspace_object = item_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'2' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
owner AS eperson_id,
item_id AS dspace_object
FROM workflowitem
WHERE
owner IS NOT NULL
AND (state = 2 OR state = 4 OR state = 6)
AND NOT EXISTS (
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 2 AND action_id = 4 AND eperson_id = owner AND dspace_object = item_id
);
-----------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on Bundle ORIGINAL to reviewers --
-----------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'1' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
i2b.bundle_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 1 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = i2b.bundle_id
);
-------------------------------------------------------------------------------
-- grant read/write/delete/add/remove permission on all Bitstreams of Bundle --
-- ORIGINAL to reviewers --
-------------------------------------------------------------------------------
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'0' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 0 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'1' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 1 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'2' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 2 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'3' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 3 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);
INSERT INTO resourcepolicy
(policy_id, resource_type_id, action_id, rptype, eperson_id, dspace_object)
SELECT
nextval('resourcepolicy_seq') AS policy_id,
'0' AS resource_type_id,
'4' AS action_id,
'TYPE_WORKFLOW' AS rptype,
wfi.owner AS eperson_id,
b2b.bitstream_id AS dspace_object
FROM workflowitem AS wfi
JOIN item2bundle AS i2b
ON i2b.item_id = wfi.item_id
JOIN bundle2bitstream AS b2b
ON b2b.bundle_id = i2b.bundle_id
JOIN metadatavalue AS mv
ON mv.dspace_object_id = i2b.bundle_id
JOIN metadatafieldregistry as mfr
ON mv.metadata_field_id = mfr.metadata_field_id
JOIN metadataschemaregistry as msr
ON mfr.metadata_schema_id = msr.metadata_schema_id
WHERE
msr.namespace = 'http://dublincore.org/documents/dcmi-terms/'
AND mfr.element = 'title'
AND mfr.qualifier IS NULL
AND mv.text_value = 'ORIGINAL'
AND wfi.owner IS NOT NULL
AND (wfi.state = 2 OR wfi.state = 4 OR wfi.state = 6)
AND NOT EXISTS(
SELECT 1 FROM resourcepolicy WHERE resource_type_id = 0 AND action_id = 4 AND resourcepolicy.eperson_id = owner AND resourcepolicy.dspace_object = b2b.bitstream_id
);

View File

@@ -518,11 +518,31 @@ public class CollectionTest extends AbstractDSpaceObjectTest
int step = 1; int step = 1;
Group g = groupService.create(context); Group g = groupService.create(context);
context.restoreAuthSystemState(); context.restoreAuthSystemState();
collection.setWorkflowGroup(step, g); collection.setWorkflowGroup(context, step, g);
assertThat("testSetWorkflowGroup 0",collectionService.getWorkflowGroup(collection, step), notNullValue()); assertThat("testSetWorkflowGroup 0",collectionService.getWorkflowGroup(collection, step), notNullValue());
assertThat("testSetWorkflowGroup 1",collectionService.getWorkflowGroup(collection, step), equalTo(g)); assertThat("testSetWorkflowGroup 1",collectionService.getWorkflowGroup(collection, step), equalTo(g));
} }
/**
* Test of setWorkflowGroup method, of class Collection.
* The setWorkflowGroup ajust the policies for the basic Workflow. This test
* shall assure that now exception (e.g. ConcurrentModificationException is
* thrown during these adjustments.
*/
@Test
public void testChangeWorkflowGroup() throws SQLException, AuthorizeException
{
context.turnOffAuthorisationSystem(); //must be an Admin to create a Group
int step = 1;
Group g1 = groupService.create(context);
Group g2 = groupService.create(context);
context.restoreAuthSystemState();
collection.setWorkflowGroup(context, step, g1);
collection.setWorkflowGroup(context, step, g2);
assertThat("testSetWorkflowGroup 0",collectionService.getWorkflowGroup(collection, step), notNullValue());
assertThat("testSetWorkflowGroup 1",collectionService.getWorkflowGroup(collection, step), equalTo(g2));
}
/** /**
* Test of getWorkflowGroup method, of class Collection. * Test of getWorkflowGroup method, of class Collection.
*/ */

View File

@@ -159,7 +159,7 @@ public class PackageUtilsTest extends AbstractUnitTest
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
Group testGroup = groupService.create(context); Group testGroup = groupService.create(context);
groupService.setName(testGroup, "TESTGROUP"); groupService.setName(testGroup, "TESTGROUP");
testCollection.setWorkflowGroup(1, testGroup); testCollection.setWorkflowGroup(context, 1, testGroup);
String exportName = PackageUtils.translateGroupNameForExport(context, String exportName = PackageUtils.translateGroupNameForExport(context,
testGroup.getName()); testGroup.getName());
@@ -168,7 +168,7 @@ public class PackageUtilsTest extends AbstractUnitTest
String importName = PackageUtils.translateGroupNameForImport(context, exportName); String importName = PackageUtils.translateGroupNameForImport(context, exportName);
assertEquals("Exported Group name without underscore unchanged by translation for import", exportName, importName); assertEquals("Exported Group name without underscore unchanged by translation for import", exportName, importName);
testCollection.setWorkflowGroup(1, originalFirstStepWorkflowGroup); testCollection.setWorkflowGroup(context, 1, originalFirstStepWorkflowGroup);
} }
@Test @Test
@@ -180,7 +180,7 @@ public class PackageUtilsTest extends AbstractUnitTest
GroupService groupService = EPersonServiceFactory.getInstance().getGroupService(); GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
Group testGroup = groupService.create(context); Group testGroup = groupService.create(context);
groupService.setName(testGroup, "TESTGROUP_ABC_TEST"); groupService.setName(testGroup, "TESTGROUP_ABC_TEST");
testCollection.setWorkflowGroup(1, testGroup); testCollection.setWorkflowGroup(context, 1, testGroup);
String exportName = PackageUtils.translateGroupNameForExport(context, String exportName = PackageUtils.translateGroupNameForExport(context,
testGroup.getName()); testGroup.getName());
@@ -189,7 +189,7 @@ public class PackageUtilsTest extends AbstractUnitTest
String importName = PackageUtils.translateGroupNameForImport(context, exportName); String importName = PackageUtils.translateGroupNameForImport(context, exportName);
assertEquals("Exported Group name with underscores but no DSO unchanged by translation for import", exportName, importName); assertEquals("Exported Group name with underscores but no DSO unchanged by translation for import", exportName, importName);
testCollection.setWorkflowGroup(1, originalFirstStepWorkflowGroup); testCollection.setWorkflowGroup(context, 1, originalFirstStepWorkflowGroup);
} }
@Test @Test
@@ -208,7 +208,7 @@ public class PackageUtilsTest extends AbstractUnitTest
String importName = PackageUtils.translateGroupNameForImport(context, exportName); String importName = PackageUtils.translateGroupNameForImport(context, exportName);
assertEquals("Exported Group name with dso unchanged by roundtrip translation for export/import", group.getName(), importName); assertEquals("Exported Group name with dso unchanged by roundtrip translation for export/import", group.getName(), importName);
testCollection.setWorkflowGroup(1, originalFirstStepWorkflowGroup); testCollection.setWorkflowGroup(context, 1, originalFirstStepWorkflowGroup);
} }
@After @After

View File

@@ -9,6 +9,8 @@
package org.dspace.identifier; package org.dspace.identifier;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
@@ -97,10 +99,9 @@ public class EZIDIdentifierProviderTest
* @throws AuthorizeException if authorization error * @throws AuthorizeException if authorization error
* @throws IOException if IO error * @throws IOException if IO error
*/ */
private Item newItem(Context ctx) private Item newItem()
throws SQLException, AuthorizeException, IOException, WorkflowException { throws SQLException, AuthorizeException, IOException, WorkflowException
ctx.turnOffAuthorisationSystem(); {
//Install a fresh item //Install a fresh item
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
@@ -117,7 +118,7 @@ public class EZIDIdentifierProviderTest
itemService.update(context, item); itemService.update(context, item);
// Commit work, clean up // Commit work, clean up
ctx.restoreAuthSystemState(); context.restoreAuthSystemState();
return item; return item;
} }
@@ -409,6 +410,7 @@ public class EZIDIdentifierProviderTest
public void testCrosswalkMetadata() public void testCrosswalkMetadata()
throws Exception throws Exception
{ {
try {
System.out.println("crosswalkMetadata"); System.out.println("crosswalkMetadata");
// Set up the instance to be tested // Set up the instance to be tested
@@ -418,7 +420,7 @@ public class EZIDIdentifierProviderTest
// instance.setCrosswalkTransform(crosswalkTransforms); // instance.setCrosswalkTransform(crosswalkTransforms);
// Let's have a fresh Item to work with // Let's have a fresh Item to work with
DSpaceObject dso = newItem(context); DSpaceObject dso = newItem();
String handle = dso.getHandle(); String handle = dso.getHandle();
// Test! // Test!
@@ -440,5 +442,13 @@ public class EZIDIdentifierProviderTest
{ {
System.out.printf(" %s : %s\n", metadatum.getKey(), metadatum.getValue()); System.out.printf(" %s : %s\n", metadatum.getKey(), metadatum.getValue());
} }
} catch (NullPointerException ex) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
System.out.println(sw.toString());
org.apache.log4j.Logger.getLogger(EZIDIdentifierProviderTest.class).fatal("Caught NPE", ex);
throw ex;
}
} }
} }

View File

@@ -0,0 +1,391 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.workflowbasic;
import org.apache.log4j.Logger;
import org.dspace.AbstractDSpaceTest;
import org.dspace.AbstractIntegrationTest;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.Item;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.InstallItemService;
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.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.workflow.WorkflowException;
import org.dspace.workflowbasic.factory.BasicWorkflowServiceFactory;
import org.dspace.workflowbasic.service.BasicWorkflowItemService;
import org.dspace.workflowbasic.service.BasicWorkflowService;
import org.hamcrest.CoreMatchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
/**
* This is an integration test to ensure that the basic workflow system
* -including methods of the collection service dealing with it- works properly
* together with the authorization service.
* @author Pascal-Nicolas Becker
* @author Terry Brady
*/
public class BasicWorkflowAuthorizationIT
extends AbstractIntegrationTest
{
/** log4j category */
private static final Logger log = Logger.getLogger(BasicWorkflowAuthorizationIT.class);
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
protected BasicWorkflowItemService basicWorkflowItemService = BasicWorkflowServiceFactory.getInstance().getBasicWorkflowItemService();
protected BasicWorkflowService basicWorkflowService = BasicWorkflowServiceFactory.getInstance().getBasicWorkflowService();
protected EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
protected GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
protected BundleService bundleService = ContentServiceFactory.getInstance().getBundleService();
protected BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
protected ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
protected Community owningCommunity;
protected Collection collection;
protected Group group;
protected EPerson member;
public BasicWorkflowAuthorizationIT()
{
owningCommunity = null;
collection = null;
group = null;
member = null;
}
/**
* This method will be run before every test as per @Before. It will
* initialize resources required for the tests.
*
* Other methods can be annotated with @Before here or in subclasses
* but no execution order is guaranteed
*/
@Before
@Override
public void init()
{
super.init();
try
{
//we have to create a new community in the database
configurationService.setProperty("workflow.notify.returned.tasks", false);
context.turnOffAuthorisationSystem();
this.owningCommunity = communityService.create(null, context);
this.collection = collectionService.create(context, owningCommunity);
this.member = ePersonService.create(context);
this.group = groupService.create(context);
groupService.addMember(context, group, member);
groupService.update(context, group);
}
catch (AuthorizeException ex)
{
log.error("Authorization Error in init", ex);
Assert.fail("Authorization Error in init: " + ex.getMessage());
}
catch (SQLException ex)
{
log.error("SQL Error in init", ex);
Assert.fail("SQL Error in init: " + ex.getMessage());
}
finally
{
// restore the authorization system as tests expect it to be in place
context.restoreAuthSystemState();
}
}
/**
* This method will be run after every test as per @After. It will
* clean resources initialized by the @Before methods.
*
* Other methods can be annotated with @After here or in subclasses
* but no execution order is guaranteed
*/
@After
@Override
public void destroy() {
try {
context.turnOffAuthorisationSystem();
// reload collection, community, group and eperson
if (collection != null) {
try {
collectionService.delete(context, collection);
} catch (Exception e) {
log.error("deleting collection", e);
}
collection = null;
}
if (owningCommunity != null) {
try {
communityService.delete(context, owningCommunity);
} catch (Exception e) {
log.error("deleting community", e);
}
owningCommunity = null;
}
if (member != null)
{
if (group != null) {
try {
groupService.removeMember(context, group, member);
} catch (Exception e) {
log.error("detaching group relationship", e);
}
try {
groupService.delete(context, group);
} catch (Exception e) {
log.error("detaching group relationship", e);
}
group = null;
}
try{
ePersonService.delete(context, member);
} catch (Exception e) {
log.error("deleting user", e);
}
eperson = null;
}
}
finally
{
// restore the authorization system
context.restoreAuthSystemState();
}
super.destroy();
}
private void setWorkflowGroup(Collection collection, Context context, int step, Group group) throws SQLException, AuthorizeException {
collection.setWorkflowGroup(context, step, group);
//collection.setWorkflowGroup(step, group);
}
/**
* Test if setWorkflowGroup method sets the appropriate policies for the
* new workflow group.
*/
@Test
public void testsetWorkflowGroupSetsPermission() throws SQLException, AuthorizeException
{
int step = 1;
try {
context.turnOffAuthorisationSystem();
setWorkflowGroup(collection, context, step, group);
collectionService.update(context, collection);
} finally {
context.restoreAuthSystemState();
}
Assert.assertThat("testsetWorkflowGroupSetsPermission 0", collectionService.getWorkflowGroup(collection, step), CoreMatchers.equalTo(group));
Assert.assertTrue(groupService.isDirectMember(group, member));
Assert.assertTrue("testsetWorkflowGroupSetsPermission 1", authorizeService.authorizeActionBoolean(context, member, collection, Constants.WORKFLOW_STEP_1, true));
}
/**
* Test if setWorkflowGroup method revokes policies when a workflow group
* is removed.
*/
@Test
public void testsetWorkflowGroupRevokesPermission() throws SQLException, AuthorizeException
{
int step = 1;
try {
context.turnOffAuthorisationSystem();
setWorkflowGroup(collection, context, step, group);
collectionService.update(context, collection);
} finally {
context.restoreAuthSystemState();
}
Assert.assertThat("testsetWorkflowGroupRevokesPermission 0", collectionService.getWorkflowGroup(collection, step), CoreMatchers
.equalTo(group));
Assert.assertTrue("testsetWorkflowGroupRevokesPermission 1", authorizeService.authorizeActionBoolean(context, member, collection, Constants.WORKFLOW_STEP_1, true));
try {
context.turnOffAuthorisationSystem();
setWorkflowGroup(collection, context, step, null);
collectionService.update(context, collection);
} finally {
context.restoreAuthSystemState();
}
Assert.assertThat("testsetWorkflowGroupRevokesPermission 2", collectionService.getWorkflowGroup(collection, step), CoreMatchers
.nullValue());
Assert.assertFalse("testsetWorkflowGroupRevokesPermission 3", authorizeService.authorizeActionBoolean(context, member, collection, Constants.WORKFLOW_STEP_1, true));
}
/**
* Test that a member of a worfklow step group can claim a task and get the
* appropriate policies.
*/
@Test
public void testReviewerPermissions()
throws SQLException, AuthorizeException, IOException, WorkflowException
{
BasicWorkflowItem wfi = null;
try {
// prepare a task to claim
// turn of the authorization system to be able to create the task
context.turnOffAuthorisationSystem();
setWorkflowGroup(collection, context, 1, group);
collectionService.update(context, collection);
WorkspaceItem wsi = workspaceItemService.create(context, collection, false);
Item item = wsi.getItem();
Bundle bundle = bundleService.create(context, item, "ORIGINAL");
File f = new File(AbstractDSpaceTest.testProps.get("test.bitstream").toString());
Bitstream bs = bitstreamService.create(context, bundle, new FileInputStream(f));
bundleService.update(context, bundle);
itemService.update(context, item);
workspaceItemService.update(context, wsi);
wfi = basicWorkflowService.startWithoutNotify(context, wsi);
basicWorkflowItemService.update(context, wfi);
} finally {
// restore the authorization system to perform our tests
context.restoreAuthSystemState();
}
wfi = basicWorkflowItemService.find(context, wfi.getID());
basicWorkflowService.claim(context, wfi, member);
Item item = wfi.getItem();
int i = 0;
// check item policies
for (int action : new int[] {Constants.READ, Constants.WRITE, Constants.ADD, Constants.REMOVE, Constants.DELETE})
{
Assert.assertTrue("testReviewerPermissions 1-" + i++,
authorizeService.authorizeActionBoolean(context, member, item, action, false));
}
// ensure we can read the original bundle and its bitstream
Bundle bundle = itemService.getBundles(item, "ORIGINAL").get(0);
Bitstream bitstream = bundle.getBitstreams().get(0);
Assert.assertTrue("testReviewerPermissions 2-1",
authorizeService.authorizeActionBoolean(context, member, bundle, Constants.READ, false));
Assert.assertTrue("testReviewerPermissions 2-2" + i++,
authorizeService.authorizeActionBoolean(context, member, bitstream, Constants.READ, false));
}
/**
* Test that a eperson not a member of a workflow step group can't claim a task.
*/
@Test(expected=AuthorizeException.class)
public void testNonWorkflowGroupMemberCannotClaimTask()
throws SQLException, AuthorizeException, IOException, WorkflowException
{
BasicWorkflowItem wfi = null;
EPerson someone = null;
try {
// prepare a task to claim
// turn of the authorization system to be able to create the task
context.turnOffAuthorisationSystem();
someone = ePersonService.create(context);
setWorkflowGroup(collection, context, 1, group);
collectionService.update(context, collection);
WorkspaceItem wsi = workspaceItemService.create(context, collection, false);
Item item = wsi.getItem();
Bundle bundle = bundleService.create(context, item, "ORIGINAL");
File f = new File(AbstractDSpaceTest.testProps.get("test.bitstream").toString());
Bitstream bs = bitstreamService.create(context, bundle, new FileInputStream(f));
bundleService.update(context, bundle);
itemService.update(context, item);
workspaceItemService.update(context, wsi);
wfi = basicWorkflowService.startWithoutNotify(context, wsi);
basicWorkflowItemService.update(context, wfi);
} finally {
// restore the authorization system to perform our tests
context.restoreAuthSystemState();
}
wfi = basicWorkflowItemService.find(context, wfi.getID());
basicWorkflowService.claim(context, wfi, someone);
Assert.fail("Someone, not part of a workflow step group was able to claim a "
+ "task without an AUthorizeException.");
}
/**
* Test that the submitter of an item who is not member of the appropriate
* workflow step group cannot claim the task of his/her own submission.
* Submitter habe special permissions on Workflow and Workspace items, so we
* need to test that they are still not able to claim tasks for there own
* items.
*/
@Test(expected=AuthorizeException.class)
public void testNonWorkflowGroupSubmitterCannotClaimTask()
throws SQLException, AuthorizeException, IOException, WorkflowException
{
BasicWorkflowItem wfi = null;
EPerson submitter = null;
try {
// prepare a task to claim
// turn of the authorization system to be able to create the task
context.turnOffAuthorisationSystem();
submitter = ePersonService.create(context);
setWorkflowGroup(collection, context, 1, group);
collectionService.update(context, collection);
WorkspaceItem wsi = workspaceItemService.create(context, collection, false);
Item item = wsi.getItem();
item.setSubmitter(submitter);
Bundle bundle = bundleService.create(context, item, "ORIGINAL");
File f = new File(AbstractDSpaceTest.testProps.get("test.bitstream").toString());
Bitstream bs = bitstreamService.create(context, bundle, new FileInputStream(f));
bundleService.update(context, bundle);
itemService.update(context, item);
workspaceItemService.update(context, wsi);
wfi = basicWorkflowService.startWithoutNotify(context, wsi);
basicWorkflowItemService.update(context, wfi);
} finally {
// restore the authorization system to perform our tests
context.restoreAuthSystemState();
}
wfi = basicWorkflowItemService.find(context, wfi.getID());
basicWorkflowService.claim(context, wfi, submitter);
Assert.fail("A submitter was able to claim a task without being a member of the "
+ "appropriate workflow step group. Expected: AuthorizeException.");
}
}