Merge pull request #10182 from tdonohue/port_9340_to_8x

[Port dspace-8_x] Bugfix: Enforce unique item id in workspace table (#9340)
This commit is contained in:
Tim Donohue
2025-01-07 10:45:22 -06:00
committed by GitHub
5 changed files with 124 additions and 0 deletions

View File

@@ -178,6 +178,14 @@ public class WorkspaceItemServiceImpl implements WorkspaceItemService {
@Override
public WorkspaceItem create(Context c, WorkflowItem workflowItem) throws SQLException, AuthorizeException {
WorkspaceItem potentialDuplicate = findByItem(c, workflowItem.getItem());
if (potentialDuplicate != null) {
throw new IllegalArgumentException(String.format(
"A workspace item referring to item %s already exists (%d)",
workflowItem.getItem().getID(),
potentialDuplicate.getID()
));
}
WorkspaceItem workspaceItem = workspaceItemDAO.create(c, new WorkspaceItem());
workspaceItem.setItem(workflowItem.getItem());
workspaceItem.setCollection(workflowItem.getCollection());

View File

@@ -0,0 +1,21 @@
--
-- 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/
--
-- In the workspaceitem table, if there are multiple rows referring to the same item ID, keep only the first of them.
DELETE FROM workspaceitem WHERE EXISTS (
SELECT item_id
FROM workspaceitem
GROUP BY item_id
HAVING COUNT(workspace_item_id) > 1
) AND workspaceitem.workspace_item_id NOT IN (
SELECT MIN(workspace_item_id) AS workspace_item_id
FROM workspaceitem
GROUP BY item_id
);
-- Identify which rows have duplicates, and compute their replacements.
ALTER TABLE workspaceitem ADD CONSTRAINT unique_item_id UNIQUE(item_id);

View File

@@ -0,0 +1,21 @@
--
-- 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/
--
-- In the workspaceitem table, if there are multiple rows referring to the same item ID, keep only the first of them.
WITH dedup AS (
SELECT item_id, MIN(workspace_item_id) AS workspace_item_id
FROM workspaceitem
GROUP BY item_id
HAVING COUNT(workspace_item_id) > 1
)
DELETE FROM workspaceitem
USING dedup
WHERE workspaceitem.item_id = dedup.item_id AND workspaceitem.workspace_item_id <> dedup.workspace_item_id;
-- Enforce uniqueness of item_id in workspaceitem table.
ALTER TABLE workspaceitem ADD CONSTRAINT unique_item_id UNIQUE(item_id);

View File

@@ -12,6 +12,7 @@ import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
@@ -39,6 +40,7 @@ import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.EPersonService;
import org.dspace.workflow.MockWorkflowItem;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -468,4 +470,14 @@ public class WorkspaceItemTest extends AbstractUnitTest {
assertTrue("testSetPublishedBefore 0", wi.isPublishedBefore());
}
@Test
public void testDuplicateItemID() throws Exception {
context.turnOffAuthorisationSystem();
Item item = wi.getItem();
MockWorkflowItem wfItem = new MockWorkflowItem();
wfItem.item = item;
wfItem.collection = collection;
assertThrows(IllegalArgumentException.class, () -> workspaceItemService.create(context, wfItem));
context.restoreAuthSystemState();
}
}

View File

@@ -0,0 +1,62 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.workflow;
import org.dspace.content.Collection;
import org.dspace.content.Item;
import org.dspace.eperson.EPerson;
public class MockWorkflowItem implements WorkflowItem {
public Integer id;
public Item item;
public Collection collection;
public EPerson submitter;
boolean hasMultipleFiles;
boolean hasMultipleTitles;
boolean isPublishedBefore;
public Integer getID() {
return id;
}
public Item getItem() {
return item;
}
public Collection getCollection() {
return collection;
}
public EPerson getSubmitter() {
return submitter;
}
public boolean hasMultipleFiles() {
return hasMultipleFiles;
}
public void setMultipleFiles(boolean b) {
hasMultipleFiles = b;
}
public boolean hasMultipleTitles() {
return hasMultipleTitles;
}
public void setMultipleTitles(boolean b) {
hasMultipleTitles = b;
}
public boolean isPublishedBefore() {
return isPublishedBefore;
}
public void setPublishedBefore(boolean b) {
isPublishedBefore = b;
}
}