84100: Admin only files rights issue IT

This commit is contained in:
Marie Verdonck
2021-10-13 11:40:18 +02:00
parent d6a9bca578
commit a0e92a5f18
3 changed files with 267 additions and 1 deletions

View File

@@ -1072,7 +1072,7 @@ prevent the generation of resource policy entry values with null dspace_object a
private boolean isNotAlreadyACustomRPOfThisTypeOnDSO(Context context, DSpaceObject dso) throws SQLException {
List<ResourcePolicy> readRPs = resourcePolicyService.find(context, dso, Constants.READ);
for (ResourcePolicy readRP : readRPs) {
if (readRP.getRpType().equals(ResourcePolicy.TYPE_CUSTOM)) {
if (readRP.getRpType() != null && readRP.getRpType().equals(ResourcePolicy.TYPE_CUSTOM)) {
return false;
}
}

View File

@@ -43,12 +43,16 @@ import org.apache.commons.lang3.time.DateUtils;
import org.dspace.app.rest.matcher.CollectionMatcher;
import org.dspace.app.rest.matcher.ItemMatcher;
import org.dspace.app.rest.matcher.MetadataMatcher;
import org.dspace.app.rest.matcher.ResourcePolicyMatcher;
import org.dspace.app.rest.matcher.WorkspaceItemMatcher;
import org.dspace.app.rest.model.patch.AddOperation;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.model.patch.RemoveOperation;
import org.dspace.app.rest.model.patch.ReplaceOperation;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.builder.BitstreamBuilder;
import org.dspace.builder.CollectionBuilder;
import org.dspace.builder.CommunityBuilder;
@@ -67,9 +71,11 @@ import org.dspace.content.Item;
import org.dspace.content.Relationship;
import org.dspace.content.RelationshipType;
import org.dspace.content.WorkspaceItem;
import org.dspace.core.Constants;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.GroupService;
import org.dspace.services.ConfigurationService;
import org.hamcrest.Matchers;
import org.junit.Before;
@@ -88,6 +94,10 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
@Autowired
private ConfigurationService configurationService;
private GroupService groupService;
private ResourcePolicyService resourcePolicyService;
private Group embargoedGroups;
private Group embargoedGroup1;
private Group embargoedGroup2;
@@ -98,6 +108,8 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
public void setUp() throws Exception {
super.setUp();
context.turnOffAuthorisationSystem();
this.groupService = EPersonServiceFactory.getInstance().getGroupService();
this.resourcePolicyService = AuthorizeServiceFactory.getInstance().getResourcePolicyService();
embargoedGroups = GroupBuilder.createGroup(context)
.withName("Embargoed Groups")
@@ -5299,4 +5311,232 @@ public class WorkspaceItemRestRepositoryIT extends AbstractControllerIntegration
}
@Test
public void patchUploadAddAdminRPInstallAndVerifyOnlyAdminCanView() throws Exception {
context.turnOffAuthorisationSystem();
Community community = CommunityBuilder.createCommunity(context).withName("Com").build();
Collection collection = CollectionBuilder.createCollection(context, community).withName("Col").build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem wItem = WorkspaceItemBuilder.createWorkspaceItem(context, collection)
.withSubmitter(eperson)
.withTitle(
"Test Item patchUploadAddAdminRPInstallAndVerifyOnlyAdminCanView")
.withIssueDate("2019-03-06")
.withFulltext("upload2.pdf", "/local/path/simple-article.pdf", pdf)
.build();
context.restoreAuthSystemState();
// auth
String epersonToken = getAuthToken(eperson.getEmail(), password);
String adminToken = getAuthToken(admin.getEmail(), password);
// prepare patch body
Map<String, String> accessCondition = new HashMap<>();
accessCondition.put("name", "administrator");
List<Operation> ops = new ArrayList<>();
ops.add(new AddOperation("/sections/upload/files/0/accessConditions/-", accessCondition));
String patchBody = getPatchContent(ops);
// submit patch and verify response
getClient(epersonToken)
.perform(
patch("/api/submission/workspaceitems/" + wItem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON)
)
.andExpect(status().isOk());
Bitstream bitstream = wItem.getItem().getBundles().get(0).getBitstreams().get(0);
Group adminGroup = groupService.findByName(context, Group.ADMIN);
// verify that bitstream of workspace item has this admin RP
getClient(adminToken).perform(get("/api/authz/resourcepolicies/search/resource")
.param("uuid", bitstream.getID().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.resourcepolicies", Matchers.hasItems(
ResourcePolicyMatcher.matchResourcePolicyProperties(adminGroup, null, bitstream,
ResourcePolicy.TYPE_CUSTOM, Constants.READ, "administrator")
)));
// submit the workspaceitem to complete the deposit (as there is no workflow configured)
getClient(epersonToken)
.perform(post(BASE_REST_SERVER_URL + "/api/workflow/workflowitems")
.content("/api/submission/workspaceitems/" + wItem.getID())
.contentType(textUriContentType))
.andExpect(status().isCreated());
Group anonGroup = groupService.findByName(context, Group.ANONYMOUS);
// verify that bitstream of workspace item still has this admin RP and no Anon READ inherited policy
getClient(adminToken).perform(get("/api/authz/resourcepolicies/search/resource")
.param("uuid", bitstream.getID().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.resourcepolicies", Matchers.hasItems(
ResourcePolicyMatcher.matchResourcePolicyProperties(adminGroup, null, bitstream,
ResourcePolicy.TYPE_CUSTOM, Constants.READ, "administrator")
)))
.andExpect(jsonPath("$._embedded.resourcepolicies", Matchers.not(Matchers.hasItems(
ResourcePolicyMatcher
.matchResourcePolicyProperties(anonGroup, null, bitstream, null, Constants.READ,
null)
))));
// Bitstream should NOT be accessible to anon or eperson user, only to admin
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
.andExpect(status().isUnauthorized());
getClient(epersonToken).perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
.andExpect(status().isForbidden());
getClient(adminToken).perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
.andExpect(status().isOk());
}
@Test
public void patchUploadAddOpenAccessRPInstallAndVerifyAnonCanView() throws Exception {
context.turnOffAuthorisationSystem();
Community community = CommunityBuilder.createCommunity(context).withName("Com").build();
Collection collection = CollectionBuilder.createCollection(context, community).withName("Col").build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem wItem =
WorkspaceItemBuilder.createWorkspaceItem(context, collection).withSubmitter(eperson)
.withTitle("Test Item patchUploadAddOpenAccessRPInstallAndVerifyOnlyAdminCanView")
.withIssueDate("2019-03-06")
.withFulltext("upload2.pdf", "/local/path/simple-article.pdf", pdf)
.build();
context.restoreAuthSystemState();
// auth
String epersonToken = getAuthToken(eperson.getEmail(), password);
String adminToken = getAuthToken(admin.getEmail(), password);
// prepare patch body
Map<String, String> accessCondition = new HashMap<>();
accessCondition.put("name", "openaccess");
List<Operation> ops = new ArrayList<>();
ops.add(new AddOperation("/sections/upload/files/0/accessConditions/-", accessCondition));
String patchBody = getPatchContent(ops);
// submit patch and verify response
getClient(epersonToken)
.perform(
patch("/api/submission/workspaceitems/" + wItem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON)
)
.andExpect(status().isOk());
Bitstream bitstream = wItem.getItem().getBundles().get(0).getBitstreams().get(0);
// verify that bitstream of workspace item has this open access RP
getClient(adminToken).perform(get("/api/authz/resourcepolicies/search/resource")
.param("uuid", bitstream.getID().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.resourcepolicies", Matchers.hasItems(
ResourcePolicyMatcher.matchResourcePolicyProperties(anonymousGroup, null, bitstream,
ResourcePolicy.TYPE_CUSTOM, Constants.READ, "openaccess")
)));
// submit the workspaceitem to complete the deposit (as there is no workflow configured)
getClient(epersonToken)
.perform(post(BASE_REST_SERVER_URL + "/api/workflow/workflowitems")
.content("/api/submission/workspaceitems/" + wItem.getID())
.contentType(textUriContentType))
.andExpect(status().isCreated());
// verify that bitstream of workspace item still has this open access RP
getClient(adminToken).perform(get("/api/authz/resourcepolicies/search/resource")
.param("uuid", bitstream.getID().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.resourcepolicies", Matchers.hasItems(
ResourcePolicyMatcher.matchResourcePolicyProperties(anonymousGroup, null, bitstream,
ResourcePolicy.TYPE_CUSTOM, Constants.READ, "openaccess")
)));
// Bitstream should be accessible to anon
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
.andExpect(status().isOk());
}
@Test
public void patchUploadAddAdminThenOpenAccessRPInstallAndVerifyAnonCanView() throws Exception {
context.turnOffAuthorisationSystem();
Community community = CommunityBuilder.createCommunity(context).withName("Com").build();
Collection collection = CollectionBuilder.createCollection(context, community).withName("Col").build();
InputStream pdf = getClass().getResourceAsStream("simple-article.pdf");
WorkspaceItem wItem =
WorkspaceItemBuilder.createWorkspaceItem(context, collection).withSubmitter(eperson)
.withTitle("Test Item patchUploadAddOpenAccessRPInstallAndVerifyOnlyAdminCanView")
.withIssueDate("2019-03-06")
.withFulltext("upload2.pdf", "/local/path/simple-article.pdf", pdf)
.build();
context.restoreAuthSystemState();
// auth
String epersonToken = getAuthToken(eperson.getEmail(), password);
String adminToken = getAuthToken(admin.getEmail(), password);
// prepare patch body
Map<String, String> accessCondition = new HashMap<>();
accessCondition.put("name", "administrator");
List<Operation> ops = new ArrayList<>();
ops.add(new AddOperation("/sections/upload/files/0/accessConditions/-", accessCondition));
String patchBody = getPatchContent(ops);
// submit patch and verify response
getClient(epersonToken)
.perform(
patch("/api/submission/workspaceitems/" + wItem.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON)
)
.andExpect(status().isOk());
Bitstream bitstream = wItem.getItem().getBundles().get(0).getBitstreams().get(0);
Group adminGroup = groupService.findByName(context, Group.ADMIN);
// verify that bitstream of workspace item has this admin RP
getClient(adminToken).perform(get("/api/authz/resourcepolicies/search/resource")
.param("uuid", bitstream.getID().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.resourcepolicies", Matchers.hasItems(
ResourcePolicyMatcher.matchResourcePolicyProperties(adminGroup, null, bitstream,
ResourcePolicy.TYPE_CUSTOM, Constants.READ, "administrator")
)));
// prepare patch body
Map<String, String> accessCondition2 = new HashMap<>();
accessCondition2.put("name", "openaccess");
List<Operation> ops2 = new ArrayList<>();
ops2.add(new AddOperation("/sections/upload/files/0/accessConditions/-", accessCondition2));
String patchBody2 = getPatchContent(ops2);
// submit patch and verify response
getClient(epersonToken)
.perform(
patch("/api/submission/workspaceitems/" + wItem.getID())
.content(patchBody2)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON)
)
.andExpect(status().isOk());
// verify that bitstream of workspace item has this open access RP
getClient(adminToken).perform(get("/api/authz/resourcepolicies/search/resource")
.param("uuid", bitstream.getID().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.resourcepolicies", Matchers.hasItems(
ResourcePolicyMatcher.matchResourcePolicyProperties(anonymousGroup, null, bitstream,
ResourcePolicy.TYPE_CUSTOM, Constants.READ, "openaccess")
)));
// submit the workspaceitem to complete the deposit (as there is no workflow configured)
getClient(epersonToken)
.perform(post(BASE_REST_SERVER_URL + "/api/workflow/workflowitems")
.content("/api/submission/workspaceitems/" + wItem.getID())
.contentType(textUriContentType))
.andExpect(status().isCreated());
// Bitstream should be accessible to anon
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
.andExpect(status().isOk());
}
}

View File

@@ -14,8 +14,13 @@ import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import javax.annotation.Nullable;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Constants;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.hamcrest.Matcher;
/**
@@ -29,6 +34,27 @@ public class ResourcePolicyMatcher {
private ResourcePolicyMatcher() {
}
public static Matcher<? super Object> matchResourcePolicyProperties(@Nullable Group group,
@Nullable EPerson eperson, DSpaceObject dso, @Nullable String rpType, int action, @Nullable String name) {
return allOf(
hasJsonPath("$.name", is(name)),
hasJsonPath("$.action", is(Constants.actionText[action])),
rpType != null ?
hasJsonPath("$.policyType", is(rpType)) :
hasNoJsonPath("$.policyType"),
hasJsonPath("$.type", is("resourcepolicy")),
hasJsonPath("$._embedded.resource.id", is(dso.getID().toString())),
eperson != null ?
hasJsonPath("$._embedded.eperson.id",
is(eperson.getID().toString())) :
hasJsonPath("$._embedded.eperson", nullValue()),
group != null ?
hasJsonPath("$._embedded.group.id",
is(group.getID().toString())) :
hasJsonPath("$._embedded.group", nullValue())
);
}
public static Matcher<? super Object> matchResourcePolicy(ResourcePolicy resourcePolicy) {
return allOf(hasJsonPath("$.id", is(resourcePolicy.getID())),
hasJsonPath("$.name", is(resourcePolicy.getRpName())),