Merge pull request #10952 from max-nuding/backport-10688-to-dspace-7_x

[Port dspace-7_x] Allow collection admins to add new policies for bitstreams
This commit is contained in:
Tim Donohue
2025-06-25 17:11:11 -05:00
committed by GitHub
6 changed files with 601 additions and 16 deletions

View File

@@ -19,6 +19,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.logging.log4j.Logger;
import org.dspace.authorize.dao.ResourcePolicyDAO;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.DSpaceObject;
import org.dspace.content.factory.ContentServiceFactory;
@@ -51,6 +52,9 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService {
@Autowired
private GroupService groupService;
@Autowired
private AuthorizeService authorizeService;
protected ResourcePolicyServiceImpl() {
}
@@ -422,6 +426,6 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService {
} else if (group != null && groupService.isMember(context, eperson, group)) {
isMy = true;
}
return isMy;
return isMy || authorizeService.isAdmin(context, eperson, resourcePolicy.getdSpaceObject());
}
}

View File

@@ -506,4 +506,5 @@ public final class Utils {
ConfigurationService config = DSpaceServicesFactory.getInstance().getConfigurationService();
return StringSubstitutor.replace(string, config.getProperties());
}
}

View File

@@ -25,6 +25,7 @@ import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.model.patch.Patch;
import org.dspace.app.rest.repository.patch.ResourcePatch;
import org.dspace.app.rest.security.DSpacePermissionEvaluator;
import org.dspace.app.rest.utils.DSpaceObjectUtils;
import org.dspace.app.rest.utils.Utils;
import org.dspace.authorize.AuthorizeException;
@@ -44,6 +45,8 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
import org.springframework.hateoas.Link;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
/**
@@ -73,6 +76,9 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
@Autowired
ResourcePatch<ResourcePolicy> resourcePatch;
@Autowired
private DSpacePermissionEvaluator permissionEvaluator;
@Autowired
DiscoverableEndpointsService discoverableEndpointsService;
@@ -222,14 +228,13 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
}
@Override
@PreAuthorize("hasAuthority('ADMIN')")
@PreAuthorize("isAuthenticated()")
protected ResourcePolicyRest createAndReturn(Context context) throws AuthorizeException, SQLException {
String resourceUuidStr = getRequestService().getCurrentRequest().getServletRequest().getParameter("resource");
String epersonUuidStr = getRequestService().getCurrentRequest().getServletRequest().getParameter("eperson");
String groupUuidStr = getRequestService().getCurrentRequest().getServletRequest().getParameter("group");
if (resourceUuidStr == null) {
throw new MissingParameterException("Missing resource (uuid) parameter");
}
@@ -244,6 +249,11 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
UUID resourceUuid = UUID.fromString(resourceUuidStr);
if (isNotAuthorized(resourceUuid, "WRITE")) {
throw new AuthorizeException(
"User unauthorized to create a new ResourcePolicy for resource: " + resourceUuid);
}
try {
resourcePolicyRest = mapper.readValue(req.getInputStream(), ResourcePolicyRest.class);
} catch (IOException exIO) {
@@ -298,7 +308,7 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
}
@Override
@PreAuthorize("hasAuthority('ADMIN')")
@PreAuthorize("hasPermission(#id, 'resourcepolicy', 'ADMIN')")
protected void delete(Context context, Integer id) throws AuthorizeException {
ResourcePolicy resourcePolicy = null;
try {
@@ -332,4 +342,10 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
Link.of("/api/" + ResourcePolicyRest.CATEGORY + "/" + ResourcePolicyRest.PLURAL_NAME + "/search",
ResourcePolicyRest.PLURAL_NAME + "-search")));
}
private boolean isNotAuthorized(UUID id, String permission) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return !permissionEvaluator.hasPermission(authentication, id, "resourcepolicy", permission);
}
}

View File

@@ -9,10 +9,13 @@ package org.dspace.app.rest.security;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.UUID;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.util.factory.UtilServiceFactory;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
@@ -38,7 +41,7 @@ public class ResourcePolicyAdminPermissionEvalutatorPlugin extends RestObjectPer
private static final Logger log = LoggerFactory.getLogger(ResourcePolicyRestPermissionEvaluatorPlugin.class);
public static final String RESOURCE_POLICY_PATCH = "resourcepolicy";
public static final String RESOURCE_POLICY_TYPE = "resourcepolicy";
@Autowired
AuthorizeService authorizeService;
@@ -55,8 +58,9 @@ public class ResourcePolicyAdminPermissionEvalutatorPlugin extends RestObjectPer
DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission);
if (!DSpaceRestPermission.ADMIN.equals(restPermission)
|| !StringUtils.equalsIgnoreCase(targetType, RESOURCE_POLICY_PATCH)) {
if (!DSpaceRestPermission.ADMIN.equals(restPermission) &&
!DSpaceRestPermission.WRITE.equals(restPermission) ||
!StringUtils.equalsIgnoreCase(targetType, RESOURCE_POLICY_TYPE)) {
return false;
}
@@ -64,19 +68,37 @@ public class ResourcePolicyAdminPermissionEvalutatorPlugin extends RestObjectPer
Context context = ContextUtil.obtainContext(request.getHttpServletRequest());
try {
int resourcePolicyID = Integer.parseInt(targetId.toString());
ResourcePolicy resourcePolicy = resourcePolicyService.find(context, resourcePolicyID);
if (resourcePolicy == null) {
throw new ResourceNotFoundException(
ResourcePolicyRest.CATEGORY + "." + ResourcePolicyRest.NAME +
" with id: " + resourcePolicyID + " not found");
DSpaceObject dso = null;
if (NumberUtils.isNumber(targetId.toString())) {
var id = Integer.parseInt(targetId.toString());
dso = getDSO(context, id);
} else {
var uuid = UUID.fromString(targetId.toString());
dso = getDSO(context, uuid);
}
DSpaceObject dso = resourcePolicy.getdSpaceObject();
return authorizeService.isAdmin(context, dso);
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
return false;
}
private DSpaceObject getDSO(Context context, int id) throws SQLException {
ResourcePolicy resourcePolicy = resourcePolicyService.find(context, id);
if (resourcePolicy == null) {
throw new ResourceNotFoundException(
ResourcePolicyRest.CATEGORY + "." + ResourcePolicyRest.NAME + " with id: " + id + " not found");
}
return resourcePolicy.getdSpaceObject();
}
private DSpaceObject getDSO(Context context, UUID uuid) throws SQLException {
DSpaceObject dso = UtilServiceFactory.getInstance().getDSpaceObjectUtils().findDSpaceObject(context, uuid);
if (dso == null) {
throw new ResourceNotFoundException("DSpaceObject with uuid: " + uuid + " not found");
}
return dso;
}
}

View File

@@ -55,7 +55,6 @@ public class ResourcePolicyRestPermissionEvaluatorPlugin extends RestObjectPermi
DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission);
if (!DSpaceRestPermission.READ.equals(restPermission)
&& !DSpaceRestPermission.WRITE.equals(restPermission)
&& !DSpaceRestPermission.DELETE.equals(restPermission)
|| !StringUtils.equalsIgnoreCase(targetType, ResourcePolicyRest.NAME)) {
return false;

View File

@@ -22,6 +22,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
@@ -32,6 +33,8 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.ws.rs.core.MediaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.CharEncoding;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.matcher.ResourcePolicyMatcher;
import org.dspace.app.rest.model.ResourcePolicyRest;
@@ -43,12 +46,14 @@ import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.builder.BitstreamBuilder;
import org.dspace.builder.CollectionBuilder;
import org.dspace.builder.CommunityBuilder;
import org.dspace.builder.EPersonBuilder;
import org.dspace.builder.GroupBuilder;
import org.dspace.builder.ItemBuilder;
import org.dspace.builder.ResourcePolicyBuilder;
import org.dspace.content.Bitstream;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.Item;
@@ -183,7 +188,7 @@ public class ResourcePolicyRestRepositoryIT extends AbstractControllerIntegratio
public void findOneNotFoundTest() throws Exception {
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/authz/resourcepolicies/" + UUID.randomUUID().toString()))
getClient(authToken).perform(get("/api/authz/resourcepolicies/" + UUID.randomUUID()))
.andExpect(status().isNotFound());
}
@@ -1215,6 +1220,376 @@ public class ResourcePolicyRestRepositoryIT extends AbstractControllerIntegratio
.andExpect(jsonPath("$.page.totalElements", is(0)));
}
@Test
public void createPolicyByCollectionAdminTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson colAdmin = EPersonBuilder.createEPerson(context)
.withEmail("colAdmin@mail.test")
.withPassword(password)
.build();
EPerson colAdmin2 = EPersonBuilder.createEPerson(context)
.withEmail("colAdmin2@mail.test")
.withPassword(password)
.build();
EPerson submitter = EPersonBuilder.createEPerson(context)
.withEmail("colSubmitter@mail.test")
.withPassword(password)
.build();
Community community = CommunityBuilder.createCommunity(context)
.withName("My top commynity")
.build();
Collection collection = CollectionBuilder.createCollection(context, community)
.withName("My collection")
.withAdminGroup(colAdmin)
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
CollectionBuilder.createCollection(context, community)
.withName("My Second Collection")
.withAdminGroup(colAdmin2)
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
Item publication = ItemBuilder.createItem(context, collection)
.withTitle("Public item")
.build();
//Add a bitstream to a publication
Bitstream bitstream = null;
try (InputStream is = IOUtils.toInputStream("ThisIsSomeDummyText", CharEncoding.UTF_8)) {
bitstream = BitstreamBuilder.createBitstream(context, publication, is)
.withName("Bitstream")
.withDescription("description")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
ResourcePolicyRest resourcePolicyRest = new ResourcePolicyRest();
resourcePolicyRest.setPolicyType(ResourcePolicy.TYPE_CUSTOM);
resourcePolicyRest.setAction(Constants.actionText[Constants.WRITE]);
resourcePolicyRest.setName("Test for collection admin");
String authcolAdminToken = getAuthToken(colAdmin.getEmail(), password);
String authcolAdmin2Token = getAuthToken(colAdmin2.getEmail(), password);
String authSubmitterToken = getAuthToken(submitter.getEmail(), password);
AtomicReference<Integer> idRef = new AtomicReference<Integer>();
try {
// submitter can't create policy
getClient(authSubmitterToken).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", bitstream.getID().toString())
.param("eperson", submitter.getID().toString())
.param("projections", "full")
.contentType(contentType))
.andExpect(status().isForbidden());
// other collection admin can't create policy for other collection
getClient(authcolAdmin2Token).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", bitstream.getID().toString())
.param("eperson", submitter.getID().toString())
.param("projections", "full")
.contentType(contentType))
.andExpect(status().isForbidden());
// create policy for submitter by collection admin
getClient(authcolAdminToken).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", bitstream.getID().toString())
.param("eperson", submitter.getID().toString())
.param("projections", "full")
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds()))
.andExpect(jsonPath("$", Matchers.allOf(
hasJsonPath("$.name", is(resourcePolicyRest.getName())),
hasJsonPath("$.description", is(resourcePolicyRest.getDescription())),
hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())),
hasJsonPath("$.action", is(resourcePolicyRest.getAction())),
hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())),
hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())),
hasJsonPath("$.type", is(resourcePolicyRest.getType())))))
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(), "$.id")));
// submitter can see own policy
getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef.get()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get())));
// collection admin can see that policy
getClient(authcolAdminToken).perform(get("/api/authz/resourcepolicies/" + idRef.get()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get())));
} finally {
ResourcePolicyBuilder.delete(idRef.get());
}
}
@Test
public void createPolicyBySubCommunityAdminTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson comAdmin = EPersonBuilder.createEPerson(context)
.withEmail("comAdmin@mail.test")
.withPassword(password)
.build();
EPerson comAdmin2 = EPersonBuilder.createEPerson(context)
.withEmail("comAdmin2@mail.test")
.withPassword(password)
.build();
EPerson submitter = EPersonBuilder.createEPerson(context)
.withEmail("colSubmitter@mail.test")
.withPassword(password)
.build();
Community community = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("My First Commynity")
.withAdminGroup(comAdmin)
.build();
Community community2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("My Second Commynity")
.withAdminGroup(comAdmin2)
.build();
Collection collection = CollectionBuilder.createCollection(context, community)
.withName("My collection")
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
CollectionBuilder.createCollection(context, community2)
.withName("My Second Collection")
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
Item publication = ItemBuilder.createItem(context, collection)
.withTitle("Public item")
.build();
context.restoreAuthSystemState();
ResourcePolicyRest resourcePolicyRest = new ResourcePolicyRest();
resourcePolicyRest.setPolicyType(ResourcePolicy.TYPE_CUSTOM);
resourcePolicyRest.setAction(Constants.actionText[Constants.WRITE]);
resourcePolicyRest.setName("Test for collection admin");
String authcomAdminToken = getAuthToken(comAdmin.getEmail(), password);
String authcomAdmin2Token = getAuthToken(comAdmin2.getEmail(), password);
String authSubmitterToken = getAuthToken(submitter.getEmail(), password);
AtomicReference<Integer> idRef = new AtomicReference<Integer>();
try {
// submitter can't create policy
getClient(authSubmitterToken).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", publication.getID().toString())
.param("eperson", submitter.getID().toString())
.param("projections", "full")
.contentType(contentType))
.andExpect(status().isForbidden());
// other Community admin can't create policy for collections into other Community
getClient(authcomAdmin2Token).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", publication.getID().toString())
.param("eperson", submitter.getID().toString())
.param("projections", "full")
.contentType(contentType))
.andExpect(status().isForbidden());
// create policy for submitter by Community admin
getClient(authcomAdminToken).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", publication.getID().toString())
.param("eperson", submitter.getID().toString())
.param("projections", "full")
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds()))
.andExpect(jsonPath("$", Matchers.allOf(
hasJsonPath("$.name", is(resourcePolicyRest.getName())),
hasJsonPath("$.description", is(resourcePolicyRest.getDescription())),
hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())),
hasJsonPath("$.action", is(resourcePolicyRest.getAction())),
hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())),
hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())),
hasJsonPath("$.type", is(resourcePolicyRest.getType())))))
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(), "$.id")));
// submitter can see own policy
getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef.get()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get())));
// community admin can see policies of own collections/items
getClient(authcomAdminToken).perform(get("/api/authz/resourcepolicies/" + idRef.get()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get())));
// Other community admin can't see policies of other community's collections/items
getClient(authcomAdmin2Token).perform(get("/api/authz/resourcepolicies/" + idRef.get()))
.andExpect(status().isForbidden());
} finally {
ResourcePolicyBuilder.delete(idRef.get());
}
}
@Test
public void createPolicyByCommunityAdminTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson rootComAdmin = EPersonBuilder.createEPerson(context)
.withEmail("rootComAdmin@mail.test")
.withPassword(password)
.build();
EPerson submitter = EPersonBuilder.createEPerson(context)
.withEmail("colSubmitter@mail.test")
.withPassword(password)
.build();
Community rootCommunity = CommunityBuilder.createCommunity(context)
.withName("Root Community")
.withAdminGroup(rootComAdmin)
.build();
Community community = CommunityBuilder.createSubCommunity(context, rootCommunity)
.withName("My First Commynity")
.build();
Community community2 = CommunityBuilder.createSubCommunity(context, rootCommunity)
.withName("My Second Commynity")
.build();
Collection collection = CollectionBuilder.createCollection(context, community)
.withName("My collection")
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
CollectionBuilder.createCollection(context, community2)
.withName("My Second Collection")
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
Item publication = ItemBuilder.createItem(context, collection)
.withTitle("Public item")
.build();
Collection collection2 = CollectionBuilder.createCollection(context, community)
.withName("My Second Collection")
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
Item publication2 = ItemBuilder.createItem(context, collection2)
.withTitle("Item of second collection")
.build();
//Add a bitstream to a publication
Bitstream bitstream = null;
try (InputStream is = IOUtils.toInputStream("ThisIsSomeDummyText", CharEncoding.UTF_8)) {
bitstream = BitstreamBuilder.createBitstream(context, publication2, is)
.withName("Bitstream")
.withDescription("description")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
ResourcePolicyRest resourcePolicyRest = new ResourcePolicyRest();
resourcePolicyRest.setPolicyType(ResourcePolicy.TYPE_CUSTOM);
resourcePolicyRest.setAction(Constants.actionText[Constants.WRITE]);
resourcePolicyRest.setName("Test for collection admin");
ResourcePolicyRest resourcePolicyRest2 = new ResourcePolicyRest();
resourcePolicyRest2.setPolicyType(ResourcePolicy.TYPE_CUSTOM);
resourcePolicyRest2.setAction(Constants.actionText[Constants.WRITE]);
resourcePolicyRest2.setName("Test for root community admin");
String authSubmitterToken = getAuthToken(submitter.getEmail(), password);
String authRootAdminToken = getAuthToken(rootComAdmin.getEmail(), password);
AtomicReference<Integer> idRef = new AtomicReference<Integer>();
AtomicReference<Integer> idRef2 = new AtomicReference<Integer>();
try {
// create policy for submitter by root Community admin
getClient(authRootAdminToken).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", publication.getID().toString())
.param("eperson", submitter.getID().toString())
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds()))
.andExpect(jsonPath("$", Matchers.allOf(
hasJsonPath("$.name", is(resourcePolicyRest.getName())),
hasJsonPath("$.description", is(resourcePolicyRest.getDescription())),
hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())),
hasJsonPath("$.action", is(resourcePolicyRest.getAction())),
hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())),
hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())),
hasJsonPath("$.type", is(resourcePolicyRest.getType())))))
.andDo(result -> idRef.set(read(result.getResponse().getContentAsString(), "$.id")));
// create policy for submitter by root Community admin
getClient(authRootAdminToken).perform(post("/api/authz/resourcepolicies")
.content(new ObjectMapper().writeValueAsBytes(resourcePolicyRest))
.param("resource", bitstream.getID().toString())
.param("eperson", submitter.getID().toString())
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$", ResourcePolicyMatcher.matchFullEmbeds()))
.andExpect(jsonPath("$", Matchers.allOf(
hasJsonPath("$.name", is(resourcePolicyRest.getName())),
hasJsonPath("$.description", is(resourcePolicyRest.getDescription())),
hasJsonPath("$.policyType", is(resourcePolicyRest.getPolicyType())),
hasJsonPath("$.action", is(resourcePolicyRest.getAction())),
hasJsonPath("$.startDate", is(resourcePolicyRest.getStartDate())),
hasJsonPath("$.endDate", is(resourcePolicyRest.getEndDate())),
hasJsonPath("$.type", is(resourcePolicyRest.getType())))))
.andDo(result -> idRef2.set(read(result.getResponse().getContentAsString(), "$.id")));
getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef.get()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + idRef.get())));
getClient(authSubmitterToken).perform(get("/api/authz/resourcepolicies/" + idRef2.get()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + idRef2.get())));
} finally {
ResourcePolicyBuilder.delete(idRef.get());
ResourcePolicyBuilder.delete(idRef2.get());
}
}
@Test
public void deleteOne() throws Exception {
context.turnOffAuthorisationSystem();
@@ -1308,6 +1683,174 @@ public class ResourcePolicyRestRepositoryIT extends AbstractControllerIntegratio
.andExpect(status().isNotFound());
}
@Test
public void deletePolicyByCollectionAdminTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson colAdmin = EPersonBuilder.createEPerson(context)
.withEmail("colAdmin@mail.test")
.withPassword(password)
.build();
EPerson colAdmin2 = EPersonBuilder.createEPerson(context)
.withEmail("colAdmin2@mail.test")
.withPassword(password)
.build();
EPerson submitter = EPersonBuilder.createEPerson(context)
.withEmail("colSubmitter@mail.test")
.withPassword(password)
.build();
Community community = CommunityBuilder.createCommunity(context)
.withName("My top commynity")
.build();
Collection collection = CollectionBuilder.createCollection(context, community)
.withName("My collection")
.withAdminGroup(colAdmin)
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
CollectionBuilder.createCollection(context, community)
.withName("My Second Collection")
.withAdminGroup(colAdmin2)
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
Item publication = ItemBuilder.createItem(context, collection)
.withTitle("Public item")
.build();
//Add a bitstream to a publication
Bitstream bitstream = null;
try (InputStream is = IOUtils.toInputStream("ThisIsSomeDummyText", CharEncoding.UTF_8)) {
bitstream = BitstreamBuilder.createBitstream(context, publication, is)
.withName("Bitstream")
.withDescription("description")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
String adminToken = getAuthToken(admin.getEmail(), password);
String authcolAdminToken = getAuthToken(colAdmin.getEmail(), password);
String authcolAdmin2Token = getAuthToken(colAdmin2.getEmail(), password);
String authSubmitterToken = getAuthToken(submitter.getEmail(), password);
ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context, submitter, null)
.withDspaceObject(bitstream)
.withAction(Constants.READ)
.withPolicyType(ResourcePolicy.TYPE_CUSTOM)
.build();
// submitter can't delete own policy
getClient(authSubmitterToken).perform(delete("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isForbidden());
// check that policy wasn't deleted
getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + rp.getID())));
// other collection admin can't delete policy that belong to items of other collections
getClient(authcolAdmin2Token).perform(delete("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isForbidden());
// check that policy wasn't deleted
getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + rp.getID())));
// delete policy for submitter by collection admin
getClient(authcolAdminToken).perform(delete("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isNoContent());
getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isNotFound());
}
@Test
public void deletePolicyBySubCommunityAdminTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson comAdmin = EPersonBuilder.createEPerson(context)
.withEmail("comAdmin@mail.test")
.withPassword(password)
.build();
EPerson comAdmin2 = EPersonBuilder.createEPerson(context)
.withEmail("comAdmin2@mail.test")
.withPassword(password)
.build();
EPerson submitter = EPersonBuilder.createEPerson(context)
.withEmail("colSubmitter@mail.test")
.withPassword(password)
.build();
Community community = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("My First Commynity")
.withAdminGroup(comAdmin)
.build();
Community community2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("My Second Commynity")
.withAdminGroup(comAdmin2)
.build();
Collection collection = CollectionBuilder.createCollection(context, community)
.withName("My collection")
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
CollectionBuilder.createCollection(context, community2)
.withName("My Second Collection")
.withSubmitterGroup(submitter)
.withEntityType("Publication")
.build();
Item publication = ItemBuilder.createItem(context, collection)
.withTitle("Public item")
.build();
context.restoreAuthSystemState();
ResourcePolicy rp = ResourcePolicyBuilder.createResourcePolicy(context, submitter, null)
.withDspaceObject(publication)
.withAction(Constants.WRITE)
.withPolicyType(ResourcePolicy.TYPE_CUSTOM)
.build();
String adminToken = getAuthToken(admin.getEmail(), password);
String authcomAdminToken = getAuthToken(comAdmin.getEmail(), password);
String authcomAdmin2Token = getAuthToken(comAdmin2.getEmail(), password);
// other Community admin can't delete policy of other Community
getClient(authcomAdmin2Token).perform(delete("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isForbidden());
getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/resourcepolicies/" + rp.getID())));
// Community admin can delete policy
getClient(authcomAdminToken).perform(delete("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isNoContent());
// submitter can see own policy
getClient(adminToken).perform(get("/api/authz/resourcepolicies/" + rp.getID()))
.andExpect(status().isNotFound());
}
@Test
public void patchReplaceStartDateTest() throws Exception {
context.turnOffAuthorisationSystem();