mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-18 07:23:08 +00:00
73986: Features Endpoint - Usage Statistics Permissions in REST
This commit is contained in:
@@ -129,3 +129,6 @@ configuration.exposed.array.value = public_value_1, public_value_2
|
|||||||
# Test config for the authentication ip functionality
|
# Test config for the authentication ip functionality
|
||||||
authentication-ip.Staff = 5.5.5.5
|
authentication-ip.Staff = 5.5.5.5
|
||||||
authentication-ip.Student = 6.6.6.6
|
authentication-ip.Student = 6.6.6.6
|
||||||
|
|
||||||
|
# Test config for the usage statistics authorization
|
||||||
|
usage-statistics.authorization.admin.usage = true
|
||||||
|
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* 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.app.rest.authorization.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||||
|
import org.dspace.app.rest.authorization.AuthorizationFeatureDocumentation;
|
||||||
|
import org.dspace.app.rest.model.BaseObjectRest;
|
||||||
|
import org.dspace.app.rest.model.CollectionRest;
|
||||||
|
import org.dspace.app.rest.model.CommunityRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.model.SiteRest;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The view statistics feature. It can be used to verify if statistics can be viewed.
|
||||||
|
*
|
||||||
|
* In case DSpace is configured to only show statistics to administrators, authorization is granted if the current user
|
||||||
|
* is the object's admin. Otherwise, authorization is granted if the current user can view the object.
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@AuthorizationFeatureDocumentation(name = ViewUsageStatisticsFeature.NAME,
|
||||||
|
description = "It can be used to verify if statistics can be viewed")
|
||||||
|
public class ViewUsageStatisticsFeature implements AuthorizationFeature {
|
||||||
|
|
||||||
|
public final static String NAME = "canViewUsageStatistics";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||||
|
if (object instanceof SiteRest
|
||||||
|
|| object instanceof CommunityRest
|
||||||
|
|| object instanceof CollectionRest
|
||||||
|
|| object instanceof ItemRest) {
|
||||||
|
|
||||||
|
if (configurationService.getBooleanProperty("usage-statistics.authorization.admin.usage", true)) {
|
||||||
|
return authorizeService.isAdmin(context,
|
||||||
|
(DSpaceObject)utils.getDSpaceAPIObjectFromRest(context, object));
|
||||||
|
} else {
|
||||||
|
return authorizeService.authorizeActionBoolean(context,
|
||||||
|
(DSpaceObject)utils.getDSpaceAPIObjectFromRest(context, object), org.dspace.core.Constants.READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getSupportedTypes() {
|
||||||
|
return new String[]{
|
||||||
|
SiteRest.CATEGORY + "." + SiteRest.NAME,
|
||||||
|
CommunityRest.CATEGORY + "." + CommunityRest.NAME,
|
||||||
|
CollectionRest.CATEGORY + "." + CollectionRest.NAME,
|
||||||
|
ItemRest.CATEGORY + "." + ItemRest.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,315 @@
|
|||||||
|
/**
|
||||||
|
* 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.app.rest.authorization;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
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 org.apache.commons.codec.CharEncoding;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.dspace.app.rest.converter.BitstreamConverter;
|
||||||
|
import org.dspace.app.rest.converter.CollectionConverter;
|
||||||
|
import org.dspace.app.rest.converter.CommunityConverter;
|
||||||
|
import org.dspace.app.rest.converter.ItemConverter;
|
||||||
|
import org.dspace.app.rest.converter.SiteConverter;
|
||||||
|
import org.dspace.app.rest.model.BitstreamRest;
|
||||||
|
import org.dspace.app.rest.model.CollectionRest;
|
||||||
|
import org.dspace.app.rest.model.CommunityRest;
|
||||||
|
import org.dspace.app.rest.model.ItemRest;
|
||||||
|
import org.dspace.app.rest.model.SiteRest;
|
||||||
|
import org.dspace.app.rest.projection.Projection;
|
||||||
|
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||||
|
import org.dspace.app.rest.utils.Utils;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.builder.BitstreamBuilder;
|
||||||
|
import org.dspace.builder.BundleBuilder;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.Bundle;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.Site;
|
||||||
|
import org.dspace.content.service.SiteService;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for the canViewUsageStatistics authorization feature
|
||||||
|
*/
|
||||||
|
public class ViewUsageStatisticsFeatureIT extends AbstractControllerIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Utils utils;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SiteConverter siteConverter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CommunityConverter communityConverter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CollectionConverter collectionConverter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ItemConverter itemConverter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BitstreamConverter bitstreamConverter;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
SiteService siteService;
|
||||||
|
|
||||||
|
private Site site;
|
||||||
|
private SiteRest siteRest;
|
||||||
|
private Community communityA;
|
||||||
|
private CommunityRest communityARest;
|
||||||
|
private Collection collectionA;
|
||||||
|
private CollectionRest collectionARest;
|
||||||
|
private Item itemA;
|
||||||
|
private ItemRest itemARest;
|
||||||
|
private Bitstream bitstreamA;
|
||||||
|
private BitstreamRest bitstreamARest;
|
||||||
|
private Bundle bundleA;
|
||||||
|
private String adminToken;
|
||||||
|
private String epersonToken;
|
||||||
|
|
||||||
|
final String feature = "canViewUsageStatistics";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
site = siteService.findSite(context);
|
||||||
|
communityA = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("communityA")
|
||||||
|
.build();
|
||||||
|
collectionA = CollectionBuilder.createCollection(context, communityA)
|
||||||
|
.withName("collectionA")
|
||||||
|
.build();
|
||||||
|
itemA = ItemBuilder.createItem(context, collectionA)
|
||||||
|
.withTitle("itemA")
|
||||||
|
.build();
|
||||||
|
bundleA = BundleBuilder.createBundle(context, itemA)
|
||||||
|
.withName("ORIGINAL")
|
||||||
|
.build();
|
||||||
|
String bitstreamContent = "Dummy content";
|
||||||
|
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||||
|
bitstreamA = BitstreamBuilder.createBitstream(context, bundleA, is)
|
||||||
|
.withName("bistreamA")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
siteRest = siteConverter.convert(site, Projection.DEFAULT);
|
||||||
|
communityARest = communityConverter.convert(communityA, Projection.DEFAULT);
|
||||||
|
collectionARest = collectionConverter.convert(collectionA, Projection.DEFAULT);
|
||||||
|
itemARest = itemConverter.convert(itemA, Projection.DEFAULT);
|
||||||
|
bitstreamARest = bitstreamConverter.convert(bitstreamA, Projection.DEFAULT);
|
||||||
|
|
||||||
|
adminToken = getAuthToken(admin.getEmail(), password);
|
||||||
|
epersonToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void adminBitstreamTestNotFound() throws Exception {
|
||||||
|
getClient(adminToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(bitstreamARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void adminItemAdminRequiredSuccess() throws Exception {
|
||||||
|
getClient(adminToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(itemARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void adminCollectionAdminRequiredSuccess() throws Exception {
|
||||||
|
getClient(adminToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(collectionARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void adminCommunityAdminRequiredSuccess() throws Exception {
|
||||||
|
getClient(adminToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(communityARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void adminSiteAdminRequiredSuccess() throws Exception {
|
||||||
|
getClient(adminToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(siteRest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonItemAdminRequiredNotFound() throws Exception {
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(itemARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonCollectionAdminRequiredNotFound() throws Exception {
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(collectionARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonCommunityAdminRequiredNotFound() throws Exception {
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(communityARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonSiteAdminRequiredNotFound() throws Exception {
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(siteRest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonItemAdminNotRequiredSuccess() throws Exception {
|
||||||
|
configurationService.setProperty("usage-statistics.authorization.admin.usage", false);
|
||||||
|
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(itemARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonCollectionAdminNotRequiredSuccess() throws Exception {
|
||||||
|
configurationService.setProperty("usage-statistics.authorization.admin.usage", false);
|
||||||
|
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(collectionARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonCommunityAdminNotRequiredSuccess() throws Exception {
|
||||||
|
configurationService.setProperty("usage-statistics.authorization.admin.usage", false);
|
||||||
|
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(communityARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonSiteAdminNotRequiredSuccess() throws Exception {
|
||||||
|
configurationService.setProperty("usage-statistics.authorization.admin.usage", false);
|
||||||
|
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(siteRest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", greaterThan(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ePersonPrivateItemAdminNotRequiredNotFound() throws Exception {
|
||||||
|
configurationService.setProperty("usage-statistics.authorization.admin.usage", false);
|
||||||
|
authorizeService.removeAllPolicies(context, itemA);
|
||||||
|
|
||||||
|
getClient(epersonToken).perform(
|
||||||
|
get("/api/authz/authorizations/search/object")
|
||||||
|
.param("embed", "feature")
|
||||||
|
.param("feature", feature)
|
||||||
|
.param("uri", utils.linkToSingleResource(itemARest, "self").getHref()))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.page.totalElements", is(0)))
|
||||||
|
.andExpect(jsonPath("$._embedded").doesNotExist());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user