Skip to content

Commit cf6e027

Browse files
committed
Fix SWORDv2 deposit with embargo for non-admin submitters
1 parent ceef4b3 commit cf6e027

5 files changed

Lines changed: 74 additions & 0 deletions

File tree

dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import org.apache.logging.log4j.Logger;
2626
import org.dspace.app.client.DSpaceHttpClientFactory;
2727
import org.dspace.authorize.AuthorizeException;
28+
import org.dspace.authorize.ResourcePolicy;
29+
import org.dspace.authorize.factory.AuthorizeServiceFactory;
30+
import org.dspace.authorize.service.AuthorizeService;
2831
import org.dspace.content.Bitstream;
2932
import org.dspace.content.BitstreamFormat;
3033
import org.dspace.content.Bundle;
@@ -127,6 +130,10 @@ public abstract class AbstractMETSIngester extends AbstractPackageIngester {
127130
protected final ConfigurationService configurationService
128131
= DSpaceServicesFactory.getInstance().getConfigurationService();
129132

133+
134+
protected final AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
135+
136+
130137
/**
131138
* <p>
132139
* An instance of ZipMdrefManager holds the state needed to retrieve the
@@ -763,11 +770,24 @@ protected void addBitstreams(Context context, Item item,
763770
bitstream.setSequenceID(Integer.parseInt(seqID));
764771
}
765772

773+
// Get TYPE_SUBMISSION policies before removing them in the `manifest.crosswalkBitstream` method.
774+
List<ResourcePolicy> bitstreamPolicies =
775+
authorizeService.findPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_SUBMISSION);
776+
766777
// crosswalk this bitstream's administrative metadata located in
767778
// METS manifest (or referenced externally)
768779
manifest.crosswalkBitstream(context, params, bitstream, mfileID,
769780
mdRefCallback);
770781

782+
// Only add the saved TYPE_SUBMISSION policies if the crosswalk actually removed them to prevent duplicates.
783+
if (!bitstreamPolicies.isEmpty()) {
784+
List<ResourcePolicy> remainingSubmissionPolicies =
785+
authorizeService.findPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_SUBMISSION);
786+
if (remainingSubmissionPolicies.isEmpty()) {
787+
authorizeService.addPolicies(context, bitstreamPolicies, bitstream);
788+
}
789+
}
790+
771791
// is this the primary bitstream?
772792
if (primaryID != null && mfileID.equals(primaryID)) {
773793
bundle.setPrimaryBitstreamID(bitstream);

dspace-server-webapp/src/test/java/org/dspace/app/sword2/Swordv2IT.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,48 @@ public void mediaResourceUnauthorizedTest() throws Exception {
190190
assertEquals(response.getStatusCode(), HttpStatus.UNAUTHORIZED);
191191
}
192192

193+
/**
194+
* There should not be any Internal Server/Authorization error when uploading a new Item with embargo
195+
* The embargo is defined in the `mets.xml` of the `example-embargo.zip` file
196+
*/
197+
@Test
198+
public void depositItemWithEmbargo() throws Exception {
199+
context.turnOffAuthorisationSystem();
200+
// Create a top level community and one Collection
201+
parentCommunity = CommunityBuilder.createCommunity(context)
202+
.withName("Parent Community")
203+
.build();
204+
// Make sure our Collection allows the "eperson" user to submit into it
205+
Collection collection = CollectionBuilder.createCollection(context, parentCommunity)
206+
.withName("Test SWORDv2 Collection")
207+
.withSubmitterGroup(eperson)
208+
.build();
209+
// Above changes MUST be committed to the database for SWORDv2 to see them.
210+
context.commit();
211+
context.restoreAuthSystemState();
212+
213+
// Add file
214+
LinkedMultiValueMap<Object, Object> multipart = new LinkedMultiValueMap<>();
215+
multipart.add("file", new FileSystemResource(Path.of("src", "test", "resources",
216+
"org", "dspace", "app", "sword2", "example-embargo.zip")));
217+
// Add required headers
218+
HttpHeaders headers = new HttpHeaders();
219+
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
220+
headers.setContentDisposition(ContentDisposition.attachment().filename("example-embargo.zip").build());
221+
headers.set("Packaging", "http://purl.org/net/sword/package/METSDSpaceSIP");
222+
headers.setAccept(List.of(MediaType.APPLICATION_ATOM_XML));
223+
224+
225+
// Send POST to upload Zip file via SWORD
226+
ResponseEntity<String> response = postResponseAsString(COLLECTION_PATH + "/" + collection.getHandle(),
227+
eperson.getEmail(), password,
228+
new HttpEntity<>(multipart, headers));
229+
230+
// Expect a 201 CREATED response with ATOM "entry" content returned
231+
assertEquals(HttpStatus.CREATED, response.getStatusCode());
232+
assertEquals(ATOM_ENTRY_CONTENT_TYPE, response.getHeaders().getContentType().toString());
233+
}
234+
193235
/**
194236
* This tests four different SWORDv2 actions, as these all require starting with a new deposit.
195237
* 1. Depositing a new item via SWORD (via POST /collections/[collection-uuid])
Binary file not shown.

dspace-swordv2/src/main/java/org/dspace/sword2/CollectionDepositManagerDSpace.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ public DepositReceipt createNew(String collectionUri, Deposit deposit,
151151
sc.commit();
152152

153153
return receipt;
154+
} catch (SwordAuthException e) {
155+
log.error("caught exception:", e);
156+
throw e;
154157
} catch (DSpaceSwordException e) {
155158
log.error("caught exception:", e);
156159
throw new SwordServerException(

dspace-swordv2/src/main/java/org/dspace/sword2/SwordMETSContentIngester.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import java.io.File;
1111

1212
import org.apache.logging.log4j.Logger;
13+
import org.dspace.authorize.AuthorizeException;
1314
import org.dspace.content.Collection;
1415
import org.dspace.content.DSpaceObject;
1516
import org.dspace.content.Item;
1617
import org.dspace.content.WorkspaceItem;
18+
import org.dspace.content.crosswalk.CrosswalkException;
1719
import org.dspace.content.factory.ContentServiceFactory;
1820
import org.dspace.content.packager.PackageIngester;
1921
import org.dspace.content.packager.PackageParameters;
@@ -28,6 +30,7 @@
2830
import org.swordapp.server.SwordAuthException;
2931
import org.swordapp.server.SwordError;
3032
import org.swordapp.server.SwordServerException;
33+
import org.swordapp.server.UriRegistry;
3134

3235
public class SwordMETSContentIngester extends AbstractSwordContentIngester {
3336
/**
@@ -181,6 +184,12 @@ public DepositResult ingestToCollection(Context context, Deposit deposit,
181184
} catch (RuntimeException re) {
182185
log.error("caught exception: ", re);
183186
throw re;
187+
} catch (AuthorizeException e) {
188+
log.error("caught exception: ", e);
189+
throw new SwordAuthException(e);
190+
} catch (CrosswalkException e) {
191+
log.error("caught exception: ", e);
192+
throw new SwordError(UriRegistry.ERROR_BAD_REQUEST, e.getMessage(), e);
184193
} catch (Exception e) {
185194
log.error("caught exception: ", e);
186195
throw new DSpaceSwordException(e);

0 commit comments

Comments
 (0)