94299 Multiple Bitstream deletion endpoint

This commit is contained in:
jensroets
2022-09-08 16:50:02 +02:00
parent fd4e6116a2
commit 51d8874a8f
4 changed files with 1050 additions and 0 deletions

View File

@@ -7,6 +7,7 @@
*/
package org.dspace.app.rest;
import static org.dspace.app.rest.utils.ContextUtil.obtainContext;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_DIGIT;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_HEX32;
import static org.dspace.app.rest.utils.RegexUtils.REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG;
@@ -55,6 +56,8 @@ import org.dspace.app.rest.repository.LinkRestRepository;
import org.dspace.app.rest.utils.RestRepositoryUtils;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context;
import org.dspace.util.UUIDUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
@@ -1050,6 +1053,13 @@ public class RestResourceController implements InitializingBean {
return deleteInternal(apiCategory, model, uuid);
}
@RequestMapping(method = RequestMethod.DELETE, consumes = {"text/uri-list"})
public ResponseEntity<RepresentationModel<?>> delete(HttpServletRequest request, @PathVariable String apiCategory,
@PathVariable String model)
throws HttpRequestMethodNotSupportedException {
return deleteUriListInternal(request, apiCategory, model);
}
/**
* Internal method to delete resource.
*
@@ -1067,6 +1077,29 @@ public class RestResourceController implements InitializingBean {
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
public <ID extends Serializable> ResponseEntity<RepresentationModel<?>> deleteUriListInternal(
HttpServletRequest request,
String apiCategory,
String model)
throws HttpRequestMethodNotSupportedException {
checkModelPluralForm(apiCategory, model);
DSpaceRestRepository<RestAddressableModel, ID> repository = utils.getResourceRepository(apiCategory, model);
Context context = obtainContext(request);
List<String> dsoStringList = utils.getStringListFromRequest(request);
List<DSpaceObject> dsoList = utils.constructDSpaceObjectList(context, dsoStringList);
if (dsoStringList.size() != dsoList.size()) {
throw new ResourceNotFoundException("One or more bitstreams could not be found.");
}
try {
repository.delete(dsoList);
} catch (ClassCastException e) {
log.error("Something went wrong whilst creating the object for apiCategory: " + apiCategory +
" and model: " + model, e);
return ControllerUtils.toEmptyResponse(HttpStatus.INTERNAL_SERVER_ERROR);
}
return ControllerUtils.toEmptyResponse(HttpStatus.NO_CONTENT);
}
/**
* Execute a PUT request for an entity with id of type UUID;
*

View File

@@ -10,6 +10,8 @@ package org.dspace.app.rest.repository;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@@ -147,6 +149,48 @@ public class BitstreamRestRepository extends DSpaceObjectRestRepository<Bitstrea
}
}
@Override
protected void deleteList(Context context, List<DSpaceObject> dsoList)
throws SQLException, AuthorizeException {
// check if list is empty
if (dsoList.isEmpty()) {
throw new ResourceNotFoundException("No bitstreams given.");
}
// check if every DSO is a Bitstream
if (dsoList.stream().anyMatch(dso -> !(dso instanceof Bitstream))) {
throw new UnprocessableEntityException("Not all given items are bitstreams.");
}
// check that they're all part of the same Item
List<DSpaceObject> items = new ArrayList<>();
for (DSpaceObject dso : dsoList) {
Bitstream bit = bs.find(context, dso.getID());
DSpaceObject bitstreamParent = bs.getParentObject(context, bit);
if (bit == null) {
throw new ResourceNotFoundException("The bitstream with uuid " + dso.getID() + " could not be found");
}
// we have to check if the bitstream has already been deleted
if (bit.isDeleted()) {
throw new UnprocessableEntityException("The bitstream with uuid " + bit.getID()
+ " was already deleted");
} else {
items.add(bitstreamParent);
}
}
if (items.stream().distinct().count() > 1) {
throw new UnprocessableEntityException("Not all given items are part of the same Item.");
}
// delete all Bitstreams
Iterator<DSpaceObject> iterator = dsoList.iterator();
while (iterator.hasNext()) {
Bitstream bit = (Bitstream) iterator.next();
try {
bs.delete(context, bit);
} catch (SQLException | IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
/**
* Find the bitstream for the provided handle and sequence or filename.
* When a bitstream can be found with the sequence ID it will be returned if the user has "METADATA_READ" access.

View File

@@ -26,6 +26,7 @@ import org.dspace.app.rest.model.ItemRest;
import org.dspace.app.rest.model.RestAddressableModel;
import org.dspace.app.rest.model.patch.Patch;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DSpaceObject;
import org.dspace.content.service.MetadataFieldService;
import org.dspace.core.Context;
import org.springframework.beans.factory.BeanNameAware;
@@ -256,6 +257,23 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
}
public void delete(List<DSpaceObject> dsoList) {
Context context = obtainContext();
try {
getThisRepository().deleteList(context, dsoList);
context.commit();
} catch (AuthorizeException e) {
throw new RESTAuthorizationException(e);
} catch (SQLException ex) {
throw new RuntimeException(ex.getMessage(), ex);
}
}
protected void deleteList(Context context, List<DSpaceObject> list)
throws AuthorizeException, SQLException, RepositoryMethodNotImplementedException {
throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", "");
}
@Override
/**
* This method cannot be implemented we required all the find method to be paginated

View File

@@ -13,6 +13,7 @@ import static org.dspace.core.Constants.WRITE;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -1201,6 +1202,960 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.andExpect(status().isNotFound());
}
@Test
public void deleteListOneBitstream() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
String bitstreamContent = "ThisIsSomeDummyText";
//Add a bitstream to an item
Bitstream bitstream = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
bitstream = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream")
.withDescription("Description")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream.getID()))
.andExpect(status().is(204));
// Verify 404 after delete
getClient(token).perform(get("/api/core/bitstreams/" + bitstream.getID()))
.andExpect(status().isNotFound());
}
@Test
public void deleteListOneOfMultipleBitstreams() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete bitstream1
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().is(204));
// Verify 404 after delete for bitstream1
getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isNotFound());
// check that bitstream2 still exists
getClient().perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()));
// check that bitstream3 still exists
getClient().perform(get("/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()))
;
}
@Test
public void deleteListAllBitstreams() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete all bitstreams
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().is(204));
// Verify 404 after delete for bitstream1
getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isNotFound());
// Verify 404 after delete for bitstream2
getClient(token).perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isNotFound());
// Verify 404 after delete for bitstream3
getClient(token).perform(get("/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isNotFound());
}
@Test
public void deleteListForbidden() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
// Delete using an unauthorized user
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isForbidden());
// Verify the bitstreams are still here
getClient().perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isOk());
getClient().perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk());
getClient().perform(get("/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isOk());
}
@Test
public void deleteListUnauthorized() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
// Delete as anonymous
getClient().perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isUnauthorized());
// Verify the bitstreams are still here
getClient().perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isOk());
getClient().perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk());
getClient().perform(get("/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isOk());
}
@Test
public void deleteListEmpty() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete with empty list throws 404
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content(""))
.andExpect(status().isNotFound());
// Verify the bitstreams are still here
getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isOk());
}
@Test
public void deleteListNotBitstream() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete with list containing non-Bitstream throws 422
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream3.getID()
+ " \n http://localhost:8080/server/api/core/items/" + publicItem1.getID()))
.andExpect(status().is(422));
// Verify the bitstreams are still here
getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isOk());
}
@Test
public void deleteListDifferentItems() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. Two public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
Item publicItem2 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 1 bitstream to each item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem2, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete with list containing Bitstreams from different items throws 422
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().is(422));
// Verify the bitstreams are still here
getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk());
}
@Test
public void deleteListLogo() throws Exception {
// We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
// ** GIVEN **
// 1. A community with a logo
parentCommunity = CommunityBuilder.createCommunity(context).withName("Community").withLogo("logo_community")
.build();
// 2. A collection with a logo
Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection")
.withLogo("logo_collection").build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// trying to DELETE parentCommunity logo and collection logo should work
// we have to delete them separately otherwise it will throw 422 as they belong to different items
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + parentCommunity.getLogo().getID()))
.andExpect(status().is(204));
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + col.getLogo().getID()))
.andExpect(status().is(204));
// Verify 404 after delete for parentCommunity logo
getClient(token).perform(get("/api/core/bitstreams/" + parentCommunity.getLogo().getID()))
.andExpect(status().isNotFound());
// Verify 404 after delete for collection logo
getClient(token).perform(get("/api/core/bitstreams/" + col.getLogo().getID()))
.andExpect(status().isNotFound());
}
@Test
public void deleteListMissing() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
// Delete
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb"))
.andExpect(status().isNotFound());
// Verify 404 after failed delete
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb"))
.andExpect(status().isNotFound());
}
@Test
public void deleteListOneMissing() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete all bitstreams and a missing bitstream returns 404
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream3.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb"))
.andExpect(status().isNotFound());
// Verify the bitstreams are still here
getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().isOk());
}
@Test
public void deleteListOneMissingDifferentItems() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. Two public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
Item publicItem2 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 1 bitstream to each item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem2, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete all bitstreams and a missing bitstream returns 404
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb"))
.andExpect(status().isNotFound());
// Verify the bitstreams are still here
getClient(token).perform(get("/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().isOk());
getClient(token).perform(get("/api/core/bitstreams/" + bitstream2.getID()))
.andExpect(status().isOk());
}
@Test
public void deleteListDeleted() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
String bitstreamContent = "ThisIsSomeDummyText";
//Add a bitstream to an item
Bitstream bitstream = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
bitstream = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream")
.withDescription("Description")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream.getID()))
.andExpect(status().is(204));
// Verify 404 when trying to delete a non-existing, already deleted, bitstream
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream.getID()))
.andExpect(status().is(422));
}
@Test
public void deleteListOneDeleted() throws Exception {
//We turn off the authorization system in order to create the structure as defined below
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
//2. One public items that is readable by Anonymous
Item publicItem1 = ItemBuilder.createItem(context, col1)
.withTitle("Test")
.withIssueDate("2010-10-17")
.withAuthor("Smith, Donald")
.withSubject("ExtraEntry")
.build();
// Add 3 bitstreams to the item
String bitstreamContent1 = "ThisIsSomeDummyText1";
Bitstream bitstream1 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent1, CharEncoding.UTF_8)) {
bitstream1 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream1")
.withDescription("Description1")
.withMimeType("text/plain")
.build();
}
String bitstreamContent2 = "ThisIsSomeDummyText2";
Bitstream bitstream2 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent2, CharEncoding.UTF_8)) {
bitstream2 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream2")
.withDescription("Description2")
.withMimeType("text/plain")
.build();
}
String bitstreamContent3 = "ThisIsSomeDummyText3";
Bitstream bitstream3 = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent3, CharEncoding.UTF_8)) {
bitstream3 = BitstreamBuilder.
createBitstream(context, publicItem1, is)
.withName("Bitstream3")
.withDescription("Description3")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete bitstream1
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()))
.andExpect(status().is(204));
// Verify 404 when trying to delete a non-existing, already deleted, bitstream
getClient(token).perform(delete("/api/core/bitstreams")
.contentType(TEXT_URI_LIST)
.content("http://localhost:8080/server/api/core/bitstreams/" + bitstream1.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream2.getID()
+ " \n http://localhost:8080/server/api/core/bitstreams/" + bitstream3.getID()))
.andExpect(status().is(422));
}
@Test
public void patchBitstreamMetadataAuthorized() throws Exception {
runPatchMetadataTests(admin, 200);