mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-17 15:03:18 +00:00
Merge remote-tracking branch 'upstream/master' into Manage-groups-2
This commit is contained in:
@@ -10,6 +10,7 @@ package org.dspace.app.rest;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.converter.EPersonConverter;
|
||||
@@ -20,6 +21,7 @@ import org.dspace.app.rest.model.EPersonRest;
|
||||
import org.dspace.app.rest.model.hateoas.AuthenticationStatusResource;
|
||||
import org.dspace.app.rest.model.hateoas.AuthnResource;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.app.rest.security.RestAuthenticationService;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.core.Context;
|
||||
@@ -60,6 +62,9 @@ public class AuthenticationRestController implements InitializingBean {
|
||||
@Autowired
|
||||
private HalLinkService halLinkService;
|
||||
|
||||
@Autowired
|
||||
private RestAuthenticationService restAuthenticationService;
|
||||
|
||||
@Autowired
|
||||
private Utils utils;
|
||||
|
||||
@@ -77,7 +82,8 @@ public class AuthenticationRestController implements InitializingBean {
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/status", method = RequestMethod.GET)
|
||||
public AuthenticationStatusResource status(HttpServletRequest request) throws SQLException {
|
||||
public AuthenticationStatusResource status(HttpServletRequest request, HttpServletResponse response)
|
||||
throws SQLException {
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
EPersonRest ePersonRest = null;
|
||||
Projection projection = utils.obtainProjection();
|
||||
@@ -86,6 +92,14 @@ public class AuthenticationRestController implements InitializingBean {
|
||||
}
|
||||
|
||||
AuthenticationStatusRest authenticationStatusRest = new AuthenticationStatusRest(ePersonRest);
|
||||
// Whether authentication status is false add WWW-Authenticate so client can retrieve the available
|
||||
// authentication methods
|
||||
if (!authenticationStatusRest.isAuthenticated()) {
|
||||
String authenticateHeaderValue = restAuthenticationService
|
||||
.getWwwAuthenticateHeaderValue(request, response);
|
||||
|
||||
response.setHeader("WWW-Authenticate", authenticateHeaderValue);
|
||||
}
|
||||
authenticationStatusRest.setProjection(projection);
|
||||
AuthenticationStatusResource authenticationStatusResource = converter.toResource(authenticationStatusRest);
|
||||
|
||||
|
@@ -10,7 +10,6 @@ package org.dspace.app.rest;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
|
@@ -12,7 +12,6 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@@ -36,6 +36,7 @@ import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.converter.JsonPatchConverter;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.exception.PaginationException;
|
||||
import org.dspace.app.rest.exception.RESTAuthorizationException;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
import org.dspace.app.rest.exception.RepositoryNotFoundException;
|
||||
import org.dspace.app.rest.exception.RepositorySearchMethodNotFoundException;
|
||||
@@ -583,9 +584,11 @@ public class RestResourceController implements InitializingBean {
|
||||
RestAddressableModel modelObject = null;
|
||||
try {
|
||||
modelObject = repository.upload(request, apiCategory, model, id, uploadfile);
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return ControllerUtils.toEmptyResponse(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
} catch (SQLException | IOException e) {
|
||||
throw new RuntimeException("Error " + e.getMessage() +
|
||||
" uploading file to " + model + " with ID= " + id, e);
|
||||
} catch ( AuthorizeException ae) {
|
||||
throw new RESTAuthorizationException(ae);
|
||||
}
|
||||
DSpaceResource result = converter.toResource(modelObject);
|
||||
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), result);
|
||||
|
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.dspace.app.rest.model.AuthnRest;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Rest controller that handles redirect after shibboleth authentication succeded
|
||||
*
|
||||
* @author Andrea Bollini (andrea dot bollini at 4science dot it)
|
||||
* @author Giuseppe Digilio (giuseppe dot digilio at 4science dot it)
|
||||
*/
|
||||
@RequestMapping(value = "/api/" + AuthnRest.CATEGORY + "/shibboleth")
|
||||
@RestController
|
||||
public class ShibbolethRestController implements InitializingBean {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ShibbolethRestController.class);
|
||||
|
||||
@Autowired
|
||||
ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
DiscoverableEndpointsService discoverableEndpointsService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
discoverableEndpointsService
|
||||
.register(this, Arrays.asList(new Link("/api/" + AuthnRest.CATEGORY, "shibboleth")));
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public void shibboleth(HttpServletResponse response,
|
||||
@RequestParam(name = "redirectUrl", required = false) String redirectUrl) throws IOException {
|
||||
if (redirectUrl == null) {
|
||||
redirectUrl = configurationService.getProperty("dspace.ui.url");
|
||||
}
|
||||
log.info("Redirecting to " + redirectUrl);
|
||||
response.sendRedirect(redirectUrl);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* 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 org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.app.rest.model.RestAddressableModel;
|
||||
import org.dspace.content.Site;
|
||||
import org.dspace.eperson.EPerson;
|
||||
|
||||
/**
|
||||
* An authorization is the right for a specific {@link EPerson}, eventually null to indicate unauthenticated users, to
|
||||
* use a specific {@link AuthorizationFeature} on a defined object. The target object must implement the
|
||||
* {@link RestAddressableModel} interface so to be directly addressable
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
public class Authorization {
|
||||
/**
|
||||
* the user authorized to use the feature. <code>null</code> mean unauthenticated user
|
||||
*/
|
||||
private EPerson eperson;
|
||||
|
||||
/**
|
||||
* the feature that is authorized to be used
|
||||
*/
|
||||
private AuthorizationFeature feature;
|
||||
|
||||
/**
|
||||
* the object where the feature can be used. Not null, for repository wide feature use the {@link Site} object
|
||||
*/
|
||||
private BaseObjectRest object;
|
||||
|
||||
public Authorization() {
|
||||
}
|
||||
|
||||
public Authorization(EPerson eperson, AuthorizationFeature feature, BaseObjectRest object) {
|
||||
super();
|
||||
this.eperson = eperson;
|
||||
this.feature = feature;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the user authorized to use the feature. <code>null</code> mean unauthenticated user
|
||||
*/
|
||||
public EPerson getEperson() {
|
||||
return eperson;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param eperson
|
||||
* the user authorized to use the feature. <code>null</code> mean unauthenticated user
|
||||
*/
|
||||
public void setEperson(EPerson eperson) {
|
||||
this.eperson = eperson;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the feature that is authorized to be used
|
||||
*/
|
||||
public AuthorizationFeature getFeature() {
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param feature
|
||||
* the feature that is authorized to be used
|
||||
*/
|
||||
public void setFeature(AuthorizationFeature feature) {
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the object where the feature can be used. Not null, for repository wide feature use the {@link Site}
|
||||
* object
|
||||
*/
|
||||
public BaseObjectRest getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param object
|
||||
* the object where the feature can be used. Not null, for repository wide feature use the {@link Site}
|
||||
* object
|
||||
*/
|
||||
public void setObject(BaseObjectRest object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return an unique business identifier generated by concatenation of eperson uuid (if any), feature name and
|
||||
* object unique identifier.
|
||||
* Some examples
|
||||
* alwaystrue_core.site_94274020-e617-43b8-90e6-277d04f6be13
|
||||
* 8c7b9132-eadc-4199-af6d-3260a678e96f_alwaystrueadmins_core.site_94274020-e617-43b8-90e6-277d04f6be13
|
||||
* 8c7b9132-eadc-4199-af6d-3260a678e96f_withdrawItem_core.item_c8924526-67ef-479a-8e37-dd8d19e625e9
|
||||
* 8c7b9132-eadc-4199-af6d-3260a678e96f_alwaystrue_submission.workspaceitem_1
|
||||
*/
|
||||
public String getID() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (eperson != null) {
|
||||
sb.append(eperson.getID().toString()).append("_");
|
||||
}
|
||||
sb.append(feature.getName()).append("_").append(object.getUniqueType()).append("_").append(object.getId());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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 java.sql.SQLException;
|
||||
|
||||
import org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.app.rest.model.RestAddressableModel;
|
||||
import org.dspace.app.rest.model.SiteRest;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
/**
|
||||
* A feature is the representation of a business goal used in the Authorization endpoint to declare what an user can do
|
||||
* on a specific object.
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
public interface AuthorizationFeature {
|
||||
/**
|
||||
* Check if the eperson in the provided context, or the anonymous user if not loggedin, has access to the feature
|
||||
* for the requested object
|
||||
*
|
||||
* @param context
|
||||
* the DSpace Context
|
||||
* @param object
|
||||
* the object target by the feature (MUST be NOT null). Use the {@link SiteRest} object for repository
|
||||
* wide feature
|
||||
* @return true if the user associated with the context has access to the feature for the specified object
|
||||
*/
|
||||
boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException;
|
||||
|
||||
/**
|
||||
* Return the name of the feature
|
||||
*
|
||||
* @return the name of the feature
|
||||
*/
|
||||
default String getName() {
|
||||
AuthorizationFeatureDocumentation anno =
|
||||
AnnotationUtils.findAnnotation(this.getClass(), AuthorizationFeatureDocumentation.class);
|
||||
if (anno != null) {
|
||||
return anno.name();
|
||||
}
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the description of the feature
|
||||
*
|
||||
* @return the description of the feature
|
||||
*/
|
||||
default String getDescription() {
|
||||
AuthorizationFeatureDocumentation anno =
|
||||
AnnotationUtils.findAnnotation(this.getClass(), AuthorizationFeatureDocumentation.class);
|
||||
if (anno != null) {
|
||||
return anno.description();
|
||||
}
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the supported object type according to the {@link RestAddressableModel#getUniqueType()}
|
||||
*
|
||||
* @return the supported object type, required to be not null
|
||||
*/
|
||||
String[] getSupportedTypes();
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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 java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Class level annotation to document an {@link AuthorizationFeature}
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface AuthorizationFeatureDocumentation {
|
||||
|
||||
/**
|
||||
* The name of the authorization feature (required).
|
||||
*
|
||||
* @return the name.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* The description of the authorization feature.
|
||||
*
|
||||
* @return the description of the authorization feature, or the empty string if unspecified by the annotation.
|
||||
*/
|
||||
String description() default "";
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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 java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.app.rest.model.SiteRest;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
/**
|
||||
* This service provides access to the Authorization Features and check if the feature is allowed or not in a specific
|
||||
* context and object.
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
public interface AuthorizationFeatureService {
|
||||
/**
|
||||
* Check if the eperson in the provided context, or the anonymous user if not loggedin, has access to the requested
|
||||
* feature for the requested object
|
||||
*
|
||||
* @param context
|
||||
* the DSpace Context
|
||||
* @param feature
|
||||
* the Authorization Feature to check
|
||||
* @param object
|
||||
* the object target by the feature. Passing a null object always return false. To check repository wide
|
||||
* feature pass the {@link SiteRest} object
|
||||
* @return true if the user associated with the context has access to the feature
|
||||
*/
|
||||
boolean isAuthorized(Context context, AuthorizationFeature feature, BaseObjectRest object) throws SQLException;
|
||||
|
||||
/**
|
||||
* Get all the authorization features defined in the system
|
||||
*
|
||||
* @return a list of all the authorization features
|
||||
*/
|
||||
public List<AuthorizationFeature> findAll();
|
||||
|
||||
/**
|
||||
* Get the authorization feature by its unique name
|
||||
*
|
||||
* @param name
|
||||
* the authorization feature unique name
|
||||
* @return the authorization feature if any
|
||||
*/
|
||||
public AuthorizationFeature find(String name);
|
||||
|
||||
/**
|
||||
* Return all the feature that apply to the rest resources identified by the
|
||||
* uniqueType string category.model
|
||||
*
|
||||
* @param categoryDotModel
|
||||
* @return
|
||||
*/
|
||||
List<AuthorizationFeature> findByResourceType(String categoryDotModel);
|
||||
}
|
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* 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 java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.app.rest.repository.DSpaceRestRepository;
|
||||
import org.dspace.app.rest.repository.ReloadableEntityObjectRepository;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Utility class to manipulate the AuthorizationRest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class AuthorizationRestUtil {
|
||||
|
||||
@Autowired
|
||||
private Utils utils;
|
||||
|
||||
/**
|
||||
* Extract the feature name from the Authorization business ID. See {@link Authorization#getID()}
|
||||
*
|
||||
* @param id
|
||||
* the Authorization business ID
|
||||
* @return the feature name
|
||||
*/
|
||||
public String getFeatureName(String id) {
|
||||
return splitIdParts(id)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object addressed in the authorization extracting its type and primary key from the authorization business
|
||||
* ID ({@link Authorization#getID()}) and using the appropriate service
|
||||
*
|
||||
* @param context
|
||||
* the DSpace context
|
||||
* @param id
|
||||
* the Authorization business ID. See {@link Authorization#getID()}
|
||||
* @return the object addressed in the authorization
|
||||
* @throws SQLException
|
||||
* if an error occur retrieving the data from the database
|
||||
* @throws IllegalArgumentException
|
||||
* if the specified id doesn't contain syntactically valid object information
|
||||
*/
|
||||
public BaseObjectRest getObject(Context context, String id) throws SQLException {
|
||||
String[] parts = splitIdParts(id);
|
||||
String objIdStr = parts[3];
|
||||
String[] objType;
|
||||
try {
|
||||
objType = parts[2].split("\\.");
|
||||
DSpaceRestRepository repository = utils.getResourceRepositoryByCategoryAndModel(objType[0], objType[1]);
|
||||
Serializable pk = utils.castToPKClass((ReloadableEntityObjectRepository) repository, objIdStr);
|
||||
try {
|
||||
// disable the security as we only need to retrieve the object to further process the authorization
|
||||
context.turnOffAuthorisationSystem();
|
||||
return (BaseObjectRest) repository.findOne(context, pk);
|
||||
} finally {
|
||||
context.restoreAuthSystemState();
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"The id " + id + " not resolve to a valid object", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the eperson in the authorization extracting its uuid from the authorization business ID
|
||||
* ({@link Authorization#getID()}) and retrieving the corresponding eperson object with the {@link EPersonService}.
|
||||
* Please note that reference to deleted eperson will result in an IllegalArgumentException
|
||||
*
|
||||
* @param context
|
||||
* the DSpace context
|
||||
* @param id
|
||||
* the Authorization business ID. See {@link Authorization#getID()}
|
||||
* @return the eperson addressed in the authorization or null if not specified.
|
||||
* @throws SQLException
|
||||
* if an error occur retrieving the data from the database
|
||||
* @throws IllegalArgumentException
|
||||
* if the specified id doesn't contain syntactically valid object information
|
||||
*/
|
||||
public EPerson getEperson(Context context, String id) throws SQLException {
|
||||
String epersonIdStr = splitIdParts(id)[0];
|
||||
if (StringUtils.isBlank(epersonIdStr)) {
|
||||
return null;
|
||||
}
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(epersonIdStr);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("The authorization id " + id +
|
||||
" contains a reference to an invalid eperson uuid " + epersonIdStr);
|
||||
}
|
||||
EPersonService service = EPersonServiceFactory.getInstance().getEPersonService();
|
||||
EPerson ep = service.find(context, uuid);
|
||||
if (ep == null) {
|
||||
throw new IllegalArgumentException("No eperson found with the uuid " + epersonIdStr);
|
||||
}
|
||||
return ep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the business ID in an array with a fixed length (4) as follow eperson uuid, feature name, object type id,
|
||||
* object id
|
||||
*
|
||||
* @param id
|
||||
* the Authorization business ID. See {@link Authorization#getID()}
|
||||
* @return an array with a fixed length (4) as follow eperson uuid, feature name, object type id, object id
|
||||
*/
|
||||
private String[] splitIdParts(String id) {
|
||||
String[] idParts = id.split("_");
|
||||
String eperson = null;
|
||||
String feature = null;
|
||||
String objType = null;
|
||||
String objId = null;
|
||||
if (idParts.length == 4) {
|
||||
eperson = idParts[0];
|
||||
feature = idParts[1];
|
||||
objType = idParts[2];
|
||||
objId = idParts[3];
|
||||
} else if (idParts.length == 3) {
|
||||
feature = idParts[0];
|
||||
objType = idParts[1];
|
||||
objId = idParts[2];
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"the authoization id is invalid, it must have the form " +
|
||||
"[eperson-uuid_]feature-id_object-type_object-id");
|
||||
}
|
||||
return new String[] { eperson, feature, objType, objId };
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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 java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureService;
|
||||
import org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* This is the default implementation of the {@link AuthorizationFeatureService}. It is based on the spring autowiring
|
||||
* feature to discover all the features available in the system
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class AuthorizationFeatureServiceImpl implements AuthorizationFeatureService {
|
||||
@Autowired
|
||||
private List<AuthorizationFeature> features;
|
||||
|
||||
@Autowired
|
||||
private Utils utils;
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(Context context, AuthorizationFeature feature, BaseObjectRest object)
|
||||
throws SQLException {
|
||||
if (object == null) {
|
||||
// the authorization interface require that the object is not null
|
||||
return false;
|
||||
}
|
||||
|
||||
if (feature == null
|
||||
|| !ArrayUtils.contains(feature.getSupportedTypes(), object.getUniqueType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return feature.isAuthorized(context, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthorizationFeature> findAll() {
|
||||
return features;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationFeature find(String name) {
|
||||
for (AuthorizationFeature feature : features) {
|
||||
if (StringUtils.equals(name, feature.getName())) {
|
||||
return feature;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthorizationFeature> findByResourceType(String categoryDotType) {
|
||||
// Loops through all features, returning any that match the given categoryDotType
|
||||
return features
|
||||
.stream()
|
||||
.filter(f -> ArrayUtils.contains(f.getSupportedTypes(), categoryDotType))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 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.ItemRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.app.util.AuthorizeUtil;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* The cclicense feature. It can be used by administrators (or community/collection delegate) to manage the Creative
|
||||
* Commons license for an item
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
@AuthorizationFeatureDocumentation(name = CCLicenseFeature.NAME,
|
||||
description = "It can be used by administrators (or community/collection delegate) to manage the Creative " +
|
||||
"Commons license for an item")
|
||||
public class CCLicenseFeature implements AuthorizationFeature {
|
||||
|
||||
public static final String NAME = "cclicense";
|
||||
|
||||
@Autowired
|
||||
private Utils utils;
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||
if (!(object instanceof ItemRest)) {
|
||||
return false;
|
||||
}
|
||||
Item item = (Item) utils.getDSpaceAPIObjectFromRest(context, object);
|
||||
try {
|
||||
AuthorizeUtil.authorizeManageCCLicense(context, item);
|
||||
} catch (AuthorizeException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedTypes() {
|
||||
return new String[] { ItemRest.CATEGORY + "." + ItemRest.NAME };
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.ItemRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.app.util.AuthorizeUtil;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* The reinstate feature. It can be used by administrators (or community/collection delegate) to reinstate an item that
|
||||
* was previously withdrawn
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
@AuthorizationFeatureDocumentation(name = ReinstateFeature.NAME,
|
||||
description = "It can be used by administrators (or community/collection delegate) to reinstate an item that "
|
||||
+ "was previously withdrawn")
|
||||
public class ReinstateFeature implements AuthorizationFeature {
|
||||
|
||||
public static final String NAME = "reinstateItem";
|
||||
|
||||
@Autowired
|
||||
private Utils utils;
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||
if (!(object instanceof ItemRest)) {
|
||||
return false;
|
||||
}
|
||||
Item item = (Item) utils.getDSpaceAPIObjectFromRest(context, object);
|
||||
if (!item.isWithdrawn()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
AuthorizeUtil.authorizeReinstateItem(context, item);
|
||||
} catch (AuthorizeException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedTypes() {
|
||||
return new String[] { ItemRest.CATEGORY + "." + ItemRest.NAME };
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.ItemRest;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.app.util.AuthorizeUtil;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* The withdrawn feature. It can be used by administrators (or community/collection delegate) to logically delete an
|
||||
* item retiring it from the archive
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
@AuthorizationFeatureDocumentation(name = WithdrawFeature.NAME,
|
||||
description = "It can be used by administrators (or community/collection delegate) to logically delete an "
|
||||
+ "item retiring it from the archive")
|
||||
public class WithdrawFeature implements AuthorizationFeature {
|
||||
|
||||
public final static String NAME = "withdrawItem";
|
||||
|
||||
@Autowired
|
||||
private Utils utils;
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
|
||||
if (!(object instanceof ItemRest)) {
|
||||
return false;
|
||||
}
|
||||
Item item = (Item) utils.getDSpaceAPIObjectFromRest(context, object);
|
||||
if (!item.isArchived()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
AuthorizeUtil.authorizeWithdrawItem(context, item);
|
||||
} catch (AuthorizeException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedTypes() {
|
||||
return new String[] { ItemRest.CATEGORY + "." + ItemRest.NAME };
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.converter;
|
||||
|
||||
import org.dspace.app.rest.authorization.Authorization;
|
||||
import org.dspace.app.rest.model.AuthorizationRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This class provides the method to convert an Authorization to its REST representation, the
|
||||
* AuthorizationRest
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
public class AuthorizationConverter
|
||||
implements DSpaceConverter<Authorization, AuthorizationRest> {
|
||||
|
||||
@Override
|
||||
public AuthorizationRest convert(Authorization authz, Projection projection) {
|
||||
AuthorizationRest featureRest = new AuthorizationRest();
|
||||
featureRest.setProjection(projection);
|
||||
if (authz != null) {
|
||||
featureRest.setId(authz.getID());
|
||||
}
|
||||
return featureRest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Authorization> getModelClass() {
|
||||
return Authorization.class;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.model.AuthorizationFeatureRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This class provides the method to convert an AuthorizationFeature to its REST representation, the
|
||||
* AuthorizationFeatureRest
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
public class AuthorizationFeatureConverter
|
||||
implements DSpaceConverter<AuthorizationFeature, AuthorizationFeatureRest> {
|
||||
|
||||
@Override
|
||||
public AuthorizationFeatureRest convert(AuthorizationFeature feature, Projection projection) {
|
||||
AuthorizationFeatureRest featureRest = new AuthorizationFeatureRest();
|
||||
featureRest.setProjection(projection);
|
||||
if (feature != null) {
|
||||
featureRest.setId(feature.getName());
|
||||
featureRest.setDescription(feature.getDescription());
|
||||
List<String> types = new ArrayList<String>();
|
||||
for (String t : feature.getSupportedTypes()) {
|
||||
types.add(t);
|
||||
}
|
||||
featureRest.setResourceTypes(types);
|
||||
}
|
||||
return featureRest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<AuthorizationFeature> getModelClass() {
|
||||
return AuthorizationFeature.class;
|
||||
}
|
||||
|
||||
}
|
@@ -38,7 +38,9 @@ public class ScriptConverter implements DSpaceConverter<DSpaceRunnable, ScriptRe
|
||||
ParameterRest parameterRest = new ParameterRest();
|
||||
parameterRest.setDescription(option.getDescription());
|
||||
parameterRest.setName((option.getOpt() != null ? "-" + option.getOpt() : "--" + option.getLongOpt()));
|
||||
parameterRest.setNameLong(option.getLongOpt() != null ? "--" + option.getLongOpt() : null);
|
||||
parameterRest.setType(((Class) option.getType()).getSimpleName());
|
||||
parameterRest.setMandatory(option.isRequired());
|
||||
parameterRestList.add(parameterRest);
|
||||
}
|
||||
scriptRest.setParameterRestList(parameterRestList);
|
||||
|
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.converter;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.services.model.Request;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the converter that takes care of the conversion between {@link Version} and {@link VersionRest}
|
||||
*/
|
||||
@Component
|
||||
public class VersionConverter implements DSpaceConverter<Version, VersionRest> {
|
||||
|
||||
private static final Logger log = Logger.getLogger(VersionConverter.class);
|
||||
|
||||
@Autowired
|
||||
private AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
private RequestService requestService;
|
||||
|
||||
@Override
|
||||
public VersionRest convert(Version modelObject, Projection projection) {
|
||||
VersionRest versionRest = new VersionRest();
|
||||
versionRest.setCreated(modelObject.getVersionDate());
|
||||
versionRest.setId(modelObject.getID());
|
||||
versionRest.setSummary(modelObject.getSummary());
|
||||
setSubmitterName(modelObject, versionRest);
|
||||
versionRest.setVersion(modelObject.getVersionNumber());
|
||||
versionRest.setProjection(projection);
|
||||
return versionRest;
|
||||
}
|
||||
|
||||
private void setSubmitterName(Version modelObject, VersionRest versionRest) {
|
||||
Context context = null;
|
||||
Request currentRequest = requestService.getCurrentRequest();
|
||||
if (currentRequest != null) {
|
||||
context = ContextUtil.obtainContext(currentRequest.getHttpServletRequest());
|
||||
}
|
||||
try {
|
||||
if ((context != null && authorizeService.isAdmin(context)) || configurationService
|
||||
.getBooleanProperty("versioning.item.history.include.submitter")) {
|
||||
EPerson submitter = modelObject.getEPerson();
|
||||
if (submitter != null) {
|
||||
versionRest.setSubmitterName(submitter.getFullName());
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Version> getModelClass() {
|
||||
return Version.class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.converter;
|
||||
|
||||
import org.dspace.app.rest.model.VersionHistoryRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.versioning.VersionHistory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the Converter that takes care of the conversion between {@link VersionHistory} and {@link VersionHistoryRest}
|
||||
*/
|
||||
@Component
|
||||
public class VersionHistoryConverter implements DSpaceConverter<VersionHistory, VersionHistoryRest> {
|
||||
|
||||
@Override
|
||||
public VersionHistoryRest convert(VersionHistory modelObject, Projection projection) {
|
||||
VersionHistoryRest versionHistoryRest = new VersionHistoryRest();
|
||||
versionHistoryRest.setId(modelObject.getID());
|
||||
return versionHistoryRest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<VersionHistory> getModelClass() {
|
||||
return VersionHistory.class;
|
||||
}
|
||||
}
|
@@ -35,7 +35,7 @@ public class AuthnHalLinkFactory extends HalLinkFactory<AuthnResource, Authentic
|
||||
.logout()));
|
||||
|
||||
list.add(buildLink("status", methodOn
|
||||
.status(null)));
|
||||
.status(null, null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty.Access;
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
/**
|
||||
* The Authorization Feature REST Resource, shortly feature. A feature is the representation of a business goal used in
|
||||
* the Authorization endpoint to declare what an user can do on a specific object.
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
public class AuthorizationFeatureRest extends BaseObjectRest<String> {
|
||||
public static final String NAME = "feature";
|
||||
public static final String CATEGORY = RestAddressableModel.AUTHORIZATION;
|
||||
|
||||
private String description;
|
||||
|
||||
@JsonProperty(value = "resourcetypes")
|
||||
private List<String> resourceTypes;
|
||||
|
||||
@Override
|
||||
@JsonProperty(access = Access.READ_ONLY)
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public List<String> getResourceTypes() {
|
||||
return resourceTypes;
|
||||
}
|
||||
|
||||
public void setResourceTypes(List<String> resourceTypes) {
|
||||
this.resourceTypes = resourceTypes;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty.Access;
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
/**
|
||||
* The Authorization REST Resource. An authorization is the representation of some rights that are available to a
|
||||
* specific user (eperson) on a defined object, eventually the whole repository (site object).
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@LinksRest(links = {
|
||||
@LinkRest(method = "getEperson", name = AuthorizationRest.EPERSON),
|
||||
@LinkRest(method = "getFeature", name = AuthorizationRest.FEATURE),
|
||||
@LinkRest(method = "getObject", name = AuthorizationRest.OBJECT)
|
||||
})
|
||||
public class AuthorizationRest extends BaseObjectRest<String> {
|
||||
public static final String NAME = "authorization";
|
||||
public static final String CATEGORY = RestAddressableModel.AUTHORIZATION;
|
||||
|
||||
public static final String EPERSON = "eperson";
|
||||
public static final String FEATURE = "feature";
|
||||
public static final String OBJECT = "object";
|
||||
|
||||
@Override
|
||||
@JsonProperty(access = Access.READ_ONLY)
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
}
|
@@ -33,6 +33,10 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
name = ItemRest.RELATIONSHIPS,
|
||||
method = "getRelationships"
|
||||
),
|
||||
@LinkRest(
|
||||
name = ItemRest.VERSION,
|
||||
method = "getItemVersion"
|
||||
),
|
||||
@LinkRest(
|
||||
name = ItemRest.TEMPLATE_ITEM_OF,
|
||||
method = "getTemplateItemOf"
|
||||
@@ -47,6 +51,7 @@ public class ItemRest extends DSpaceObjectRest {
|
||||
public static final String MAPPED_COLLECTIONS = "mappedCollections";
|
||||
public static final String OWNING_COLLECTION = "owningCollection";
|
||||
public static final String RELATIONSHIPS = "relationships";
|
||||
public static final String VERSION = "version";
|
||||
public static final String TEMPLATE_ITEM_OF = "templateItemOf";
|
||||
|
||||
private boolean inArchive = false;
|
||||
|
@@ -25,6 +25,16 @@ public class ParameterRest {
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* The long name of the parameter
|
||||
*/
|
||||
private String nameLong;
|
||||
|
||||
/**
|
||||
* Boolean indicating whether the parameter is mandatory or not
|
||||
*/
|
||||
private boolean mandatory;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -48,4 +58,36 @@ public class ParameterRest {
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for the nameLong
|
||||
* @return the nameLong value of this ParameterRest
|
||||
*/
|
||||
public String getNameLong() {
|
||||
return nameLong;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the nameLong
|
||||
* @param nameLong The nameLong to be set on this ParameterRest
|
||||
*/
|
||||
public void setNameLong(String nameLong) {
|
||||
this.nameLong = nameLong;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for the mandatory
|
||||
* @return the mandatory value of this ParameterRest
|
||||
*/
|
||||
public boolean isMandatory() {
|
||||
return mandatory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the mandatory
|
||||
* @param mandatory The mandatory to be set on this ParameterRest
|
||||
*/
|
||||
public void setMandatory(boolean mandatory) {
|
||||
this.mandatory = mandatory;
|
||||
}
|
||||
}
|
||||
|
@@ -44,4 +44,16 @@ public abstract class RestAddressableModel implements RestModel {
|
||||
public void setProjection(Projection projection) {
|
||||
this.projection = projection;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
/**
|
||||
*
|
||||
* @return an unique string useful to unambiguously identify the type of rest
|
||||
* object. It is in the form of category.model where model is in its
|
||||
* singular form. Examples include core.item, core.community,
|
||||
* submission.workspaceitem, etc.
|
||||
*/
|
||||
public String getUniqueType() {
|
||||
return getCategory() + "." + getType();
|
||||
}
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@ public interface RestModel extends Serializable {
|
||||
public static final String SYSTEM = "system";
|
||||
public static final String WORKFLOW = "workflow";
|
||||
public static final String AUTHORIZATION = "authz";
|
||||
public static final String VERSIONING = "versioning";
|
||||
|
||||
public String getType();
|
||||
|
||||
|
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
/**
|
||||
* The REST object for the {@link org.dspace.versioning.VersionHistory} object
|
||||
*/
|
||||
@LinksRest(links = {
|
||||
@LinkRest(
|
||||
name = VersionHistoryRest.VERSIONS,
|
||||
method = "getVersions"
|
||||
)
|
||||
})
|
||||
public class VersionHistoryRest extends BaseObjectRest<Integer> {
|
||||
|
||||
private Integer id;
|
||||
|
||||
public static final String NAME = "versionhistory";
|
||||
public static final String CATEGORY = RestAddressableModel.VERSIONING;
|
||||
public static final String VERSIONS = "versions";
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for the id
|
||||
* @return the id value of this VersionHistoryRest
|
||||
*/
|
||||
@Override
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the id
|
||||
* @param id The id to be set on this VersionHistoryRest
|
||||
*/
|
||||
@Override
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
/**
|
||||
* The REST object for the {@link org.dspace.versioning.Version} objects
|
||||
*/
|
||||
@LinksRest(links = {
|
||||
@LinkRest(
|
||||
name = VersionRest.VERSION_HISTORY,
|
||||
method = "getVersionHistory"
|
||||
),
|
||||
@LinkRest(
|
||||
name = VersionRest.ITEM,
|
||||
method = "getVersionItem"
|
||||
)
|
||||
})
|
||||
public class VersionRest extends BaseObjectRest<Integer> {
|
||||
|
||||
public static final String NAME = "version";
|
||||
public static final String CATEGORY = RestAddressableModel.VERSIONING;
|
||||
|
||||
public static final String VERSION_HISTORY = "versionhistory";
|
||||
public static final String ITEM = "item";
|
||||
|
||||
private Integer id;
|
||||
private Integer version;
|
||||
private Date created;
|
||||
private String summary;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String submitterName;
|
||||
|
||||
/**
|
||||
* Generic getter for the id
|
||||
* @return the id value of this VersionRest
|
||||
*/
|
||||
@Override
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the id
|
||||
* @param id The id to be set on this VersionRest
|
||||
*/
|
||||
@Override
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for the version
|
||||
* @return the version value of this VersionRest
|
||||
*/
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the version
|
||||
* @param version The version to be set on this VersionRest
|
||||
*/
|
||||
public void setVersion(Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for the created
|
||||
* @return the created value of this VersionRest
|
||||
*/
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the created
|
||||
* @param created The created to be set on this VersionRest
|
||||
*/
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for the summary
|
||||
* @return the summary value of this VersionRest
|
||||
*/
|
||||
public String getSummary() {
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the summary
|
||||
* @param summary The summary to be set on this VersionRest
|
||||
*/
|
||||
public void setSummary(String summary) {
|
||||
this.summary = summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic getter for the submitterName
|
||||
* @return the submitterName value of this VersionRest
|
||||
*/
|
||||
public String getSubmitterName() {
|
||||
return submitterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic setter for the submitterName
|
||||
* @param submitterName The submitterName to be set on this VersionRest
|
||||
*/
|
||||
public void setSubmitterName(String submitterName) {
|
||||
this.submitterName = submitterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.AuthorizationFeatureRest;
|
||||
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Authorization Feature Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@RelNameDSpaceResource(AuthorizationFeatureRest.NAME)
|
||||
public class AuthorizationFeatureResource extends DSpaceResource<AuthorizationFeatureRest> {
|
||||
public AuthorizationFeatureResource(AuthorizationFeatureRest authzFeature, Utils utils) {
|
||||
super(authzFeature, utils);
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.AuthorizationRest;
|
||||
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Authorization Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@RelNameDSpaceResource(AuthorizationRest.NAME)
|
||||
public class AuthorizationResource extends DSpaceResource<AuthorizationRest> {
|
||||
public AuthorizationResource(AuthorizationRest authz, Utils utils) {
|
||||
super(authz, utils);
|
||||
}
|
||||
}
|
@@ -12,7 +12,7 @@ import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* Item Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* Collection Rest HAL Resource. The HAL Resource wraps the REST Resource
|
||||
* adding support for the links and embedded resources
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
|
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 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.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.VersionHistoryRest;
|
||||
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* The HALResource object for the {@link VersionHistoryRest} object
|
||||
*/
|
||||
@RelNameDSpaceResource(VersionHistoryRest.NAME)
|
||||
public class VersionHistoryResource extends DSpaceResource<VersionHistoryRest> {
|
||||
|
||||
public VersionHistoryResource(VersionHistoryRest data, Utils utils) {
|
||||
super(data, utils);
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
/**
|
||||
* The HALResource object for the {@link VersionRest} object
|
||||
*/
|
||||
@RelNameDSpaceResource(VersionRest.NAME)
|
||||
public class VersionResource extends DSpaceResource<VersionRest> {
|
||||
public VersionResource(VersionRest data, Utils utils) {
|
||||
super(data, utils);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.app.rest.model.step;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -93,4 +92,4 @@ public class UploadBitstreamRest extends UploadStatusResponse {
|
||||
public void setFormat(BitstreamFormatRest format) {
|
||||
this.format = format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.authorization.AuthorizationRestUtil;
|
||||
import org.dspace.app.rest.model.AuthorizationRest;
|
||||
import org.dspace.app.rest.model.EPersonRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Link repository for "eperson" subresource of an individual authorization.
|
||||
*/
|
||||
@Component(AuthorizationRest.CATEGORY + "." + AuthorizationRest.NAME + "." + AuthorizationRest.EPERSON)
|
||||
public class AuthorizationEpersonLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
private AuthorizationRestUtil authorizationRestUtil;
|
||||
|
||||
@PreAuthorize("hasPermission(#authzId, 'AUTHORIZATION', 'READ')")
|
||||
public EPersonRest getEperson(@Nullable HttpServletRequest request,
|
||||
String authzId,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) {
|
||||
Context context = obtainContext();
|
||||
EPerson eperson;
|
||||
try {
|
||||
eperson = authorizationRestUtil.getEperson(context, authzId);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
if (eperson == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.toRest(eperson, projection);
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureService;
|
||||
import org.dspace.app.rest.authorization.AuthorizationRestUtil;
|
||||
import org.dspace.app.rest.model.AuthorizationFeatureRest;
|
||||
import org.dspace.app.rest.model.AuthorizationRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Link repository for "feature" subresource of an individual authorization.
|
||||
*/
|
||||
@Component(AuthorizationRest.CATEGORY + "." + AuthorizationRest.NAME + "." + AuthorizationRest.FEATURE)
|
||||
public class AuthorizationFeatureLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
private AuthorizationRestUtil authorizationRestUtil;
|
||||
|
||||
@Autowired
|
||||
private AuthorizationFeatureService authorizationFeatureService;
|
||||
|
||||
@PreAuthorize("hasPermission(#authzId, 'AUTHORIZATION', 'READ')")
|
||||
public AuthorizationFeatureRest getFeature(@Nullable HttpServletRequest request,
|
||||
String authzId,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) {
|
||||
String featureName = authorizationRestUtil.getFeatureName(authzId);
|
||||
AuthorizationFeature feature = authorizationFeatureService.find(featureName);
|
||||
if (feature == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.toRest(feature, projection);
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.Parameter;
|
||||
import org.dspace.app.rest.SearchRestMethod;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureService;
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.model.AuthorizationFeatureRest;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage AuthorizationFeature Rest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component(AuthorizationFeatureRest.CATEGORY + "." + AuthorizationFeatureRest.NAME)
|
||||
public class AuthorizationFeatureRestRepository extends DSpaceRestRepository<AuthorizationFeatureRest, String> {
|
||||
|
||||
@Autowired
|
||||
private AuthorizationFeatureService authorizationFeatureService;
|
||||
|
||||
@Autowired
|
||||
protected ConverterService converter;
|
||||
|
||||
@Override
|
||||
public Class<AuthorizationFeatureRest> getDomainClass() {
|
||||
return AuthorizationFeatureRest.class;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@Override
|
||||
public Page<AuthorizationFeatureRest> findAll(Context context, Pageable pageable) {
|
||||
return converter.toRestPage(utils.getPage(authorizationFeatureService.findAll(),
|
||||
pageable), utils.obtainProjection());
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@Override
|
||||
public AuthorizationFeatureRest findOne(Context context, String id) {
|
||||
AuthorizationFeature authzFeature = authorizationFeatureService.find(id);
|
||||
if (authzFeature != null) {
|
||||
return converter.toRest(authzFeature, utils.obtainProjection());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@SearchRestMethod(name = "resourcetype")
|
||||
public Page<AuthorizationFeatureRest> findByResourceType(@Parameter(value = "type", required = true) String type,
|
||||
Pageable pageable) {
|
||||
List<AuthorizationFeature> foundFeatures = authorizationFeatureService.findByResourceType(type);
|
||||
return converter.toRestPage(utils.getPage(foundFeatures, pageable), utils.obtainProjection());
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.authorization.AuthorizationRestUtil;
|
||||
import org.dspace.app.rest.model.AuthorizationRest;
|
||||
import org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Link repository for "object" subresource of an individual authorization.
|
||||
*/
|
||||
@Component(AuthorizationRest.CATEGORY + "." + AuthorizationRest.NAME + "." + AuthorizationRest.OBJECT)
|
||||
public class AuthorizationObjectLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
private AuthorizationRestUtil authorizationRestUtil;
|
||||
|
||||
@PreAuthorize("hasPermission(#authzId, 'AUTHORIZATION', 'READ')")
|
||||
public BaseObjectRest getObject(@Nullable HttpServletRequest request,
|
||||
String authzId,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) {
|
||||
Context context = obtainContext();
|
||||
BaseObjectRest object;
|
||||
try {
|
||||
object = authorizationRestUtil.getObject(context, authzId);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
}
|
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.dspace.app.rest.Parameter;
|
||||
import org.dspace.app.rest.SearchRestMethod;
|
||||
import org.dspace.app.rest.authorization.Authorization;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureService;
|
||||
import org.dspace.app.rest.authorization.AuthorizationRestUtil;
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
import org.dspace.app.rest.model.AuthorizationRest;
|
||||
import org.dspace.app.rest.model.BaseObjectRest;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage Authorization Rest object
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
|
||||
@Component(AuthorizationRest.CATEGORY + "." + AuthorizationRest.NAME)
|
||||
public class AuthorizationRestRepository extends DSpaceRestRepository<AuthorizationRest, String> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AuthorizationRestRepository.class);
|
||||
|
||||
@Autowired
|
||||
private AuthorizationFeatureService authorizationFeatureService;
|
||||
|
||||
@Autowired
|
||||
private AuthorizationRestUtil authorizationRestUtil;
|
||||
|
||||
@Autowired
|
||||
private AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private EPersonService epersonService;
|
||||
|
||||
@Autowired
|
||||
protected ConverterService converter;
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasPermission(#id, 'authorization', 'READ')")
|
||||
public AuthorizationRest findOne(Context context, String id) {
|
||||
|
||||
AuthorizationRest authorizationRest = null;
|
||||
|
||||
String featureName;
|
||||
try {
|
||||
featureName = authorizationRestUtil.getFeatureName(id);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
BaseObjectRest object = null;
|
||||
try {
|
||||
object = authorizationRestUtil.getObject(context, id);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("Object informations not found in the specified id " + id, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
AuthorizationFeature authorizationFeature = null;
|
||||
if (featureName != null) {
|
||||
authorizationFeature = authorizationFeatureService.find(featureName);
|
||||
}
|
||||
|
||||
if (authorizationFeature == null) {
|
||||
return null;
|
||||
}
|
||||
// get the user specified identified by the id, can be null for anonymous
|
||||
EPerson user;
|
||||
try {
|
||||
user = authorizationRestUtil.getEperson(context, id);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("Invalid eperson informations in the specified id " + id, e);
|
||||
return null;
|
||||
}
|
||||
EPerson currUser = context.getCurrentUser();
|
||||
if (currUser != user) {
|
||||
// Temporarily change the Context's current user in order to retrieve
|
||||
// authorizations based on that user
|
||||
context.switchContextUser(user);
|
||||
}
|
||||
|
||||
if (authorizationFeatureService.isAuthorized(context, authorizationFeature, object)) {
|
||||
Authorization authz = new Authorization();
|
||||
authz.setEperson(user);
|
||||
authz.setFeature(authorizationFeature);
|
||||
authz.setObject(object);
|
||||
authorizationRest = converter.toRest(authz, utils.obtainProjection());
|
||||
}
|
||||
if (currUser != user) {
|
||||
// restore the real current user
|
||||
context.restoreContextUser();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return authorizationRest;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* It returns the list of matching available authorizations granted to the specified eperson or to the anonymous
|
||||
* user. Only administrators and the user identified by the epersonUuid parameter can access this method
|
||||
*
|
||||
* @param uri
|
||||
* the uri of the object to check the authorization against
|
||||
* @param epersonUuid
|
||||
* the eperson uuid to use in the authorization evaluation
|
||||
* @param pageable
|
||||
* the pagination options
|
||||
* @return the list of matching authorization available for the requested user and object, filtered by feature if
|
||||
* provided
|
||||
* @throws AuthorizeException
|
||||
* @throws SQLException
|
||||
*/
|
||||
@PreAuthorize("#epersonUuid==null || hasPermission(#epersonUuid, 'EPERSON', 'READ')")
|
||||
@SearchRestMethod(name = "object")
|
||||
public Page<AuthorizationRest> findByObject(@Parameter(value = "uri", required = true) String uri,
|
||||
@Parameter(value = "eperson") UUID epersonUuid,
|
||||
Pageable pageable) throws AuthorizeException, SQLException {
|
||||
Context context = obtainContext();
|
||||
BaseObjectRest obj = utils.getBaseObjectRestFromUri(context, uri);
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EPerson currUser = context.getCurrentUser();
|
||||
// get the user specified in the requested parameters, can be null for anonymous
|
||||
EPerson user = getUserFromRequestParameter(context, epersonUuid);
|
||||
if (currUser != user) {
|
||||
// Temporarily change the Context's current user in order to retrieve
|
||||
// authorizations based on that user
|
||||
context.switchContextUser(user);
|
||||
}
|
||||
|
||||
List<AuthorizationFeature> features = authorizationFeatureService.findByResourceType(obj.getUniqueType());
|
||||
List<Authorization> authorizations = new ArrayList<Authorization>();
|
||||
for (AuthorizationFeature f : features) {
|
||||
if (authorizationFeatureService.isAuthorized(context, f, obj)) {
|
||||
authorizations.add(new Authorization(user, f, obj));
|
||||
}
|
||||
}
|
||||
|
||||
if (currUser != user) {
|
||||
// restore the real current user
|
||||
context.restoreContextUser();
|
||||
}
|
||||
return converter.toRestPage(utils.getPage(authorizations, pageable), utils.obtainProjection());
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns the authorization related to the requested feature if granted to the specified eperson or to the
|
||||
* anonymous user. Only administrators and the user identified by the epersonUuid parameter can access this method
|
||||
*
|
||||
* @param uri
|
||||
* the uri of the object to check the authorization against
|
||||
* @param epersonUuid
|
||||
* the eperson uuid to use in the authorization evaluation
|
||||
* @param featureName
|
||||
* limit the authorization check to only the feature identified via its name
|
||||
* @param pageable
|
||||
* the pagination options
|
||||
* @return the list of matching authorization available for the requested user and object, filtered by feature if
|
||||
* provided
|
||||
* @throws AuthorizeException
|
||||
* @throws SQLException
|
||||
*/
|
||||
@PreAuthorize("#epersonUuid==null || hasPermission(#epersonUuid, 'EPERSON', 'READ')")
|
||||
@SearchRestMethod(name = "objectAndFeature")
|
||||
public AuthorizationRest findByObjectAndFeature(@Parameter(value = "uri", required = true) String uri,
|
||||
@Parameter(value = "eperson") UUID epersonUuid,
|
||||
@Parameter(value = "feature", required = true) String featureName,
|
||||
Pageable pageable) throws AuthorizeException, SQLException {
|
||||
Context context = obtainContext();
|
||||
BaseObjectRest obj = utils.getBaseObjectRestFromUri(context, uri);
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EPerson currUser = context.getCurrentUser();
|
||||
// get the user specified in the requested parameters, can be null for anonymous
|
||||
EPerson user = getUserFromRequestParameter(context, epersonUuid);
|
||||
if (currUser != user) {
|
||||
// Temporarily change the Context's current user in order to retrieve
|
||||
// authorizations based on that user
|
||||
context.switchContextUser(user);
|
||||
}
|
||||
AuthorizationFeature feature = authorizationFeatureService.find(featureName);
|
||||
AuthorizationRest authorizationRest = null;
|
||||
if (authorizationFeatureService.isAuthorized(context, feature, obj)) {
|
||||
Authorization authz = new Authorization();
|
||||
authz.setEperson(user);
|
||||
authz.setFeature(feature);
|
||||
authz.setObject(obj);
|
||||
authorizationRest = converter.toRest(authz, utils.obtainProjection());
|
||||
}
|
||||
if (currUser != user) {
|
||||
// restore the real current user
|
||||
context.restoreContextUser();
|
||||
}
|
||||
return authorizationRest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user specified in the request parameter if valid
|
||||
*
|
||||
* @param context
|
||||
* @param epersonUuid
|
||||
* @return
|
||||
* @throws AuthorizeException if the user specified in the request parameter is
|
||||
* not valid
|
||||
* @throws SQLException if a database error occurs
|
||||
*/
|
||||
private EPerson getUserFromRequestParameter(Context context, UUID epersonUuid)
|
||||
throws AuthorizeException, SQLException {
|
||||
EPerson currUser = context.getCurrentUser();
|
||||
EPerson user = currUser;
|
||||
if (epersonUuid != null) {
|
||||
if (currUser == null) {
|
||||
throw new AuthorizeException("attempt to anonymously access the authorization of the eperson "
|
||||
+ epersonUuid);
|
||||
} else {
|
||||
// an user is specified in the request parameters
|
||||
if (!authorizeService.isAdmin(context) && !epersonUuid.equals(currUser.getID())) {
|
||||
throw new AuthorizeException("attempt to access the authorization of the eperson " + epersonUuid
|
||||
+ " only system administrators can see the authorization of other users");
|
||||
}
|
||||
user = epersonService.find(context, epersonUuid);
|
||||
}
|
||||
} else {
|
||||
// the request asks to check the permission for the anonymous user
|
||||
user = null;
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<AuthorizationRest> getDomainClass() {
|
||||
return AuthorizationRest.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<AuthorizationRest> findAll(Context context, Pageable pageable) {
|
||||
throw new RepositoryMethodNotImplementedException(AuthorizationRest.NAME, "findAll");
|
||||
}
|
||||
}
|
@@ -9,6 +9,7 @@ package org.dspace.app.rest.repository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.ServletInputStream;
|
||||
@@ -29,6 +30,7 @@ import org.dspace.app.rest.model.patch.Patch;
|
||||
import org.dspace.app.rest.model.wrapper.TemplateItem;
|
||||
import org.dspace.app.rest.utils.CollectionRestEqualityUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
@@ -39,6 +41,12 @@ import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.indexobject.IndexableCollection;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -71,6 +79,12 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
|
||||
@Autowired
|
||||
private ItemService itemService;
|
||||
|
||||
@Autowired
|
||||
SearchService searchService;
|
||||
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
public CollectionRestRepository(CollectionService dsoService) {
|
||||
super(dsoService);
|
||||
}
|
||||
@@ -93,11 +107,28 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
|
||||
@Override
|
||||
public Page<CollectionRest> findAll(Context context, Pageable pageable) {
|
||||
try {
|
||||
long total = cs.countTotal(context);
|
||||
List<Collection> collections = cs.findAll(context, pageable.getPageSize(),
|
||||
Math.toIntExact(pageable.getOffset()));
|
||||
return converter.toRestPage(collections, pageable, total, utils.obtainProjection());
|
||||
} catch (SQLException e) {
|
||||
if (authorizeService.isAdmin(context)) {
|
||||
long total = cs.countTotal(context);
|
||||
List<Collection> collections = cs.findAll(context, pageable.getPageSize(),
|
||||
Math.toIntExact(pageable.getOffset()));
|
||||
return converter.toRestPage(collections, pageable, total, utils.obtainProjection());
|
||||
} else {
|
||||
List<Collection> collections = new LinkedList<Collection>();
|
||||
// search for all the collections and let the SOLR security plugins to limit
|
||||
// what is returned to what the user can see
|
||||
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||
discoverQuery.setDSpaceObjectFilter(IndexableCollection.TYPE);
|
||||
discoverQuery.setStart(Math.toIntExact(pageable.getOffset()));
|
||||
discoverQuery.setMaxResults(pageable.getPageSize());
|
||||
DiscoverResult resp = searchService.search(context, discoverQuery);
|
||||
long tot = resp.getTotalSearchResults();
|
||||
for (IndexableObject solrCollections : resp.getIndexableObjects()) {
|
||||
Collection c = ((IndexableCollection) solrCollections).getIndexedObject();
|
||||
collections.add(c);
|
||||
}
|
||||
return converter.toRestPage(collections, pageable, tot, utils.obtainProjection());
|
||||
}
|
||||
} catch (SQLException | SearchServiceException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -20,6 +21,13 @@ import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.indexobject.IndexableCollection;
|
||||
import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -37,6 +45,9 @@ public class CommunityCollectionLinkRepository extends AbstractDSpaceRestReposit
|
||||
@Autowired
|
||||
CommunityService communityService;
|
||||
|
||||
@Autowired
|
||||
SearchService searchService;
|
||||
|
||||
@PreAuthorize("hasPermission(#communityId, 'COMMUNITY', 'READ')")
|
||||
public Page<CollectionRest> getCollections(@Nullable HttpServletRequest request,
|
||||
UUID communityId,
|
||||
@@ -48,10 +59,27 @@ public class CommunityCollectionLinkRepository extends AbstractDSpaceRestReposit
|
||||
if (community == null) {
|
||||
throw new ResourceNotFoundException("No such community: " + communityId);
|
||||
}
|
||||
List<Collection> collections = community.getCollections();
|
||||
return converter.toRestPage(utils.getPage(collections, optionalPageable), projection);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
Pageable pageable = utils.getPageable(optionalPageable);
|
||||
List<Collection> collections = new LinkedList<Collection>();
|
||||
IndexObjectFactoryFactory indexObjectFactory = IndexObjectFactoryFactory.getInstance();
|
||||
IndexableObject scopeObject = indexObjectFactory.getIndexableObjects(context, community).get(0);
|
||||
// search for all the collections direct children of our community
|
||||
// and let the SOLR security plugins to limit what is returned to what the user can see
|
||||
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||
discoverQuery.setQuery("*:*");
|
||||
discoverQuery.setDSpaceObjectFilter(IndexableCollection.TYPE);
|
||||
discoverQuery.addFilterQueries("location.parent:" + communityId);
|
||||
discoverQuery.setStart(Math.toIntExact(pageable.getOffset()));
|
||||
discoverQuery.setMaxResults(pageable.getPageSize());
|
||||
DiscoverResult resp = searchService.search(context, scopeObject, discoverQuery);
|
||||
long tot = resp.getTotalSearchResults();
|
||||
for (IndexableObject solrCol : resp.getIndexableObjects()) {
|
||||
Collection c = ((IndexableCollection) solrCol).getIndexedObject();
|
||||
collections.add(c);
|
||||
}
|
||||
return converter.toRestPage(collections, pageable, tot, utils.obtainProjection());
|
||||
} catch (SQLException | SearchServiceException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ package org.dspace.app.rest.repository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.ServletInputStream;
|
||||
@@ -17,7 +18,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.Parameter;
|
||||
import org.dspace.app.rest.SearchRestMethod;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
@@ -27,11 +27,18 @@ import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.patch.Patch;
|
||||
import org.dspace.app.rest.utils.CommunityRestEqualityUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.indexobject.IndexableCommunity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -59,6 +66,11 @@ public class CommunityRestRepository extends DSpaceObjectRestRepository<Communit
|
||||
CommunityRestEqualityUtils communityRestEqualityUtils;
|
||||
|
||||
@Autowired
|
||||
SearchService searchService;
|
||||
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
private CommunityService cs;
|
||||
|
||||
public CommunityRestRepository(CommunityService dsoService) {
|
||||
@@ -147,11 +159,28 @@ public class CommunityRestRepository extends DSpaceObjectRestRepository<Communit
|
||||
@Override
|
||||
public Page<CommunityRest> findAll(Context context, Pageable pageable) {
|
||||
try {
|
||||
long total = cs.countTotal(context);
|
||||
List<Community> communities = cs.findAll(context, pageable.getPageSize(),
|
||||
if (authorizeService.isAdmin(context)) {
|
||||
long total = cs.countTotal(context);
|
||||
List<Community> communities = cs.findAll(context, pageable.getPageSize(),
|
||||
Math.toIntExact(pageable.getOffset()));
|
||||
return converter.toRestPage(communities, pageable, total, utils.obtainProjection());
|
||||
} catch (SQLException e) {
|
||||
return converter.toRestPage(communities, pageable, total, utils.obtainProjection());
|
||||
} else {
|
||||
List<Community> communities = new LinkedList<Community>();
|
||||
// search for all the communities and let the SOLR security plugins to limit
|
||||
// what is returned to what the user can see
|
||||
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||
discoverQuery.setDSpaceObjectFilter(IndexableCommunity.TYPE);
|
||||
discoverQuery.setStart(Math.toIntExact(pageable.getOffset()));
|
||||
discoverQuery.setMaxResults(pageable.getPageSize());
|
||||
DiscoverResult resp = searchService.search(context, discoverQuery);
|
||||
long tot = resp.getTotalSearchResults();
|
||||
for (IndexableObject solrCommunities : resp.getIndexableObjects()) {
|
||||
Community c = ((IndexableCommunity) solrCommunities).getIndexedObject();
|
||||
communities.add(c);
|
||||
}
|
||||
return converter.toRestPage(communities, pageable, tot, utils.obtainProjection());
|
||||
}
|
||||
} catch (SQLException | SearchServiceException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
@@ -168,25 +197,6 @@ public class CommunityRestRepository extends DSpaceObjectRestRepository<Communit
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add method in dspace api to support direct query for subcommunities
|
||||
// with pagination and authorization check
|
||||
@SearchRestMethod(name = "subCommunities")
|
||||
public Page<CommunityRest> findSubCommunities(@Parameter(value = "parent", required = true) UUID parentCommunity,
|
||||
Pageable pageable) {
|
||||
Context context = obtainContext();
|
||||
try {
|
||||
Community community = cs.find(context, parentCommunity);
|
||||
if (community == null) {
|
||||
throw new ResourceNotFoundException(
|
||||
CommunityRest.CATEGORY + "." + CommunityRest.NAME + " with id: " + parentCommunity + " not found");
|
||||
}
|
||||
List<Community> subCommunities = community.getSubcommunities();
|
||||
return converter.toRestPage(utils.getPage(subCommunities, pageable), utils.obtainProjection());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasPermission(#id, 'COMMUNITY', 'WRITE')")
|
||||
protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, UUID id,
|
||||
|
@@ -8,6 +8,7 @@
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -18,6 +19,13 @@ import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.DiscoverQuery;
|
||||
import org.dspace.discovery.DiscoverResult;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.SearchService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.discovery.indexobject.IndexableCommunity;
|
||||
import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -35,6 +43,9 @@ public class CommunitySubcommunityLinkRepository extends AbstractDSpaceRestRepos
|
||||
@Autowired
|
||||
CommunityService communityService;
|
||||
|
||||
@Autowired
|
||||
SearchService searchService;
|
||||
|
||||
@PreAuthorize("hasPermission(#communityId, 'COMMUNITY', 'READ')")
|
||||
public Page<CommunityRest> getSubcommunities(@Nullable HttpServletRequest request,
|
||||
UUID communityId,
|
||||
@@ -46,10 +57,25 @@ public class CommunitySubcommunityLinkRepository extends AbstractDSpaceRestRepos
|
||||
if (community == null) {
|
||||
throw new ResourceNotFoundException("No such community: " + communityId);
|
||||
}
|
||||
List<Community> subcommunities = community.getSubcommunities();
|
||||
return converter.toRestPage(utils.getPage(subcommunities, optionalPageable), projection);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
Pageable pageable = utils.getPageable(optionalPageable);
|
||||
List<Community> publicSubcommunities = new LinkedList<Community>();
|
||||
IndexObjectFactoryFactory indexObjectFactory = IndexObjectFactoryFactory.getInstance();
|
||||
IndexableObject scopeObject = indexObjectFactory.getIndexableObjects(context, community).get(0);
|
||||
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||
discoverQuery.setQuery("*:*");
|
||||
discoverQuery.setDSpaceObjectFilter(IndexableCommunity.TYPE);
|
||||
discoverQuery.addFilterQueries("location.parent:" + communityId);
|
||||
discoverQuery.setStart(Math.toIntExact(pageable.getOffset()));
|
||||
discoverQuery.setMaxResults(pageable.getPageSize());
|
||||
DiscoverResult resp = searchService.search(context, scopeObject, discoverQuery);
|
||||
long tot = resp.getTotalSearchResults();
|
||||
for (IndexableObject solrCommunities : resp.getIndexableObjects()) {
|
||||
Community c = ((IndexableCommunity) solrCommunities).getIndexedObject();
|
||||
publicSubcommunities.add(c);
|
||||
}
|
||||
return converter.toRestPage(publicSubcommunities, pageable, tot, utils.obtainProjection());
|
||||
} catch (SQLException | SearchServiceException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
* @param <R> the corresponding DSpaceObjectRest.
|
||||
*/
|
||||
public abstract class DSpaceObjectRestRepository<M extends DSpaceObject, R extends DSpaceObjectRest>
|
||||
extends DSpaceRestRepository<R, UUID> {
|
||||
extends DSpaceRestRepository<R, UUID> implements ReloadableEntityObjectRepository<M, UUID> {
|
||||
|
||||
final DSpaceObjectService<M> dsoService;
|
||||
|
||||
@@ -64,4 +64,14 @@ public abstract class DSpaceObjectRestRepository<M extends DSpaceObject, R exten
|
||||
resourcePatch.patch(obtainContext(), dso, patch.getOperations());
|
||||
dsoService.update(obtainContext(), dso);
|
||||
}
|
||||
|
||||
@Override
|
||||
public M findDomainObjectByPk(Context context, UUID uuid) throws SQLException {
|
||||
return dsoService.find(context, uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<UUID> getPKClass() {
|
||||
return UUID.class;
|
||||
}
|
||||
}
|
||||
|
@@ -14,7 +14,6 @@ import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
@@ -382,7 +381,8 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
|
||||
* @return the new state of the REST object
|
||||
*/
|
||||
public T upload(HttpServletRequest request, String apiCategory, String model,
|
||||
ID id, MultipartFile file) throws SQLException {
|
||||
ID id, MultipartFile file)
|
||||
throws SQLException, FileNotFoundException, IOException, AuthorizeException {
|
||||
throw new RuntimeException("No implementation found; Method not allowed!");
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the Repository that will take care of fetching the Version for a given Item
|
||||
*/
|
||||
@Component(ItemRest.CATEGORY + "." + ItemRest.NAME + "." + ItemRest.VERSION)
|
||||
public class ItemVersionLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
@Autowired
|
||||
private ItemService itemService;
|
||||
|
||||
/**
|
||||
* This method will return the VersionRest object from the Item that is associated with the given itemUuid
|
||||
* @param request The current request
|
||||
* @param itemUuid The itemUuid used to find the Item for which we'll return the VersionRest object
|
||||
* @param optionalPageable Pageable if present
|
||||
* @param projection Current Projection
|
||||
* @return The VersionRest object constructed from the Version object for the Item that has the
|
||||
* itemUuid param as UUID
|
||||
* @throws SQLException If something goes wrong
|
||||
*/
|
||||
public VersionRest getItemVersion(@Nullable HttpServletRequest request,
|
||||
UUID itemUuid,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) throws SQLException {
|
||||
|
||||
|
||||
Context context = obtainContext();
|
||||
Item item = itemService.find(context, itemUuid);
|
||||
if (item == null) {
|
||||
throw new ResourceNotFoundException("The Item for uuid: " + itemUuid + " couldn't be found");
|
||||
}
|
||||
Version version = versioningService.getVersion(context, item);
|
||||
if (version == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.toRest(version, projection);
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.ReloadableEntity;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by all the rest repository that need to
|
||||
* provide access to the DSpace API model objects corresponding to the REST
|
||||
* resources that it manages
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
* @param <T> the ReloadableEntity type
|
||||
* @param <PK> the primary key type
|
||||
*/
|
||||
public interface ReloadableEntityObjectRepository<T extends ReloadableEntity<PK>,
|
||||
PK extends Serializable> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param id the primary key shared between the rest and dspace api object
|
||||
* @return the dspace api model object related to the specified id
|
||||
* @throws SQLException if a database error occurs
|
||||
*/
|
||||
T findDomainObjectByPk(Context context, PK id) throws SQLException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the class of the primary key
|
||||
*/
|
||||
Class<PK> getPKClass();
|
||||
}
|
@@ -11,11 +11,9 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.dspace.app.rest.Parameter;
|
||||
import org.dspace.app.rest.SearchRestMethod;
|
||||
import org.dspace.app.rest.exception.MissingParameterException;
|
||||
|
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.model.VersionHistoryRest;
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.VersionHistory;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the Repository that takes care of the retrieval of the {@link VersionHistory} object
|
||||
* for a given {@link Version}
|
||||
*/
|
||||
@Component(VersionRest.CATEGORY + "." + VersionRest.NAME + "." + VersionRest.VERSION_HISTORY)
|
||||
public class VersionHistoryLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
/**
|
||||
* This method will retrieve the VersionHistoryRest object from the Version that is found by the associated
|
||||
* versionId parameter
|
||||
* @param request The current request
|
||||
* @param versionId The ID for the Version object
|
||||
* @param optionalPageable The pageable if present
|
||||
* @param projection The current Projection
|
||||
* @return The VersionHistoryRest object that is constructed from the VersionHistory object that
|
||||
* is linked to the Version found by the versionId parameter
|
||||
* @throws SQLException If something goes wrong
|
||||
*/
|
||||
public VersionHistoryRest getVersionHistory(@Nullable HttpServletRequest request,
|
||||
Integer versionId,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) throws SQLException {
|
||||
|
||||
Context context = obtainContext();
|
||||
Version version = versioningService.getVersion(context, versionId);
|
||||
if (version == null) {
|
||||
throw new ResourceNotFoundException("The version with ID: " + versionId + " couldn't be found");
|
||||
}
|
||||
VersionHistory versionHistory = version.getVersionHistory();
|
||||
if (versionHistory == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.toRest(versionHistory, projection);
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
import org.dspace.app.rest.model.VersionHistoryRest;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.versioning.VersionHistory;
|
||||
import org.dspace.versioning.service.VersionHistoryService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Repository for the operations on the {@link VersionHistoryRest} endpoints
|
||||
*/
|
||||
@Component(VersionHistoryRest.CATEGORY + "." + VersionHistoryRest.NAME)
|
||||
public class VersionHistoryRestRepository extends DSpaceRestRepository<VersionHistoryRest, Integer> {
|
||||
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(VersionHistoryRestRepository.class);
|
||||
|
||||
@Autowired
|
||||
private VersionHistoryService versionHistoryService;
|
||||
|
||||
@Autowired
|
||||
private ConverterService converterService;
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasPermission(#id, 'VERSIONHISTORY', 'READ')")
|
||||
public VersionHistoryRest findOne(Context context, Integer id) {
|
||||
try {
|
||||
VersionHistory versionHistory = versionHistoryService.find(context, id);
|
||||
if (versionHistory == null) {
|
||||
throw new ResourceNotFoundException("Couldn't find version for id: " + id);
|
||||
}
|
||||
return converterService.toRest(versionHistory, utils.obtainProjection());
|
||||
} catch (SQLException e) {
|
||||
log.error("Something with wrong getting version with id:" + id, e);
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<VersionHistoryRest> findAll(Context context, Pageable pageable) {
|
||||
throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<VersionHistoryRest> getDomainClass() {
|
||||
return VersionHistoryRest.class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.model.ItemRest;
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This Repository takes care of the retrieval of the {@link org.dspace.content.Item} objects
|
||||
* for a given {@link Version}
|
||||
*/
|
||||
@Component(VersionRest.CATEGORY + "." + VersionRest.NAME + "." + VersionRest.ITEM)
|
||||
public class VersionItemLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
/**
|
||||
* This method will return the ItemRest object constructed from the Item object which is found in the Version
|
||||
* that will be found through the versionId parameter
|
||||
* @param request The current request
|
||||
* @param versionId The ID for the Version to be used
|
||||
* @param optionalPageable The pageable if present
|
||||
* @param projection The current Projection
|
||||
* @return The ItemRest object that is relevant for the Version
|
||||
* @throws SQLException If something goes wrong
|
||||
*/
|
||||
public ItemRest getVersionItem(@Nullable HttpServletRequest request,
|
||||
Integer versionId,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) throws SQLException {
|
||||
|
||||
|
||||
Context context = obtainContext();
|
||||
Version version = versioningService.getVersion(context, versionId);
|
||||
if (version == null) {
|
||||
throw new ResourceNotFoundException("The version with ID: " + versionId + " couldn't be found");
|
||||
}
|
||||
Item item = version.getItem();
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
return converter.toRest(item, projection);
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the Repository that takes care of the operations on the {@link VersionRest} objects
|
||||
*/
|
||||
@Component(VersionRest.CATEGORY + "." + VersionRest.NAME)
|
||||
public class VersionRestRepository extends DSpaceRestRepository<VersionRest, Integer> {
|
||||
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(VersionRestRepository.class);
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
@Autowired
|
||||
private ConverterService converterService;
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasPermission(#id, 'VERSION', 'READ')")
|
||||
public VersionRest findOne(Context context, Integer id) {
|
||||
try {
|
||||
Version version = versioningService.getVersion(context, id);
|
||||
if (version == null) {
|
||||
throw new ResourceNotFoundException("Couldn't find version for id: " + id);
|
||||
}
|
||||
return converterService.toRest(version, utils.obtainProjection());
|
||||
} catch (SQLException e) {
|
||||
log.error("Something with wrong getting version with id:" + id, e);
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<VersionRest> findAll(Context context, Pageable pageable) {
|
||||
throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<VersionRest> getDomainClass() {
|
||||
return VersionRest.class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.model.VersionHistoryRest;
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.VersionHistory;
|
||||
import org.dspace.versioning.service.VersionHistoryService;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This is the Repository that takes care of the retrieval of the {@link Version} objects for a given
|
||||
* {@link VersionHistory}
|
||||
*/
|
||||
@Component(VersionHistoryRest.CATEGORY + "." + VersionHistoryRest.NAME + "." + VersionHistoryRest.VERSIONS)
|
||||
public class VersionsLinkRepository extends AbstractDSpaceRestRepository
|
||||
implements LinkRestRepository {
|
||||
|
||||
@Autowired
|
||||
private VersionHistoryService versionHistoryService;
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
/**
|
||||
* This method will return a page of VersionRest objects found through the VersionHistory object that is resolved
|
||||
* from the versionHistoryId parameter
|
||||
* @param request The current request
|
||||
* @param versionHistoryId The ID for the VersionHistory to be used
|
||||
* @param optionalPageable The pageable if present
|
||||
* @param projection The current Projection
|
||||
* @return The page containing relevant VersionRest objects
|
||||
* @throws SQLException If something goes wrong
|
||||
*/
|
||||
public Page<VersionRest> getVersions(@Nullable HttpServletRequest request,
|
||||
Integer versionHistoryId,
|
||||
@Nullable Pageable optionalPageable,
|
||||
Projection projection) throws SQLException {
|
||||
|
||||
Context context = obtainContext();
|
||||
VersionHistory versionHistory = versionHistoryService.find(context, versionHistoryId);
|
||||
if (versionHistory == null) {
|
||||
throw new ResourceNotFoundException("The versionHistory with ID: " + versionHistoryId +
|
||||
" couldn't be found");
|
||||
}
|
||||
List<Version> versions = versioningService.getVersionsByHistory(context, versionHistory);
|
||||
Pageable pageable = optionalPageable != null ? optionalPageable : new PageRequest(0, 20);
|
||||
return converter.toRestPage(utils.getPage(versions, pageable), projection);
|
||||
}
|
||||
}
|
@@ -34,9 +34,12 @@ import org.dspace.app.util.SubmissionConfigReader;
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.app.util.SubmissionStepConfig;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.service.BitstreamFormatService;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.EPersonServiceImpl;
|
||||
@@ -56,6 +59,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@@ -97,6 +101,9 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository<WorkflowIte
|
||||
@Autowired
|
||||
WorkflowService<XmlWorkflowItem> wfs;
|
||||
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
ClaimedTaskService claimedTaskService;
|
||||
|
||||
@@ -188,6 +195,7 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository<WorkflowIte
|
||||
@Override
|
||||
public WorkflowItemRest upload(HttpServletRequest request, String apiCategory, String model, Integer id,
|
||||
MultipartFile file) throws SQLException {
|
||||
|
||||
Context context = obtainContext();
|
||||
WorkflowItemRest wsi = findOne(context, id);
|
||||
XmlWorkflowItem source = wis.find(context, id);
|
||||
@@ -353,4 +361,33 @@ public class WorkflowItemRestRepository extends DSpaceRestRepository<WorkflowIte
|
||||
+ "#checkIfEditMetadataAllowedInCurrentStep trying to retrieve workflow configuration from config", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a search method that will return the WorkflowItemRest object found through the UUID of an item. It'll
|
||||
* find the Item through the given UUID and try to resolve the WorkflowItem relevant for that item and return it.
|
||||
* It'll return a 401/403 if the current user isn't allowed to view the WorkflowItem.
|
||||
* It'll return a 204 if nothing was found
|
||||
* @param itemUuid The UUID for the Item to be used
|
||||
* @param pageable The pageable if present
|
||||
* @return The resulting WorkflowItemRest object
|
||||
*/
|
||||
@SearchRestMethod(name = "item")
|
||||
public WorkflowItemRest findByItemUuid(@Parameter(value = "uuid", required = true) UUID itemUuid,
|
||||
Pageable pageable) {
|
||||
try {
|
||||
Context context = obtainContext();
|
||||
Item item = itemService.find(context, itemUuid);
|
||||
XmlWorkflowItem xmlWorkflowItem = wis.findByItem(context, item);
|
||||
if (xmlWorkflowItem == null) {
|
||||
return null;
|
||||
}
|
||||
if (!authorizeService.authorizeActionBoolean(context, xmlWorkflowItem.getItem(), Constants.READ)) {
|
||||
throw new AccessDeniedException("The current user does not have rights to view the WorkflowItem");
|
||||
}
|
||||
return converter.toRest(xmlWorkflowItem, utils.obtainProjection());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -41,7 +41,9 @@ import org.dspace.app.util.SubmissionConfigReader;
|
||||
import org.dspace.app.util.SubmissionConfigReaderException;
|
||||
import org.dspace.app.util.SubmissionStepConfig;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.WorkspaceItem;
|
||||
import org.dspace.content.service.BitstreamFormatService;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
@@ -65,6 +67,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.json.patch.PatchException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@@ -74,7 +78,8 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component(WorkspaceItemRest.CATEGORY + "." + WorkspaceItemRest.NAME)
|
||||
public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceItemRest, Integer> {
|
||||
public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceItemRest, Integer>
|
||||
implements ReloadableEntityObjectRepository<WorkspaceItem, Integer> {
|
||||
|
||||
public static final String OPERATION_PATH_SECTIONS = "sections";
|
||||
|
||||
@@ -110,6 +115,9 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
@Autowired
|
||||
CollectionService collectionService;
|
||||
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private UriListHandlerService uriListHandlerService;
|
||||
|
||||
@@ -119,7 +127,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
submissionConfigReader = new SubmissionConfigReader();
|
||||
}
|
||||
|
||||
//TODO @PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'READ')")
|
||||
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'READ')")
|
||||
@Override
|
||||
public WorkspaceItemRest findOne(Context context, Integer id) {
|
||||
WorkspaceItem witem = null;
|
||||
@@ -134,7 +142,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
return converter.toRest(witem, utils.obtainProjection());
|
||||
}
|
||||
|
||||
//TODO @PreAuthorize("hasAuthority('ADMIN')")
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
@Override
|
||||
public Page<WorkspaceItemRest> findAll(Context context, Pageable pageable) {
|
||||
try {
|
||||
@@ -147,7 +155,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
}
|
||||
}
|
||||
|
||||
//TODO @PreAuthorize("hasPermission(#submitterID, 'EPERSON', 'READ')")
|
||||
@PreAuthorize("hasPermission(#submitterID, 'EPERSON', 'READ')")
|
||||
@SearchRestMethod(name = "findBySubmitter")
|
||||
public Page<WorkspaceItemRest> findBySubmitter(@Parameter(value = "uuid", required = true) UUID submitterID,
|
||||
Pageable pageable) {
|
||||
@@ -213,7 +221,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
return WorkspaceItemRest.class;
|
||||
}
|
||||
|
||||
//TODO @PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'WRITE')")
|
||||
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'WRITE')")
|
||||
@Override
|
||||
public WorkspaceItemRest upload(HttpServletRequest request, String apiCategory, String model, Integer id,
|
||||
MultipartFile file) throws SQLException {
|
||||
@@ -263,7 +271,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
return wsi;
|
||||
}
|
||||
|
||||
//TODO @PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'WRITE')")
|
||||
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'WRITE')")
|
||||
@Override
|
||||
public void patch(Context context, HttpServletRequest request, String apiCategory, String model, Integer id,
|
||||
Patch patch) throws SQLException, AuthorizeException {
|
||||
@@ -326,7 +334,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
}
|
||||
}
|
||||
|
||||
//TODO @PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'DELETE')")
|
||||
@PreAuthorize("hasPermission(#id, 'WORKSPACEITEM', 'DELETE')")
|
||||
@Override
|
||||
protected void delete(Context context, Integer id) throws AuthorizeException {
|
||||
WorkspaceItem witem = null;
|
||||
@@ -496,5 +504,41 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository<WorkspaceI
|
||||
return converter.toRest(workspaceItem, utils.obtainProjection());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a search method that will return the WorkspaceItemRest object found through the UUID of an item. It'll
|
||||
* find the Item through the given UUID and try to resolve the WorkspaceItem relevant for that item and return it.
|
||||
* It'll return a 401/403 if the current user isn't allowed to view the WorkspaceItem.
|
||||
* It'll return a 204 if nothing was found
|
||||
* @param itemUuid The UUID for the Item to be used
|
||||
* @param pageable The pageable if present
|
||||
* @return The resulting WorkspaceItem object
|
||||
*/
|
||||
@SearchRestMethod(name = "item")
|
||||
public WorkspaceItemRest findByItemUuid(@Parameter(value = "uuid", required = true) UUID itemUuid,
|
||||
Pageable pageable) {
|
||||
try {
|
||||
Context context = obtainContext();
|
||||
Item item = itemService.find(context, itemUuid);
|
||||
WorkspaceItem workspaceItem = wis.findByItem(context, item);
|
||||
if (workspaceItem == null) {
|
||||
return null;
|
||||
}
|
||||
if (!authorizeService.authorizeActionBoolean(context, workspaceItem.getItem(), Constants.READ)) {
|
||||
throw new AccessDeniedException("The current user does not have rights to view the WorkflowItem");
|
||||
}
|
||||
return converter.toRest(workspaceItem, utils.obtainProjection());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkspaceItem findDomainObjectByPk(Context context, Integer id) throws SQLException {
|
||||
return wis.find(context, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Integer> getPKClass() {
|
||||
return Integer.class;
|
||||
}
|
||||
}
|
||||
|
@@ -15,7 +15,6 @@ import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
@@ -45,7 +45,7 @@ public class CustomLogoutHandler implements LogoutHandler {
|
||||
Authentication authentication) {
|
||||
try {
|
||||
Context context = ContextUtil.obtainContext(httpServletRequest);
|
||||
restAuthenticationService.invalidateAuthenticationData(httpServletRequest, context);
|
||||
restAuthenticationService.invalidateAuthenticationData(httpServletRequest, httpServletResponse, context);
|
||||
context.commit();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.rest.authorization.AuthorizationRestUtil;
|
||||
import org.dspace.app.rest.model.AuthorizationRest;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.services.model.Request;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link RestPermissionEvaluatorPlugin} class that evaluate READ permissions for an Authorization
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
public class ReadAuthorizationPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ReadAuthorizationPermissionEvaluatorPlugin.class);
|
||||
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private RequestService requestService;
|
||||
|
||||
@Autowired
|
||||
private AuthorizationRestUtil authorizationRestUtil;
|
||||
|
||||
@Override
|
||||
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||
DSpaceRestPermission permission) {
|
||||
|
||||
DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission);
|
||||
|
||||
if (!DSpaceRestPermission.READ.equals(restPermission)
|
||||
|| !StringUtils.equalsIgnoreCase(targetType, AuthorizationRest.NAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Request request = requestService.getCurrentRequest();
|
||||
Context context = ContextUtil.obtainContext(request.getServletRequest());
|
||||
try {
|
||||
// admin can always access
|
||||
if (authorizeService.isAdmin(context)) {
|
||||
return true;
|
||||
}
|
||||
EPerson ePerson = authorizationRestUtil.getEperson(context, targetId.toString());
|
||||
EPerson currUser = context.getCurrentUser();
|
||||
|
||||
if (ePerson == null) {
|
||||
// everyone can check authorization for the anonymous user
|
||||
return true;
|
||||
} else {
|
||||
// anonymous user
|
||||
if (currUser != null && currUser.getID().equals(ePerson.getID())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.app.rest.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -29,9 +28,9 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* {@link RestPermissionEvaluatorPlugin} class that evaluate ADMIN permissions over a Resource Policy
|
||||
*
|
||||
*
|
||||
* @author Mykhaylo Boychuk - (4Science.it)
|
||||
*/
|
||||
@Component
|
||||
|
@@ -26,13 +26,14 @@ import org.springframework.stereotype.Service;
|
||||
public interface RestAuthenticationService {
|
||||
|
||||
void addAuthenticationDataForUser(HttpServletRequest request, HttpServletResponse response,
|
||||
DSpaceAuthentication authentication) throws IOException;
|
||||
DSpaceAuthentication authentication, boolean addCookie) throws IOException;
|
||||
|
||||
EPerson getAuthenticatedEPerson(HttpServletRequest request, Context context);
|
||||
|
||||
boolean hasAuthenticationData(HttpServletRequest request);
|
||||
|
||||
void invalidateAuthenticationData(HttpServletRequest request, Context context) throws Exception;
|
||||
void invalidateAuthenticationData(HttpServletRequest request, HttpServletResponse response, Context context)
|
||||
throws Exception;
|
||||
|
||||
AuthenticationService getAuthenticationService();
|
||||
|
||||
@@ -44,4 +45,6 @@ public interface RestAuthenticationService {
|
||||
*/
|
||||
String getWwwAuthenticateHeaderValue(HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
void invalidateAuthenticationCookie(HttpServletResponse res);
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* This class will filter shibboleth requests to try and authenticate them
|
||||
*
|
||||
* @author Giuseppe Digilio (giuseppe dot digilio at 4science dot it)
|
||||
*/
|
||||
public class ShibbolethAuthenticationFilter extends StatelessLoginFilter {
|
||||
|
||||
public ShibbolethAuthenticationFilter(String url, AuthenticationManager authenticationManager,
|
||||
RestAuthenticationService restAuthenticationService) {
|
||||
super(url, authenticationManager, restAuthenticationService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest req,
|
||||
HttpServletResponse res) throws AuthenticationException {
|
||||
|
||||
return authenticationManager.authenticate(
|
||||
new DSpaceAuthentication(null, null, new ArrayList<>())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest req,
|
||||
HttpServletResponse res,
|
||||
FilterChain chain,
|
||||
Authentication auth) throws IOException, ServletException {
|
||||
|
||||
DSpaceAuthentication dSpaceAuthentication = (DSpaceAuthentication) auth;
|
||||
restAuthenticationService.addAuthenticationDataForUser(req, res, dSpaceAuthentication, true);
|
||||
chain.doFilter(req, res);
|
||||
}
|
||||
|
||||
}
|
@@ -61,6 +61,7 @@ public class StatelessAuthenticationFilter extends BasicAuthenticationFilter {
|
||||
Authentication authentication = getAuthentication(req);
|
||||
if (authentication != null) {
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
restAuthenticationService.invalidateAuthenticationCookie(res);
|
||||
}
|
||||
|
||||
chain.doFilter(req, res);
|
||||
|
@@ -28,9 +28,9 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
*/
|
||||
public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
private AuthenticationManager authenticationManager;
|
||||
protected AuthenticationManager authenticationManager;
|
||||
|
||||
private RestAuthenticationService restAuthenticationService;
|
||||
protected RestAuthenticationService restAuthenticationService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
@@ -63,7 +63,7 @@ public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter
|
||||
Authentication auth) throws IOException, ServletException {
|
||||
|
||||
DSpaceAuthentication dSpaceAuthentication = (DSpaceAuthentication) auth;
|
||||
restAuthenticationService.addAuthenticationDataForUser(req, res, dSpaceAuthentication);
|
||||
restAuthenticationService.addAuthenticationDataForUser(req, res, dSpaceAuthentication, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.rest.model.VersionHistoryRest;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.services.model.Request;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This class acts as a PermissionEvaluator to decide whether a given request to a Versioning endpoint is allowed to
|
||||
* pass through or not
|
||||
*/
|
||||
@Component
|
||||
public class VersionHistoryRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(VersionHistoryRestPermissionEvaluatorPlugin.class);
|
||||
|
||||
@Autowired
|
||||
private RequestService requestService;
|
||||
|
||||
@Autowired
|
||||
private AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||
DSpaceRestPermission restPermission) {
|
||||
|
||||
|
||||
if (!StringUtils.equalsIgnoreCase(targetType, VersionHistoryRest.NAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Request request = requestService.getCurrentRequest();
|
||||
Context context = ContextUtil.obtainContext(request.getServletRequest());
|
||||
|
||||
try {
|
||||
if (configurationService.getBooleanProperty("versioning.item.history.view.admin")
|
||||
&& !authorizeService.isAdmin(context)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.rest.model.VersionRest;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.services.model.Request;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This class acts as a PermissionEvaluator to decide whether a given request to a Versioning endpoint is allowed to
|
||||
* pass through or not
|
||||
*/
|
||||
@Component
|
||||
public class VersionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(VersionRestPermissionEvaluatorPlugin.class);
|
||||
|
||||
@Autowired
|
||||
private RequestService requestService;
|
||||
|
||||
@Autowired
|
||||
private AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||
DSpaceRestPermission restPermission) {
|
||||
|
||||
|
||||
if (!StringUtils.equalsIgnoreCase(targetType, VersionRest.NAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Request request = requestService.getCurrentRequest();
|
||||
Context context = ContextUtil.obtainContext(request.getServletRequest());
|
||||
|
||||
try {
|
||||
int versionId = Integer.parseInt(targetId.toString());
|
||||
if (configurationService.getBooleanProperty("versioning.item.history.view.admin")
|
||||
&& !authorizeService.isAdmin(context)) {
|
||||
return false;
|
||||
}
|
||||
Version version = versioningService.getVersion(context, versionId);
|
||||
if (version == null) {
|
||||
return true;
|
||||
}
|
||||
if (authorizeService.authorizeActionBoolean(context, version.getItem(),
|
||||
restPermission.getDspaceApiActionId())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -109,6 +109,12 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
restAuthenticationService),
|
||||
LogoutFilter.class)
|
||||
|
||||
//Add a filter before our shibboleth endpoints to do the authentication based on the data in the
|
||||
// HTTP request
|
||||
.addFilterBefore(new ShibbolethAuthenticationFilter("/api/authn/shibboleth", authenticationManager(),
|
||||
restAuthenticationService),
|
||||
LogoutFilter.class)
|
||||
|
||||
// Add a custom Token based authentication filter based on the token previously given to the client
|
||||
// before each URL
|
||||
.addFilterBefore(new StatelessAuthenticationFilter(authenticationManager(), restAuthenticationService,
|
||||
|
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.rest.model.WorkspaceItemRest;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.content.WorkspaceItem;
|
||||
import org.dspace.content.service.WorkspaceItemService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.services.model.Request;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* {@link RestPermissionEvaluatorPlugin} class that evaluate READ, WRITE and DELETE permissions over a WorkspaceItem
|
||||
*
|
||||
* @author Mykhaylo Boychuk (mykhaylo.boychuk at 4science.it)
|
||||
*/
|
||||
@Component
|
||||
public class WorkspaceItemRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(WorkspaceItemRestPermissionEvaluatorPlugin.class);
|
||||
|
||||
@Autowired
|
||||
private RequestService requestService;
|
||||
|
||||
@Autowired
|
||||
WorkspaceItemService wis;
|
||||
|
||||
@Override
|
||||
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||
DSpaceRestPermission permission) {
|
||||
|
||||
DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission);
|
||||
if (!DSpaceRestPermission.READ.equals(restPermission)
|
||||
&& !DSpaceRestPermission.WRITE.equals(restPermission)
|
||||
&& !DSpaceRestPermission.DELETE.equals(restPermission)) {
|
||||
return false;
|
||||
}
|
||||
if (!StringUtils.equalsIgnoreCase(targetType, WorkspaceItemRest.NAME)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Request request = requestService.getCurrentRequest();
|
||||
Context context = ContextUtil.obtainContext(request.getServletRequest());
|
||||
|
||||
EPerson ePerson = null;
|
||||
WorkspaceItem witem = null;
|
||||
try {
|
||||
ePerson = context.getCurrentUser();
|
||||
Integer dsoId = Integer.parseInt(targetId.toString());
|
||||
|
||||
// anonymous user
|
||||
if (ePerson == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
witem = wis.find(context, dsoId);
|
||||
|
||||
// If the dso is null then we give permission so we can throw another status
|
||||
// code instead
|
||||
if (witem == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (witem.getSubmitter() != null) {
|
||||
if (witem.getSubmitter().getID().equals(ePerson.getID())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -12,6 +12,7 @@ import java.sql.SQLException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -37,11 +38,13 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
* @author Frederic Van Reet (frederic dot vanreet at atmire dot com)
|
||||
* @author Tom Desair (tom dot desair at atmire dot com)
|
||||
* @author Giuseppe Digilio (giuseppe dot digilio at 4science dot it)
|
||||
*/
|
||||
@Component
|
||||
public class JWTTokenRestAuthenticationServiceImpl implements RestAuthenticationService, InitializingBean {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(RestAuthenticationService.class);
|
||||
private static final String AUTHORIZATION_COOKIE = "Authorization-cookie";
|
||||
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
private static final String AUTHORIZATION_TYPE = "Bearer";
|
||||
|
||||
@@ -61,7 +64,7 @@ public class JWTTokenRestAuthenticationServiceImpl implements RestAuthentication
|
||||
|
||||
@Override
|
||||
public void addAuthenticationDataForUser(HttpServletRequest request, HttpServletResponse response,
|
||||
DSpaceAuthentication authentication) throws IOException {
|
||||
DSpaceAuthentication authentication, boolean addCookie) throws IOException {
|
||||
try {
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
context.setCurrentUser(ePersonService.findByEmail(context, authentication.getName()));
|
||||
@@ -71,7 +74,7 @@ public class JWTTokenRestAuthenticationServiceImpl implements RestAuthentication
|
||||
String token = jwtTokenHandler.createTokenForEPerson(context, request,
|
||||
authentication.getPreviousLoginDate(), groups);
|
||||
|
||||
addTokenToResponse(response, token);
|
||||
addTokenToResponse(response, token, addCookie);
|
||||
context.commit();
|
||||
|
||||
} catch (JOSEException e) {
|
||||
@@ -99,15 +102,26 @@ public class JWTTokenRestAuthenticationServiceImpl implements RestAuthentication
|
||||
|
||||
@Override
|
||||
public boolean hasAuthenticationData(HttpServletRequest request) {
|
||||
return StringUtils.isNotBlank(request.getHeader(AUTHORIZATION_HEADER));
|
||||
return StringUtils.isNotBlank(request.getHeader(AUTHORIZATION_HEADER))
|
||||
|| StringUtils.isNotBlank(getAuthorizationCookie(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticationData(HttpServletRequest request, Context context) throws Exception {
|
||||
public void invalidateAuthenticationData(HttpServletRequest request, HttpServletResponse response,
|
||||
Context context) throws Exception {
|
||||
String token = getToken(request);
|
||||
invalidateAuthenticationCookie(response);
|
||||
jwtTokenHandler.invalidateToken(token, request, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateAuthenticationCookie(HttpServletResponse response) {
|
||||
Cookie cookie = new Cookie(AUTHORIZATION_COOKIE, "");
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationService getAuthenticationService() {
|
||||
return authenticationService;
|
||||
@@ -140,18 +154,42 @@ public class JWTTokenRestAuthenticationServiceImpl implements RestAuthentication
|
||||
return wwwAuthenticate.toString();
|
||||
}
|
||||
|
||||
private void addTokenToResponse(final HttpServletResponse response, final String token) throws IOException {
|
||||
private void addTokenToResponse(final HttpServletResponse response, final String token, final Boolean addCookie)
|
||||
throws IOException {
|
||||
// we need authentication cookies because Shibboleth can't use the authentication headers due to the redirects
|
||||
if (addCookie) {
|
||||
Cookie cookie = new Cookie(AUTHORIZATION_COOKIE, token);
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setSecure(true);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
response.setHeader(AUTHORIZATION_HEADER, String.format("%s %s", AUTHORIZATION_TYPE, token));
|
||||
}
|
||||
|
||||
private String getToken(HttpServletRequest request) {
|
||||
String tokenValue = null;
|
||||
String authHeader = request.getHeader(AUTHORIZATION_HEADER);
|
||||
String authCookie = getAuthorizationCookie(request);
|
||||
if (StringUtils.isNotBlank(authHeader)) {
|
||||
String tokenValue = authHeader.replace(AUTHORIZATION_TYPE, "").trim();
|
||||
return tokenValue;
|
||||
} else {
|
||||
return null;
|
||||
tokenValue = authHeader.replace(AUTHORIZATION_TYPE, "").trim();
|
||||
} else if (StringUtils.isNotBlank(authCookie)) {
|
||||
tokenValue = authCookie;
|
||||
}
|
||||
|
||||
return tokenValue;
|
||||
}
|
||||
|
||||
private String getAuthorizationCookie(HttpServletRequest request) {
|
||||
String authCookie = "";
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals(AUTHORIZATION_COOKIE) && StringUtils.isNotEmpty(cookie.getValue())) {
|
||||
authCookie = cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return authCookie;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.app.rest.submit;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -141,7 +140,7 @@ public class SubmissionService {
|
||||
* Build the rest representation of a bitstream as used in the upload section
|
||||
* ({@link DataUpload}. It contains all its metadata and the list of applied
|
||||
* access conditions (@link {@link UploadBitstreamAccessConditionDTO}
|
||||
*
|
||||
*
|
||||
* @param configurationService the DSpace ConfigurationService
|
||||
* @param source the bitstream to translate in its rest submission
|
||||
* representation
|
||||
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.app.rest.submit.factory.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
@@ -28,7 +28,7 @@ public class RegexUtils {
|
||||
* identifier (digits or uuid)
|
||||
*/
|
||||
public static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_STRING_VERSION_STRONG = "/{id:^(?!^\\d+$)" +
|
||||
"(?!^[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}$)[\\w+\\-]+$+}";
|
||||
"(?!^[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}$)[\\w+\\-\\.]+$+}";
|
||||
|
||||
/**
|
||||
* Regular expression in the request mapping to accept number as identifier
|
||||
|
@@ -21,6 +21,7 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.SQLException;
|
||||
@@ -55,6 +56,7 @@ import org.dspace.app.rest.model.ProcessRest;
|
||||
import org.dspace.app.rest.model.ResourcePolicyRest;
|
||||
import org.dspace.app.rest.model.RestAddressableModel;
|
||||
import org.dspace.app.rest.model.RestModel;
|
||||
import org.dspace.app.rest.model.VersionHistoryRest;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceResource;
|
||||
import org.dspace.app.rest.model.hateoas.EmbeddedPage;
|
||||
import org.dspace.app.rest.model.hateoas.HALResource;
|
||||
@@ -64,18 +66,22 @@ import org.dspace.app.rest.projection.EmbedRelsProjection;
|
||||
import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.app.rest.repository.DSpaceRestRepository;
|
||||
import org.dspace.app.rest.repository.LinkRestRepository;
|
||||
import org.dspace.app.rest.repository.ReloadableEntityObjectRepository;
|
||||
import org.dspace.content.BitstreamFormat;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.service.BitstreamFormatService;
|
||||
import org.dspace.content.service.DSpaceObjectService;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.RequestService;
|
||||
import org.dspace.util.UUIDUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@@ -110,6 +116,10 @@ public class Utils {
|
||||
@Autowired
|
||||
RequestService requestService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("defaultConversionService")
|
||||
ConversionService conversionService;
|
||||
|
||||
@Autowired(required = true)
|
||||
private List<DSpaceObjectService<? extends DSpaceObject>> dSpaceObjectServices;
|
||||
|
||||
@@ -119,6 +129,9 @@ public class Utils {
|
||||
@Autowired
|
||||
private ConverterService converter;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
/** Cache to support fast lookups of LinkRest method annotation information. */
|
||||
private Map<Method, Optional<LinkRest>> linkAnnotationForMethod = new HashMap<>();
|
||||
|
||||
@@ -168,12 +181,32 @@ public class Utils {
|
||||
.withRel(rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the {@link DSpaceRestRepository} for the specified category and model in the plural form as used in the endpoints.
|
||||
* If the model is available in its singular form use {@link #getResourceRepositoryByCategoryAndModel(String, String)}
|
||||
*
|
||||
* @param apiCategory
|
||||
* @param modelPlural
|
||||
* @return
|
||||
*/
|
||||
public DSpaceRestRepository getResourceRepository(String apiCategory, String modelPlural) {
|
||||
String model = makeSingular(modelPlural);
|
||||
return getResourceRepositoryByCategoryAndModel(apiCategory, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the {@link DSpaceRestRepository} for the specified category and model. The model is in the singular form
|
||||
* as returned by the {@link RestAddressableModel#getType()} method
|
||||
*
|
||||
* @param apiCategory
|
||||
* @param modelSingular
|
||||
* @return
|
||||
*/
|
||||
public DSpaceRestRepository getResourceRepositoryByCategoryAndModel(String apiCategory, String modelSingular) {
|
||||
try {
|
||||
return applicationContext.getBean(apiCategory + "." + model, DSpaceRestRepository.class);
|
||||
return applicationContext.getBean(apiCategory + "." + modelSingular, DSpaceRestRepository.class);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
throw new RepositoryNotFoundException(apiCategory, model);
|
||||
throw new RepositoryNotFoundException(apiCategory, modelSingular);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +229,9 @@ public class Utils {
|
||||
if (StringUtils.equals(modelPlural, "processes")) {
|
||||
return ProcessRest.NAME;
|
||||
}
|
||||
if (StringUtils.equals(modelPlural, "versionhistories")) {
|
||||
return VersionHistoryRest.NAME;
|
||||
}
|
||||
return modelPlural.replaceAll("s$", "");
|
||||
}
|
||||
|
||||
@@ -784,4 +820,89 @@ public class Utils {
|
||||
}
|
||||
return contentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the input string in the primary key class according to the repository interface
|
||||
*
|
||||
* @param repository
|
||||
* @param pkStr
|
||||
* @return
|
||||
*/
|
||||
public Serializable castToPKClass(ReloadableEntityObjectRepository repository, String pkStr) {
|
||||
return (Serializable) conversionService.convert(pkStr, repository.getPKClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dspace api model object corresponding to the provided, not null, rest object. This only works when the
|
||||
* rest object is supported by a {@link DSpaceRestRepository} that also implement the
|
||||
* {@link ReloadableEntityObjectRepository} interface. If this is not the case the method will throw an
|
||||
* IllegalArgumentException
|
||||
*
|
||||
* @param context
|
||||
* the DSpace Context
|
||||
* @param restObj
|
||||
* the not null rest object. If null the method will throws an {@link IllegalArgumentException}
|
||||
* @return the dspace api model object corresponding to the provided, not null, rest object
|
||||
* @throws IllegalArgumentException
|
||||
* if the restObj is not supported by a {@link DSpaceRestRepository} that also implement the
|
||||
* {@link ReloadableEntityObjectRepository} interface
|
||||
* @throws SQLException
|
||||
* if a database error occur
|
||||
*/
|
||||
public Object getDSpaceAPIObjectFromRest(Context context, BaseObjectRest restObj)
|
||||
throws IllegalArgumentException, SQLException {
|
||||
DSpaceRestRepository repository = getResourceRepositoryByCategoryAndModel(restObj.getCategory(),
|
||||
restObj.getType());
|
||||
Serializable pk = castToPKClass((ReloadableEntityObjectRepository) repository, restObj.getId().toString());
|
||||
return ((ReloadableEntityObjectRepository) repository).findDomainObjectByPk(context, pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rest object associated with the specified URI
|
||||
*
|
||||
* @param context the DSpace context
|
||||
* @param uri the uri of a {@link BaseObjectRest}
|
||||
* @return the {@link BaseObjectRest} identified by the provided uri
|
||||
* @throws SQLException if a database error occur
|
||||
* @throws IllegalArgumentException if the uri is not valid
|
||||
*/
|
||||
public BaseObjectRest getBaseObjectRestFromUri(Context context, String uri) throws SQLException {
|
||||
String dspaceUrl = configurationService.getProperty("dspace.server.url");
|
||||
// first check if the uri could be valid
|
||||
if (!StringUtils.startsWith(uri, dspaceUrl)) {
|
||||
throw new IllegalArgumentException("the supplied uri is not valid: " + uri);
|
||||
}
|
||||
// extract from the uri the category, model and id components
|
||||
// they start after the dspaceUrl/api/{apiCategory}/{apiModel}/{id}
|
||||
String[] uriParts = uri.substring(dspaceUrl.length() + (dspaceUrl.endsWith("/") ? 0 : 1) + "api/".length())
|
||||
.split("/", 3);
|
||||
if (uriParts.length != 3) {
|
||||
throw new IllegalArgumentException("the supplied uri is not valid: " + uri);
|
||||
}
|
||||
|
||||
DSpaceRestRepository repository;
|
||||
try {
|
||||
repository = getResourceRepository(uriParts[0], uriParts[1]);
|
||||
if (!(repository instanceof ReloadableEntityObjectRepository)) {
|
||||
throw new IllegalArgumentException("the supplied uri is not valid: " + uri);
|
||||
}
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
throw new IllegalArgumentException("the supplied uri is not valid: " + uri, e);
|
||||
}
|
||||
|
||||
Serializable pk;
|
||||
try {
|
||||
// cast the string id in the uriParts to the real pk class
|
||||
pk = castToPKClass((ReloadableEntityObjectRepository) repository, uriParts[2]);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("the supplied uri is not valid: " + uri, e);
|
||||
}
|
||||
try {
|
||||
// disable the security as we only need to retrieve the object to further process the authorization
|
||||
context.turnOffAuthorisationSystem();
|
||||
return (BaseObjectRest) repository.findOne(context, pk);
|
||||
} finally {
|
||||
context.restoreAuthSystemState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,6 @@ import com.lyncode.xoai.dataprovider.services.api.ResourceResolver;
|
||||
import com.lyncode.xoai.dataprovider.services.impl.BaseDateProvider;
|
||||
import com.lyncode.xoai.dataprovider.xml.xoaiconfig.Configuration;
|
||||
import com.lyncode.xoai.dataprovider.xml.xoaiconfig.ContextConfiguration;
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
@@ -39,7 +38,6 @@ import org.dspace.xoai.services.api.EarliestDateResolver;
|
||||
import org.dspace.xoai.services.api.cache.XOAICacheService;
|
||||
import org.dspace.xoai.services.api.config.XOAIManagerResolver;
|
||||
import org.dspace.xoai.services.api.xoai.DSpaceFilterResolver;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@@ -12,10 +12,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@@ -15,13 +15,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.builder.ItemBuilder;
|
||||
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.junit.Before;
|
||||
|
@@ -21,6 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.Base64;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.dspace.app.rest.builder.GroupBuilder;
|
||||
import org.dspace.app.rest.matcher.AuthenticationStatusMatcher;
|
||||
@@ -40,6 +41,7 @@ import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
|
||||
*
|
||||
* @author Frederic Van Reet (frederic dot vanreet at atmire dot com)
|
||||
* @author Tom Desair (tom dot desair at atmire dot com)
|
||||
* @author Giuseppe Digilio (giuseppe dot digilio at 4science dot it)
|
||||
*/
|
||||
public class AuthenticationRestControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@@ -48,6 +50,9 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
|
||||
public static final String[] PASS_ONLY = {"org.dspace.authenticate.PasswordAuthentication"};
|
||||
public static final String[] SHIB_ONLY = {"org.dspace.authenticate.ShibAuthentication"};
|
||||
public static final String[] SHIB_AND_PASS =
|
||||
{"org.dspace.authenticate.ShibAuthentication",
|
||||
"org.dspace.authenticate.PasswordAuthentication"};
|
||||
public static final String[] SHIB_AND_IP =
|
||||
{"org.dspace.authenticate.IPAuthentication",
|
||||
"org.dspace.authenticate.ShibAuthentication"};
|
||||
@@ -97,7 +102,43 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(false)))
|
||||
.andExpect(jsonPath("$.type", is("status")));
|
||||
.andExpect(jsonPath("$.type", is("status")))
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"password realm=\"DSpace REST API\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusAuthenticatedWithCookie() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable Shibboleth login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
//Simulate that a shibboleth authentication has happened
|
||||
String token = getClient().perform(post("/api/authn/login")
|
||||
.requestAttr("SHIB-MAIL", eperson.getEmail())
|
||||
.requestAttr("SHIB-SCOPED-AFFILIATION", "faculty;staff"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getResponse().getHeader(AUTHORIZATION_HEADER).replace("Bearer ", "");
|
||||
|
||||
Cookie[] cookies = new Cookie[1];
|
||||
cookies[0] = new Cookie(AUTHORIZATION_COOKIE, token);
|
||||
|
||||
//Check if we are authenticated with a status request with authorization cookie
|
||||
getClient().perform(get("/api/authn/status")
|
||||
.secure(true)
|
||||
.cookie(cookies))
|
||||
.andExpect(status().isOk())
|
||||
//We expect the content type to be "application/hal+json;charset=UTF-8"
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||
.andExpect(jsonPath("$.type", is("status")));
|
||||
|
||||
//Logout
|
||||
getClient(token).perform(get("/api/authn/logout"))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -354,6 +395,108 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShibbolethLoginURLWithDefaultLazyURL() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable Shibboleth login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
|
||||
|
||||
//Create a reviewers group
|
||||
Group reviewersGroup = GroupBuilder.createGroup(context)
|
||||
.withName("Reviewers")
|
||||
.build();
|
||||
|
||||
//Faculty members are assigned to the Reviewers group
|
||||
configurationService.setProperty("authentication-shibboleth.role.faculty", "Reviewers");
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(post("/api/authn/login").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"https://localhost/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShibbolethLoginURLWithServerlURLConteiningPort() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable Shibboleth login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
|
||||
configurationService.setProperty("dspace.server.url", "http://localhost:8080/server");
|
||||
configurationService.setProperty("authentication-shibboleth.lazysession.secure", false);
|
||||
|
||||
//Create a reviewers group
|
||||
Group reviewersGroup = GroupBuilder.createGroup(context)
|
||||
.withName("Reviewers")
|
||||
.build();
|
||||
|
||||
//Faculty members are assigned to the Reviewers group
|
||||
configurationService.setProperty("authentication-shibboleth.role.faculty", "Reviewers");
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(post("/api/authn/login").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"http://localhost:8080/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%3A8080%2Fserver%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShibbolethLoginURLWithConfiguredLazyURL() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable Shibboleth login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
|
||||
configurationService.setProperty("authentication-shibboleth.lazysession.loginurl",
|
||||
"http://shibboleth.org/Shibboleth.sso/Login");
|
||||
|
||||
//Create a reviewers group
|
||||
Group reviewersGroup = GroupBuilder.createGroup(context)
|
||||
.withName("Reviewers")
|
||||
.build();
|
||||
|
||||
//Faculty members are assigned to the Reviewers group
|
||||
configurationService.setProperty("authentication-shibboleth.role.faculty", "Reviewers");
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(post("/api/authn/login").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"http://shibboleth.org/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShibbolethLoginURLWithConfiguredLazyURLWithPort() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable Shibboleth login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
|
||||
configurationService.setProperty("authentication-shibboleth.lazysession.loginurl",
|
||||
"http://shibboleth.org:8080/Shibboleth.sso/Login");
|
||||
|
||||
//Create a reviewers group
|
||||
Group reviewersGroup = GroupBuilder.createGroup(context)
|
||||
.withName("Reviewers")
|
||||
.build();
|
||||
|
||||
//Faculty members are assigned to the Reviewers group
|
||||
configurationService.setProperty("authentication-shibboleth.role.faculty", "Reviewers");
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(post("/api/authn/login").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"http://shibboleth.org:8080/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
// Ignored until an endpoint is added to return all groups
|
||||
@@ -375,7 +518,9 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"/Shibboleth.sso/Login?target=http%3A%2F%2Fmy.uni.edu\""));
|
||||
"location=\"https://localhost/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\""));
|
||||
|
||||
//Simulate that a shibboleth authentication has happened
|
||||
|
||||
@@ -411,7 +556,9 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"ip realm=\"DSpace REST API\", shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"/Shibboleth.sso/Login?target=http%3A%2F%2Fmy.uni.edu\""));
|
||||
"location=\"https://localhost/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\""));
|
||||
|
||||
//Simulate that a shibboleth authentication has happened
|
||||
String token = getClient().perform(post("/api/authn/login")
|
||||
@@ -454,4 +601,164 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
|
||||
EPersonMatcher.matchEPersonWithGroups(eperson.getEmail(), "Anonymous")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShibbolethAndPasswordAuthentication() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable Shibboleth and password login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_AND_PASS);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
//Check if WWW-Authenticate header contains shibboleth and password
|
||||
getClient().perform(get("/api/authn/status").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"https://localhost/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\"" +
|
||||
", password realm=\"DSpace REST API\""));
|
||||
|
||||
//Simulate a password authentication
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
//Check if we have a valid token
|
||||
getClient(token).perform(get("/api/authn/status"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||
.andExpect(jsonPath("$.type", is("status")));
|
||||
|
||||
//Logout
|
||||
getClient(token).perform(get("/api/authn/logout"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
//Check if we are actually logged out
|
||||
getClient(token).perform(get("/api/authn/status"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(false)))
|
||||
.andExpect(jsonPath("$.type", is("status")));
|
||||
|
||||
//Simulate that a shibboleth authentication has happened
|
||||
token = getClient().perform(post("/api/authn/login")
|
||||
.requestAttr("SHIB-MAIL", eperson.getEmail())
|
||||
.requestAttr("SHIB-SCOPED-AFFILIATION", "faculty;staff"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getResponse().getHeader(AUTHORIZATION_HEADER).replace("Bearer ", "");
|
||||
|
||||
//Check if we have a valid token
|
||||
getClient(token).perform(get("/api/authn/status"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||
.andExpect(jsonPath("$.type", is("status")));
|
||||
|
||||
//Logout
|
||||
getClient(token).perform(get("/api/authn/logout"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyPasswordAuthenticationWorks() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable only password login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", PASS_ONLY);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
//Check if WWW-Authenticate header contains only
|
||||
getClient().perform(get("/api/authn/status").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"password realm=\"DSpace REST API\""));
|
||||
|
||||
//Simulate a password authentication
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
//Check if we have a valid token
|
||||
getClient(token).perform(get("/api/authn/status"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.okay", is(true)))
|
||||
.andExpect(jsonPath("$.authenticated", is(true)))
|
||||
.andExpect(jsonPath("$.type", is("status")));
|
||||
|
||||
//Logout
|
||||
getClient(token).perform(get("/api/authn/logout"))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShibbolethAuthenticationDoesNotWorkWithPassOnly() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable only password login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", PASS_ONLY);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
//Check if WWW-Authenticate header contains only password
|
||||
getClient().perform(get("/api/authn/status").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"password realm=\"DSpace REST API\""));
|
||||
|
||||
//Check if a shibboleth authentication fails
|
||||
getClient().perform(post("/api/authn/login")
|
||||
.requestAttr("SHIB-MAIL", eperson.getEmail())
|
||||
.requestAttr("SHIB-SCOPED-AFFILIATION", "faculty;staff"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyShibbolethAuthenticationWorks() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable only Shibboleth login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
//Check if WWW-Authenticate header contains only shibboleth
|
||||
getClient().perform(get("/api/authn/status").header("Referer", "http://my.uni.edu"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("WWW-Authenticate",
|
||||
"shibboleth realm=\"DSpace REST API\", " +
|
||||
"location=\"https://localhost/Shibboleth.sso/Login?" +
|
||||
"target=http%3A%2F%2Flocalhost%2Fapi%2Fauthn%2Fshibboleth%3F" +
|
||||
"redirectUrl%3Dhttp%3A%2F%2Fmy.uni.edu\""));
|
||||
|
||||
//Simulate that a shibboleth authentication has happened
|
||||
String token = getClient().perform(post("/api/authn/login")
|
||||
.requestAttr("SHIB-MAIL", eperson.getEmail())
|
||||
.requestAttr("SHIB-SCOPED-AFFILIATION", "faculty;staff"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getResponse().getHeader(AUTHORIZATION_HEADER);
|
||||
|
||||
//Logout
|
||||
getClient(token).perform(get("/api/authn/logout"))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPasswordAuthenticationDoesNotWorkWithShibOnly() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
//Enable only Shibboleth login
|
||||
configurationService.setProperty("plugin.sequence.org.dspace.authenticate.AuthenticationMethod", SHIB_ONLY);
|
||||
|
||||
//Create a reviewers group
|
||||
Group reviewersGroup = GroupBuilder.createGroup(context)
|
||||
.withName("Reviewers")
|
||||
.build();
|
||||
|
||||
//Faculty members are assigned to the Reviewers group
|
||||
configurationService.setProperty("authentication-shibboleth.role.faculty", "Reviewers");
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(post("/api/authn/login")
|
||||
.param("user", eperson.getEmail())
|
||||
.param("password", password))
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import static com.jayway.jsonpath.JsonPath.read;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.fail;
|
||||
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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.jayway.jsonpath.matchers.JsonPathMatchers;
|
||||
import org.dspace.app.rest.authorization.AlwaysTrueFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureService;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Test suite for the Authorization Feature endpoint
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
@Autowired
|
||||
private AuthorizationFeatureService authzFeatureService;
|
||||
|
||||
@Test
|
||||
/**
|
||||
* All the features should be returned
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void findAllTest() throws Exception {
|
||||
int featuresNum = authzFeatureService.findAll().size();
|
||||
int expReturn = featuresNum > 20 ? 20 : featuresNum;
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
// verify that only the admin can access the endpoint (see subsequent call in the method)
|
||||
getClient(adminToken).perform(get("/api/authz/features")).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(expReturn))))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features")))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(featuresNum)));
|
||||
// verify that anonymous user cannot access
|
||||
getClient().perform(get("/api/authz/features")).andExpect(status().isUnauthorized());
|
||||
// verify that normal user cannot access
|
||||
String epersonAuthToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(epersonAuthToken).perform(get("/api/authz/features")).andExpect(status().isForbidden());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* The feature endpoint must provide proper pagination. Unauthorized and
|
||||
* forbidden scenarios are managed in the findAllTest
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void findAllWithPaginationTest() throws Exception {
|
||||
int featuresNum = authzFeatureService.findAll().size();
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
List<String> featureIDs = new ArrayList<String>();
|
||||
for (int page = 0; page < featuresNum; page++) {
|
||||
AtomicReference<String> idRef = new AtomicReference<String>();
|
||||
|
||||
getClient(adminToken)
|
||||
.perform(get("/api/authz/features").param("page", String.valueOf(page)).param("size", "1"))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(1))))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features")))
|
||||
.andExpect(
|
||||
(page == 0) ? jsonPath("$._links.prev.href").doesNotExist()
|
||||
: jsonPath("$._links.prev.href", Matchers.containsString("/api/authz/features")))
|
||||
.andExpect((page == featuresNum - 1)
|
||||
? jsonPath("$._links.next.href").doesNotExist()
|
||||
: jsonPath("$._links.next.href", Matchers.containsString("/api/authz/features")))
|
||||
.andExpect(jsonPath("$._links.first.href", Matchers.containsString("/api/authz/features")))
|
||||
.andExpect(jsonPath("$._links.last.href", Matchers.containsString("/api/authz/features")))
|
||||
.andExpect(jsonPath("$.page.size", is(1)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(Integer.valueOf(featuresNum))))
|
||||
.andDo(result -> idRef
|
||||
.set(read(result.getResponse().getContentAsString(), "$._embedded.features[0].id")));
|
||||
|
||||
if (idRef.get() == null || featureIDs.contains(idRef.get())) {
|
||||
fail("Duplicate feature " + idRef.get() + " returned at page " + page);
|
||||
}
|
||||
featureIDs.add(idRef.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* The feature resource endpoint must expose the proper structure and be reserved to administrators
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void findOneTest() throws Exception {
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
// verify that only the admin can access the endpoint (see subsequent call in the method)
|
||||
getClient(adminToken).perform(get("/api/authz/features/withdrawItem")).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id", is("withdrawItem")))
|
||||
.andExpect(jsonPath("$.description", Matchers.any(String.class)))
|
||||
.andExpect(jsonPath("$.resourcetypes", Matchers.contains("core.item")))
|
||||
.andExpect(jsonPath("$.type", is("feature")));
|
||||
// verify that anonymous user cannot access
|
||||
getClient().perform(get("/api/authz/features/withdrawItem")).andExpect(status().isUnauthorized());
|
||||
// verify that normal user cannot access
|
||||
String epersonAuthToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(epersonAuthToken).perform(get("/api/authz/features/withdrawItem")).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneNotFoundTest() throws Exception {
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
// verify that only the admin can access the endpoint and get the not found response code
|
||||
// (see subsequent calls in the method for unauthorized and forbidden attempts)
|
||||
getClient(adminToken).perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isNotFound());
|
||||
// verify that anonymous user cannot access, without information disclosure
|
||||
getClient().perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isUnauthorized());
|
||||
// verify that normal user cannot access, without information disclosure
|
||||
getClient(adminToken).perform(get("/api/authz/features/1")).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* It should be possible to find features by resourcetype. The endpoint is only available to administrators
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void findByResourceTypeTest() throws Exception {
|
||||
AuthorizationFeature alwaysTrueFeature = authzFeatureService.find(AlwaysTrueFeature.NAME);
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
for (String type : alwaysTrueFeature.getSupportedTypes()) {
|
||||
// verify that only the admin can access the endpoint (see subsequent call in the method)
|
||||
getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", type))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$",
|
||||
JsonPathMatchers.hasJsonPath("$._embedded.features",
|
||||
Matchers.everyItem(
|
||||
JsonPathMatchers.hasJsonPath("$.resourcetypes",
|
||||
Matchers.hasItem(is(type))))
|
||||
)))
|
||||
.andExpect(
|
||||
jsonPath("$._links.self.href",
|
||||
Matchers.containsString("/api/authz/features/search/resourcetype")));
|
||||
}
|
||||
// verify that the right response code is returned also for not existing types
|
||||
getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", "NOT-EXISTING"))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.page.totalElements", is(0)));
|
||||
// verify that anonymous user cannot access, without information disclosure
|
||||
getClient().perform(get("/api/authz/features/search/resourcetype").param("type", "core.item"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
// verify that normal user cannot access, without information disclosure
|
||||
String epersonAuthToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(epersonAuthToken).perform(get("/api/authz/features/search/resourcetype").param("type", "core.item"))
|
||||
.andExpect(status().isForbidden());
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* 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;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.dspace.app.rest.authorization.AlwaysFalseFeature;
|
||||
import org.dspace.app.rest.authorization.AlwaysThrowExceptionFeature;
|
||||
import org.dspace.app.rest.authorization.AlwaysTrueFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeature;
|
||||
import org.dspace.app.rest.authorization.AuthorizationFeatureService;
|
||||
import org.dspace.app.rest.authorization.TrueForAdminsFeature;
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.dspace.app.rest.model.SiteRest;
|
||||
import org.dspace.app.rest.projection.DefaultProjection;
|
||||
import org.dspace.app.rest.test.AbstractIntegrationTestWithDatabase;
|
||||
import org.dspace.app.rest.utils.DSpaceConfigurationInitializer;
|
||||
import org.dspace.app.rest.utils.DSpaceKernelInitializer;
|
||||
import org.dspace.content.Site;
|
||||
import org.dspace.content.service.SiteService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
/**
|
||||
* Test for the Authorization Feature Service
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
*
|
||||
*/
|
||||
//Run tests with JUnit 4 and Spring TestContext Framework
|
||||
@RunWith(SpringRunner.class)
|
||||
//Specify main class to use to load Spring ApplicationContext
|
||||
//NOTE: By default, Spring caches and reuses ApplicationContext for each integration test (to speed up tests)
|
||||
//See: https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#integration-testing
|
||||
@SpringBootTest(classes = Application.class)
|
||||
//Load DSpace initializers in Spring ApplicationContext (to initialize DSpace Kernel & Configuration)
|
||||
@ContextConfiguration(initializers = { DSpaceKernelInitializer.class, DSpaceConfigurationInitializer.class })
|
||||
//Tell Spring to make ApplicationContext an instance of WebApplicationContext (for web-based tests)
|
||||
@WebAppConfiguration
|
||||
public class AuthorizationFeatureServiceIT extends AbstractIntegrationTestWithDatabase {
|
||||
@Autowired
|
||||
private SiteService siteService;
|
||||
|
||||
@Autowired
|
||||
private ConverterService converterService;
|
||||
|
||||
@Autowired
|
||||
private AuthorizationFeatureService authzFeatureService;
|
||||
|
||||
@Test
|
||||
/**
|
||||
* All the features available in the Sprint Context should be returned
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void findAllTest() throws Exception {
|
||||
List<AuthorizationFeature> authzFeatureServiceFindAll = authzFeatureService.findAll();
|
||||
|
||||
assertThat("We have at least our 7 mock features for testing",
|
||||
authzFeatureServiceFindAll.size(), greaterThanOrEqualTo(7));
|
||||
|
||||
Set<String> featureNames = new HashSet<String>();
|
||||
for (AuthorizationFeature f : authzFeatureServiceFindAll) {
|
||||
featureNames.add(f.getName());
|
||||
}
|
||||
|
||||
assertThat("all the features must have unique name", authzFeatureServiceFindAll.size(),
|
||||
equalTo(featureNames.size()));
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* The find method should return existing feature and null in the case the feature doesn't exist
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void findTest() throws Exception {
|
||||
AuthorizationFeature aFeature = authzFeatureService.find(AlwaysTrueFeature.NAME);
|
||||
assertThat("check that one of our mock feature is retrieved", aFeature.getName(),
|
||||
equalTo(AlwaysTrueFeature.NAME));
|
||||
|
||||
AuthorizationFeature aNotExistingFeature = authzFeatureService.find("this feature doesn't exist!");
|
||||
assertThat("check that not existing feature name return null", aNotExistingFeature, equalTo(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* The findByResourceType must return only features that support the specified type
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void findByResourceTypeTest() throws Exception {
|
||||
// we have at least one feature that support the Site object
|
||||
final String siteUniqueType = SiteRest.CATEGORY + "." + SiteRest.NAME;
|
||||
List<AuthorizationFeature> siteFeatures = authzFeatureService.findByResourceType(siteUniqueType);
|
||||
assertThat(siteFeatures.size(), greaterThan(0));
|
||||
boolean alwaysTrueFound = false;
|
||||
for (AuthorizationFeature f : siteFeatures) {
|
||||
assertThat(ArrayUtils.contains(f.getSupportedTypes(), siteUniqueType), equalTo(true));
|
||||
alwaysTrueFound = alwaysTrueFound || AlwaysTrueFeature.NAME.equals(f.getName());
|
||||
}
|
||||
assertThat(alwaysTrueFound, equalTo(true));
|
||||
|
||||
// we can check that the AlwaysTrueFeature is returned also when searching for a
|
||||
// type other than the Site (that is the first type supported by the feature)
|
||||
alwaysTrueFound = false;
|
||||
final String collectionUniqueType = CollectionRest.CATEGORY + "." + CollectionRest.NAME;
|
||||
List<AuthorizationFeature> collectionFeatures = authzFeatureService.findByResourceType(collectionUniqueType);
|
||||
for (AuthorizationFeature f : collectionFeatures) {
|
||||
assertThat(ArrayUtils.contains(f.getSupportedTypes(), collectionUniqueType), equalTo(true));
|
||||
alwaysTrueFound = alwaysTrueFound || AlwaysTrueFeature.NAME.equals(f.getName());
|
||||
}
|
||||
|
||||
// finally check that not existing type will return an empty list
|
||||
final List<AuthorizationFeature> notExistingTypeFeatures = authzFeatureService
|
||||
.findByResourceType("NOT-EXISTING-TYPE");
|
||||
assertThat(notExistingTypeFeatures.size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
/**
|
||||
* The isAuthorized must return true for authorized feature and false for not authorized feature
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void isAuthorizedTest() throws Exception {
|
||||
Site site = siteService.findSite(context);
|
||||
SiteRest siteRest = converterService.toRest(site, DefaultProjection.DEFAULT);
|
||||
|
||||
AuthorizationFeature alwaysTrue = authzFeatureService.find(AlwaysTrueFeature.NAME);
|
||||
AuthorizationFeature alwaysFalse = authzFeatureService.find(AlwaysFalseFeature.NAME);
|
||||
AuthorizationFeature alwaysThrowEx = authzFeatureService.find(AlwaysThrowExceptionFeature.NAME);
|
||||
AuthorizationFeature trueForAdmins = authzFeatureService.find(TrueForAdminsFeature.NAME);
|
||||
|
||||
assertThat(authzFeatureService.isAuthorized(context, alwaysTrue, siteRest), equalTo(true));
|
||||
assertThat(authzFeatureService.isAuthorized(context, alwaysFalse, siteRest), equalTo(false));
|
||||
try {
|
||||
authzFeatureService.isAuthorized(context, alwaysThrowEx, siteRest);
|
||||
// this code should be not run as the previous one throw an exception that we expect to be re-thrown
|
||||
assertThat("the exception has been not re-thrown!", false, equalTo(true));
|
||||
} catch (Exception ex) {
|
||||
// if this code is executed the exception was re-thrown
|
||||
assertThat("exceptions are rethrown", true, equalTo(true));
|
||||
}
|
||||
assertThat(authzFeatureService.isAuthorized(context, trueForAdmins, siteRest), equalTo(false));
|
||||
// login our admin
|
||||
context.setCurrentUser(admin);
|
||||
assertThat(authzFeatureService.isAuthorized(context, trueForAdmins, siteRest), equalTo(true));
|
||||
// finally check that a null object will always result in false to be returned
|
||||
assertThat(authzFeatureService.isAuthorized(context, alwaysTrue, null), equalTo(false));
|
||||
// without call at all the authorizationFeature to prevent NPE
|
||||
assertThat(authzFeatureService.isAuthorized(context, alwaysThrowEx, null), equalTo(false));
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -351,6 +351,61 @@ public class BitstreamControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putOnBitstreamInOneBundleForbiddenTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
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();
|
||||
|
||||
Item publicItem1 = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Test")
|
||||
.withIssueDate("2016-11-11")
|
||||
.withAuthor("Smith, Donald")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
Item targetItem = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Test")
|
||||
.withIssueDate("2016-11-11")
|
||||
.withAuthor("Smith, Donald")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
|
||||
Bundle bundle1 = BundleBuilder.createBundle(context, publicItem1)
|
||||
.withName("TEST FIRST BUNDLE")
|
||||
.build();
|
||||
|
||||
Bundle targetBundle = BundleBuilder.createBundle(context, targetItem)
|
||||
.withName("TARGET BUNDLE")
|
||||
.build();
|
||||
|
||||
String bitstreamContent = "ThisIsSomeDummyText";
|
||||
Bitstream bitstream = null;
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream = BitstreamBuilder.createBitstream(context, bundle1, is)
|
||||
.withName("Bitstream")
|
||||
.withDescription("description")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(token).perform(put("/api/core/bitstreams/" + bitstream.getID() + "/bundle")
|
||||
.contentType(parseMediaType(TEXT_URI_LIST_VALUE))
|
||||
.content("https://localhost:8080/spring-rest/api/core/bundles/" + targetBundle.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putOnBitstreamInMultipleBundles() throws Exception {
|
||||
|
||||
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static java.util.UUID.randomUUID;
|
||||
|
||||
import static org.apache.commons.codec.CharEncoding.UTF_8;
|
||||
import static org.apache.commons.collections.CollectionUtils.isEmpty;
|
||||
import static org.apache.commons.io.IOUtils.toInputStream;
|
||||
|
@@ -45,6 +45,7 @@ import org.dspace.app.rest.model.patch.MoveOperation;
|
||||
import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Collection;
|
||||
@@ -54,10 +55,14 @@ import org.dspace.eperson.EPerson;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
ResourcePolicyService resourcePolicyService;
|
||||
|
||||
private Collection collection;
|
||||
private Item item;
|
||||
private Bundle bundle1;
|
||||
@@ -136,6 +141,30 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
String bitstreamContent = "Dummy content";
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream1 = BitstreamBuilder.createBitstream(context, item, is)
|
||||
.withName("Bitstream")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
bundle1 = BundleBuilder.createBundle(context, item)
|
||||
.withName("testname")
|
||||
.withBitstream(bitstream1)
|
||||
.build();
|
||||
|
||||
resourcePolicyService.removePolicies(context, bundle1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/bundles/" + bundle1.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getItemBundles() throws Exception {
|
||||
@@ -385,6 +414,38 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBitstreamsForBundleForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
String bitstreamContent = "Dummy content";
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream1 = BitstreamBuilder.createBitstream(context, item, is)
|
||||
.withName("Bitstream")
|
||||
.withDescription("Description")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
bitstream2 = BitstreamBuilder.createBitstream(context, item, is)
|
||||
.withName("Bitstream2")
|
||||
.withDescription("Description2")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
bundle1 = BundleBuilder.createBundle(context, item)
|
||||
.withName("testname")
|
||||
.withBitstream(bitstream1)
|
||||
.withBitstream(bitstream2)
|
||||
.build();
|
||||
|
||||
resourcePolicyService.removePolicies(context, bundle1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/bundles/" + bundle1.getID() + "/bitstreams"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchMoveBitstreams() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -24,6 +24,7 @@ import java.util.UUID;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.builder.EPersonBuilder;
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.matcher.CollectionMatcher;
|
||||
import org.dspace.app.rest.matcher.CommunityMatcher;
|
||||
@@ -37,6 +38,7 @@ import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.core.Constants;
|
||||
@@ -54,6 +56,9 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
ResourcePolicyService resoucePolicyService;
|
||||
|
||||
@Test
|
||||
public void findAllTest() throws Exception {
|
||||
|
||||
@@ -86,6 +91,108 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
|
||||
)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllUnAuthenticatedTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
Collection col2 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, col2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// anonymous can see only public collections
|
||||
getClient().perform(get("/api/core/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.contains(
|
||||
CollectionMatcher.matchCollection(col1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
Collection col2 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, col2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// eperson logged can see only public collections
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.contains(
|
||||
CollectionMatcher.matchCollection(col1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllGrantAccessAdminsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson parentAdmin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson1@mail.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withAdminGroup(parentAdmin)
|
||||
.build();
|
||||
|
||||
EPerson col1Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson2@mail.com")
|
||||
.withPassword("qwerty02")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.withAdminGroup(col1Admin)
|
||||
.build();
|
||||
|
||||
Collection col2 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, parentCommunity, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, col1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// parent community admin can see all sub collections
|
||||
String tokenParentAdmin = getAuthToken(parentAdmin.getEmail(), "qwerty01");
|
||||
getClient(tokenParentAdmin).perform(get("/api/core/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.containsInAnyOrder(
|
||||
CollectionMatcher.matchCollection(col1),
|
||||
CollectionMatcher.matchCollection(col2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
|
||||
// admin of col1 can see owner collections and any public collections
|
||||
String tokenCol1Admin = getAuthToken(col1Admin.getEmail(), "qwerty02");
|
||||
getClient(tokenCol1Admin).perform(get("/api/core/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.containsInAnyOrder(
|
||||
CollectionMatcher.matchCollection(col1),
|
||||
CollectionMatcher.matchCollection(col2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllPaginationTest() throws Exception {
|
||||
|
||||
@@ -182,6 +289,100 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
|
||||
col1.getName(), col1.getID(), col1.getHandle())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneCollectionUnAuthenticatedTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, col1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(get("/api/core/collections/" + col1.getID()))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneCollectionForbiddenTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, col1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/collections/" + col1.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneCollectionGrantAccessAdminsTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson parentAdmin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson1@mail.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withAdminGroup(parentAdmin)
|
||||
.build();
|
||||
|
||||
EPerson col1Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson2@mail.com")
|
||||
.withPassword("qwerty02")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.withAdminGroup(col1Admin)
|
||||
.build();
|
||||
|
||||
EPerson col2Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson3@mail.com")
|
||||
.withPassword("qwerty03")
|
||||
.build();
|
||||
Collection col2 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 2")
|
||||
.withAdminGroup(col2Admin)
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, parentCommunity, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, col1, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, col2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenParentAdmin = getAuthToken(parentAdmin.getEmail(), "qwerty01");
|
||||
getClient(tokenParentAdmin).perform(get("/api/core/collections/" + col1.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$",
|
||||
Matchers.is((CollectionMatcher.matchCollection(col1)))));
|
||||
|
||||
String tokenCol1Admin = getAuthToken(col1Admin.getEmail(), "qwerty02");
|
||||
getClient(tokenCol1Admin).perform(get("/api/core/collections/" + col1.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$",
|
||||
Matchers.is((CollectionMatcher.matchCollection(col1)))));
|
||||
|
||||
String tokenCol2Admin = getAuthToken(col2Admin.getEmail(), "qwerty03");
|
||||
getClient(tokenCol2Admin).perform(get("/api/core/collections/" + col1.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
@Test
|
||||
public void findOneCollectionRelsTest() throws Exception {
|
||||
|
||||
|
@@ -32,7 +32,9 @@ import java.util.stream.StreamSupport;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.builder.EPersonBuilder;
|
||||
import org.dspace.app.rest.converter.ConverterService;
|
||||
import org.dspace.app.rest.matcher.CollectionMatcher;
|
||||
import org.dspace.app.rest.matcher.CommunityMatcher;
|
||||
import org.dspace.app.rest.matcher.HalMatcher;
|
||||
import org.dspace.app.rest.matcher.MetadataMatcher;
|
||||
@@ -44,6 +46,7 @@ import org.dspace.app.rest.projection.Projection;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
@@ -71,6 +74,9 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
ResourcePolicyService resoucePolicyService;
|
||||
|
||||
@Test
|
||||
public void createTest() throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
@@ -528,6 +534,110 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllUnAuthenticatedTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
Community child2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, parentCommunity, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, child1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// anonymous can see only public communities
|
||||
getClient().perform(get("/api/core/communities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.contains(
|
||||
CommunityMatcher.matchCommunity(child2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
Community child2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, parentCommunity, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, child1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/communities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.contains(
|
||||
CommunityMatcher.matchCommunity(child2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllGrantAccessAdminsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson parentAdmin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson1@mail.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withAdminGroup(parentAdmin)
|
||||
.build();
|
||||
|
||||
EPerson child1Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson2@mail.com")
|
||||
.withPassword("qwerty02")
|
||||
.build();
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community 1")
|
||||
.withAdminGroup(child1Admin)
|
||||
.build();
|
||||
|
||||
Community child2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, parentCommunity, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, child1, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenParentAdmin = getAuthToken(parentAdmin.getEmail(), "qwerty01");
|
||||
getClient(tokenParentAdmin).perform(get("/api/core/communities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.containsInAnyOrder(
|
||||
CommunityMatcher.matchCommunity(parentCommunity),
|
||||
CommunityMatcher.matchCommunity(child1),
|
||||
CommunityMatcher.matchCommunity(child2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(3)));
|
||||
|
||||
String tokenChild1Admin = getAuthToken(child1Admin.getEmail(), "qwerty02");
|
||||
getClient(tokenChild1Admin).perform(get("/api/core/communities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.containsInAnyOrder(
|
||||
CommunityMatcher.matchCommunity(child1),
|
||||
CommunityMatcher.matchCommunity(child2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneTest() throws Exception {
|
||||
//We turn off the authorization system in order to create the structure as defined below
|
||||
@@ -564,6 +674,86 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
parentCommunity.getName(), parentCommunity.getID(), parentCommunity.getHandle())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneUnAuthenticatedTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
Community privateCommunity = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Private Community")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, privateCommunity, Constants.READ);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(get("/api/core/communities/" + privateCommunity.getID().toString()))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
Community privateCommunity = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Private Community")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, privateCommunity, Constants.READ);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/communities/" + privateCommunity.getID().toString()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneGrantAccessAdminsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withAdminGroup(eperson)
|
||||
.build();
|
||||
|
||||
EPerson privateCommunityAdmin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("comunityAdmin@mail.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
Community privateCommunity = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.withAdminGroup(privateCommunityAdmin)
|
||||
.build();
|
||||
|
||||
EPerson privateCommunityAdmin2 = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("comunityAdmin2@mail.com")
|
||||
.withPassword("qwerty02")
|
||||
.build();
|
||||
Community privateCommunity2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community 2")
|
||||
.withAdminGroup(privateCommunityAdmin2)
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, privateCommunity, Constants.READ);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenParentComunityAdmin = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenParentComunityAdmin).perform(get("/api/core/communities/" + privateCommunity.getID().toString()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(CommunityMatcher.matchCommunity(privateCommunity))));
|
||||
|
||||
String tokenCommunityAdmin = getAuthToken(privateCommunityAdmin.getEmail(), "qwerty01");
|
||||
getClient(tokenCommunityAdmin).perform(get("/api/core/communities/" + privateCommunity.getID().toString()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(CommunityMatcher.matchCommunity(privateCommunity))));
|
||||
|
||||
String tokenComunityAdmin2 = getAuthToken(privateCommunityAdmin2.getEmail(), "qwerty02");
|
||||
getClient(tokenComunityAdmin2).perform(get("/api/core/communities/"
|
||||
+ privateCommunity.getID().toString()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneRelsTest() throws Exception {
|
||||
//We turn off the authorization system in order to create the structure as defined below
|
||||
@@ -615,7 +805,7 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
getClient().perform(get("/api/core/communities/" + child1.getID().toString() + "/logo"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
//Main community has no collections, therefore contentType is not set
|
||||
//Main community has no collections
|
||||
getClient().perform(get("/api/core/communities/" + parentCommunity.getID().toString() + "/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.page.totalElements", is(0)));
|
||||
@@ -698,31 +888,30 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and one collection.
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.build();
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.build();
|
||||
|
||||
Community parentCommunity2 = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community 2")
|
||||
.withLogo("SomeTest")
|
||||
.build();
|
||||
.withName("Parent Community 2")
|
||||
.withLogo("SomeTest")
|
||||
.build();
|
||||
|
||||
Community parentCommunityChild1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
|
||||
Community parentCommunityChild2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community2")
|
||||
.build();
|
||||
.withName("Sub Community2")
|
||||
.build();
|
||||
|
||||
Community parentCommunityChild2Child1 = CommunityBuilder.createSubCommunity(context, parentCommunityChild2)
|
||||
.withName("Sub Sub Community")
|
||||
.build();
|
||||
|
||||
.withName("Sub Sub Community")
|
||||
.build();
|
||||
|
||||
Community parentCommunity2Child1 = CommunityBuilder.createSubCommunity(context, parentCommunity2)
|
||||
.withName("Sub2 Community")
|
||||
.build();
|
||||
.withName("Sub2 Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunityChild1)
|
||||
.withName("Collection 1")
|
||||
@@ -730,98 +919,379 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(get("/api/core/communities/search/subCommunities")
|
||||
.param("parent", parentCommunity.getID().toString())
|
||||
.param("projection", "full"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
//Checking that these communities are present
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.containsInAnyOrder(
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunityChild1.getName(),
|
||||
parentCommunityChild1.getID(),
|
||||
parentCommunityChild1.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunityChild2.getName(),
|
||||
parentCommunityChild2.getID(),
|
||||
parentCommunityChild2.getHandle())
|
||||
)))
|
||||
//Checking that these communities are not present
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.not(Matchers.anyOf(
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunity.getName(),
|
||||
parentCommunity.getID(),
|
||||
parentCommunity.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunity2.getName(),
|
||||
parentCommunity2.getID(),
|
||||
parentCommunity2.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunity2Child1.getName(),
|
||||
parentCommunity2Child1.getID(),
|
||||
parentCommunity2Child1.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunityChild2Child1.getName(),
|
||||
parentCommunityChild2Child1.getID(),
|
||||
parentCommunityChild2Child1.getHandle())
|
||||
))))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
Matchers.containsString("/api/core/communities/search/subCommunities")))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)))
|
||||
;
|
||||
getClient().perform(get("/api/core/communities/" + parentCommunity.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
//Checking that these communities are present
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.containsInAnyOrder(
|
||||
CommunityMatcher.matchCommunity(parentCommunityChild1),
|
||||
CommunityMatcher.matchCommunity(parentCommunityChild2)
|
||||
)))
|
||||
//Checking that these communities are not present
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.not(Matchers.anyOf(
|
||||
CommunityMatcher.matchCommunity(parentCommunity),
|
||||
CommunityMatcher.matchCommunity(parentCommunity2),
|
||||
CommunityMatcher.matchCommunity(parentCommunity2Child1),
|
||||
CommunityMatcher.matchCommunity(parentCommunityChild2Child1)
|
||||
))))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
Matchers.containsString("/api/core/communities/" + parentCommunity.getID().toString())))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
|
||||
getClient().perform(get("/api/core/communities/search/subCommunities")
|
||||
.param("parent", parentCommunityChild2.getID().toString())
|
||||
.param("projection", "full"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
//Checking that these communities are present
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.contains(
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunityChild2Child1.getName(),
|
||||
parentCommunityChild2Child1.getID(),
|
||||
parentCommunityChild2Child1.getHandle())
|
||||
)))
|
||||
//Checking that these communities are not present
|
||||
.andExpect(jsonPath("$._embedded.communities", Matchers.not(Matchers.anyOf(
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunity.getName(),
|
||||
parentCommunity.getID(),
|
||||
parentCommunity.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunity2.getName(),
|
||||
parentCommunity2.getID(),
|
||||
parentCommunity2.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunity2Child1.getName(),
|
||||
parentCommunity2Child1.getID(),
|
||||
parentCommunity2Child1.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunityChild2Child1.getName(),
|
||||
parentCommunityChild2Child1.getID(),
|
||||
parentCommunityChild2Child1.getHandle()),
|
||||
CommunityMatcher.matchCommunityEntryFullProjection(parentCommunityChild1.getName(),
|
||||
parentCommunityChild1.getID(),
|
||||
parentCommunityChild1.getHandle())
|
||||
))))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
Matchers.containsString("/api/core/communities/search/subCommunities")))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)))
|
||||
;
|
||||
getClient().perform(get("/api/core/communities/" + parentCommunityChild2.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
//Checking that these communities are present
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.contains(
|
||||
CommunityMatcher.matchCommunity(parentCommunityChild2Child1)
|
||||
)))
|
||||
//Checking that these communities are not present
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.not(Matchers.anyOf(
|
||||
CommunityMatcher.matchCommunity(parentCommunity),
|
||||
CommunityMatcher.matchCommunity(parentCommunity2),
|
||||
CommunityMatcher.matchCommunity(parentCommunity2Child1),
|
||||
CommunityMatcher.matchCommunity(parentCommunityChild2Child1),
|
||||
CommunityMatcher.matchCommunity(parentCommunityChild1)
|
||||
))))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
Matchers.containsString("/api/core/communities/" + parentCommunityChild2.getID().toString())))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
|
||||
getClient().perform(get("/api/core/communities/search/subCommunities")
|
||||
.param("parent", parentCommunityChild2Child1.getID().toString()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
Matchers.containsString("/api/core/communities/search/subCommunities")))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(0)))
|
||||
;
|
||||
getClient().perform(get("/api/core/communities/"
|
||||
+ parentCommunityChild2Child1.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
Matchers.containsString("/api/core/communities/" + parentCommunityChild2Child1.getID().toString())))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllSubCommunitiesWithoutUUID() throws Exception {
|
||||
getClient().perform(get("/api/core/communities/search/subCommunities"))
|
||||
.andExpect(status().isBadRequest());
|
||||
public void findAllSubCommunitiesUnAuthenticatedTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.build();
|
||||
|
||||
Community communityChild1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
|
||||
Community communityChild2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community2")
|
||||
.build();
|
||||
|
||||
Community communityChild2Child1 = CommunityBuilder.createSubCommunity(context, communityChild2)
|
||||
.withName("Sub Community2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, communityChild2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// anonymous can NOT see the private communities
|
||||
getClient().perform(get("/api/core/communities/" + communityChild2.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
// anonymous can see only public communities
|
||||
getClient().perform(get("/api/core/communities/" + parentCommunity.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.contains(
|
||||
CommunityMatcher.matchCommunity(communityChild1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
|
||||
// admin can see all communities
|
||||
String tokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||
getClient(tokenAdmin).perform(get("/api/core/communities/"
|
||||
+ parentCommunity.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.containsInAnyOrder(
|
||||
CommunityMatcher.matchCommunity(communityChild1),
|
||||
CommunityMatcher.matchCommunity(communityChild2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllSubCommunitiesForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.build();
|
||||
|
||||
Community communityChild1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
|
||||
Community communityChild2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community2")
|
||||
.build();
|
||||
|
||||
Community communityChild2Child1 = CommunityBuilder.createSubCommunity(context, communityChild2)
|
||||
.withName("Sub Community2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, communityChild2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/communities/"
|
||||
+ parentCommunity.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.contains(
|
||||
CommunityMatcher.matchCommunity(communityChild1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
|
||||
getClient(tokenEperson).perform(get("/api/core/communities/"
|
||||
+ communityChild2.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllSubCommunitiesGrantAccessAdminsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson parentComAdmin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson1@mail.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.withAdminGroup(parentComAdmin)
|
||||
.build();
|
||||
|
||||
EPerson child1Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson2@mail.com")
|
||||
.withPassword("qwerty02")
|
||||
.build();
|
||||
Community communityChild1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.withAdminGroup(child1Admin)
|
||||
.build();
|
||||
|
||||
EPerson child2Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson3@mail.com")
|
||||
.withPassword("qwerty03")
|
||||
.build();
|
||||
Community communityChild2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community2")
|
||||
.withAdminGroup(child2Admin)
|
||||
.build();
|
||||
|
||||
Community ommunityChild1Child1 = CommunityBuilder.createSubCommunity(context, communityChild1)
|
||||
.withName("Sub1 Community 1")
|
||||
.build();
|
||||
|
||||
Community сommunityChild2Child1 = CommunityBuilder.createSubCommunity(context, communityChild2)
|
||||
.withName("Sub2 Community 1")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, parentCommunity, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, communityChild1, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, communityChild2, Constants.READ);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenParentAdmin = getAuthToken(parentComAdmin.getEmail(), "qwerty01");
|
||||
getClient(tokenParentAdmin).perform(get("/api/core/communities/"
|
||||
+ parentCommunity.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$._embedded.subcommunities", Matchers.containsInAnyOrder(
|
||||
CommunityMatcher.matchCommunity(communityChild1),
|
||||
CommunityMatcher.matchCommunity(communityChild2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
|
||||
String tokenChild1Admin = getAuthToken(child1Admin.getEmail(), "qwerty02");
|
||||
getClient(tokenChild1Admin).perform(get("/api/core/communities/"
|
||||
+ parentCommunity.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isForbidden());
|
||||
|
||||
String tokenChild2Admin = getAuthToken(child2Admin.getEmail(), "qwerty03");
|
||||
getClient(tokenChild2Admin).perform(get("/api/core/communities/"
|
||||
+ communityChild1.getID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllCollectionsUnAuthenticatedTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.build();
|
||||
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
|
||||
Community child2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
|
||||
Collection child1Col1 = CollectionBuilder.createCollection(context, child1)
|
||||
.withName("Collection 1 child 1")
|
||||
.build();
|
||||
Collection child1Col2 = CollectionBuilder.createCollection(context, child1)
|
||||
.withName("Collection 2 child 1")
|
||||
.build();
|
||||
|
||||
Collection child2Col1 = CollectionBuilder.createCollection(context, child2)
|
||||
.withName("Collection 1 child 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, child1Col2, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, child2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
// anonymous can see only public communities
|
||||
getClient().perform(get("/api/core/communities/" + child1.getID().toString() + "/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.contains(CollectionMatcher
|
||||
.matchCollection(child1Col1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
|
||||
// anonymous can NOT see the private communities
|
||||
getClient().perform(get("/api/core/communities/" + child2.getID().toString() + "/collections"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllCollectionsForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.build();
|
||||
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community 1")
|
||||
.build();
|
||||
|
||||
|
||||
Community child2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community 2")
|
||||
.build();
|
||||
|
||||
Collection child1Col1 = CollectionBuilder.createCollection(context, child1)
|
||||
.withName("Collection 1 child 1")
|
||||
.build();
|
||||
Collection child1Col2 = CollectionBuilder.createCollection(context, child1)
|
||||
.withName("Collection 2 child 1")
|
||||
.build();
|
||||
|
||||
Collection child2Col1 = CollectionBuilder.createCollection(context, child2)
|
||||
.withName("Collection 1 child 2")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, child1Col2, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, child2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenAdmin = getAuthToken(admin.getEmail(), password);
|
||||
getClient(tokenAdmin).perform(get("/api/core/communities/" + child1.getID().toString() + "/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.containsInAnyOrder(
|
||||
CollectionMatcher.matchCollection(child1Col1),
|
||||
CollectionMatcher.matchCollection(child1Col2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
|
||||
getClient(tokenAdmin).perform(get("/api/core/communities/" + child2.getID().toString() + "/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.contains(
|
||||
CollectionMatcher.matchCollection(child2Col1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/communities/" + child2.getID().toString() + "/collections"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllCollectionsGrantAccessAdminsTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson parentAdmin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("eperson1@mail.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.withLogo("ThisIsSomeDummyText")
|
||||
.withAdminGroup(parentAdmin)
|
||||
.build();
|
||||
|
||||
EPerson child1Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("child1admin@mail.com")
|
||||
.withPassword("qwerty02")
|
||||
.build();
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.withAdminGroup(child1Admin)
|
||||
.build();
|
||||
|
||||
EPerson child2Admin = EPersonBuilder.createEPerson(context)
|
||||
.withEmail("child2admin@mail.com")
|
||||
.withPassword("qwerty03")
|
||||
.build();
|
||||
Community child2 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.withAdminGroup(child2Admin)
|
||||
.build();
|
||||
|
||||
Collection child1Col1 = CollectionBuilder.createCollection(context, child1)
|
||||
.withName("Child 1 Collection 1")
|
||||
.build();
|
||||
Collection child1Col2 = CollectionBuilder.createCollection(context, child1)
|
||||
.withName("Child 1 Collection 2")
|
||||
.build();
|
||||
|
||||
Collection child2Col1 = CollectionBuilder.createCollection(context, child2)
|
||||
.withName("Child 2 Collection 1")
|
||||
.build();
|
||||
|
||||
resoucePolicyService.removePolicies(context, child1Col2, Constants.READ);
|
||||
resoucePolicyService.removePolicies(context, child2, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenParentAdmin = getAuthToken(parentAdmin.getEmail(), "qwerty01");
|
||||
getClient(tokenParentAdmin).perform(get("/api/core/communities/" + child1.getID().toString() + "/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.containsInAnyOrder(
|
||||
CollectionMatcher.matchCollection(child1Col1),
|
||||
CollectionMatcher.matchCollection(child1Col2))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)));
|
||||
|
||||
|
||||
getClient(tokenParentAdmin).perform(get("/api/core/communities/" + child2.getID().toString() + "/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.contains(
|
||||
CollectionMatcher.matchCollection(child2Col1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
|
||||
String tokenChild2Admin = getAuthToken(child2Admin.getEmail(), "qwerty03");
|
||||
getClient(tokenChild2Admin).perform(get("/api/core/communities/" + child1.getID().toString() + "/collections"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.collections", Matchers.contains(
|
||||
CollectionMatcher.matchCollection(child1Col1))))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllSubCommunitiesWithUnexistentUUID() throws Exception {
|
||||
getClient().perform(get("/api/core/communities/search/subCommunities")
|
||||
.param("parent", UUID.randomUUID().toString()))
|
||||
.andExpect(status().isNotFound());
|
||||
getClient().perform(get("/api/core/communities/" + UUID.randomUUID().toString() + "/subcommunities"))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -235,6 +235,28 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson ePerson1 = EPersonBuilder.createEPerson(context)
|
||||
.withNameInMetadata("Mik", "Reck")
|
||||
.withEmail("MikReck@email.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
|
||||
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
|
||||
.withNameInMetadata("Bob", "Smith")
|
||||
.withEmail("bobsmith@fake-email.com")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson1 = getAuthToken(ePerson1.getEmail(), "qwerty01");
|
||||
getClient(tokenEperson1).perform(get("/api/eperson/epersons/" + ePerson2.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readEpersonAuthorizationTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
@@ -1494,6 +1516,31 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
new MetadataPatchSuite().runWith(getClient(token), "/api/eperson/epersons/" + ePerson.getID(), expectedStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newlyCreatedAccountHasNoGroups() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson ePerson1 = EPersonBuilder.createEPerson(context)
|
||||
.withNameInMetadata("Mik", "Reck")
|
||||
.withEmail("MikReck@email.com")
|
||||
.withPassword("qwerty01")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson1 = getAuthToken(ePerson1.getEmail(), "qwerty01");
|
||||
// by contract the groups embedded in the eperson only contains direct explicit membership,
|
||||
// so the anonymous group is not listed
|
||||
getClient(tokenEperson1).perform(get("/api/eperson/epersons/" + ePerson1.getID())
|
||||
.param("projection", "full"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$", Matchers.allOf(
|
||||
hasJsonPath("$._embedded.groups._embedded.groups.length()", is(0)),
|
||||
hasJsonPath("$._embedded.groups.page.totalElements", is(0))
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that epersons/<:uuid>/groups endpoint returns the direct groups of the epersons
|
||||
* @throws Exception
|
||||
@@ -1543,5 +1590,4 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -43,11 +43,13 @@ import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.model.patch.ReplaceOperation;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.app.rest.test.MetadataPatchSuite;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
@@ -55,6 +57,7 @@ import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.eperson.service.GroupService;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* @author Jonas Van Goolen - (jonas@atmire.com)
|
||||
@@ -62,6 +65,9 @@ import org.junit.Test;
|
||||
|
||||
public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
ResourcePolicyService resourcePolicyService;
|
||||
|
||||
@Test
|
||||
public void createTest()
|
||||
throws Exception {
|
||||
@@ -195,6 +201,13 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllForbiddenTest() throws Exception {
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/eperson/groups"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllPaginationTest() throws Exception {
|
||||
|
||||
@@ -304,6 +317,22 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
Matchers.containsString("/api/eperson/groups/" + group2.getID())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
Group privateGroup = GroupBuilder.createGroup(context)
|
||||
.withName("Private Group")
|
||||
.build();
|
||||
|
||||
resourcePolicyService.removePolicies(context, privateGroup, Constants.READ);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/eperson/groups/" + privateGroup.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneTestWrongUUID() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -283,4 +283,34 @@ public class ItemOwningCollectionUpdateRestControllerIT extends AbstractControll
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveItemForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
Collection col2 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 2")
|
||||
.build();
|
||||
|
||||
Item publicItem1 = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Public item 1")
|
||||
.withIssueDate("2019-10-21")
|
||||
.withAuthor("Smith, Donald")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String tokenEPerson = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(tokenEPerson).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/")
|
||||
.contentType(parseMediaType(TEXT_URI_LIST_VALUE))
|
||||
.content("https://localhost:8080/spring-rest/api/core/collections/" + col2.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
@@ -124,6 +123,13 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllForbiddenTest() throws Exception {
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get("/api/core/items"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllWithPaginationTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
@@ -32,14 +32,20 @@ import org.dspace.app.rest.model.patch.AddOperation;
|
||||
import org.dspace.app.rest.model.patch.Operation;
|
||||
import org.dspace.app.rest.model.patch.ReplaceOperation;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.authorize.service.ResourcePolicyService;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.core.Constants;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
public class ItemTemplateRestControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
ResourcePolicyService resourcePolicyService;
|
||||
|
||||
private ObjectMapper mapper;
|
||||
private String adminAuthToken;
|
||||
private Collection childCollection;
|
||||
@@ -160,6 +166,17 @@ public class ItemTemplateRestControllerIT extends AbstractControllerIntegrationT
|
||||
)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTemplateItemFromCollectionForbiddenTest() throws Exception {
|
||||
setupTestTemplate();
|
||||
String itemUuidString = installTestTemplate();
|
||||
|
||||
resourcePolicyService.removePolicies(context, childCollection, Constants.READ);
|
||||
String tokenEperson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEperson).perform(get(getCollectionTemplateItemUrlTemplate(childCollection.getID().toString())))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTemplateItemFromItemId() throws Exception {
|
||||
setupTestTemplate();
|
||||
|
@@ -8,7 +8,6 @@
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static com.jayway.jsonpath.JsonPath.read;
|
||||
|
||||
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
@@ -27,11 +26,9 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.builder.EPersonBuilder;
|
||||
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Integration test that cover ShibbolethRestController
|
||||
*
|
||||
* @author Giuseppe Digilio (giuseppe dot digilio at 4science dot it)
|
||||
*/
|
||||
public class ShibbolethRestControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void testRedirectToDefaultDspaceUrl() throws Exception {
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(token).perform(get("/api/authn/shibboleth"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://localhost:3000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedirectToGivenUrl() throws Exception {
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(token).perform(get("/api/authn/shibboleth")
|
||||
.param("redirectUrl", "http://dspace.org"))
|
||||
.andExpect(status().is3xxRedirection())
|
||||
.andExpect(redirectedUrl("http://dspace.org"));
|
||||
}
|
||||
}
|
@@ -8,6 +8,7 @@
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
import static org.dspace.app.rest.test.AbstractControllerIntegrationTest.REST_SERVER_URL;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
@@ -62,6 +63,22 @@ public class SubmissionDefinitionsControllerIT extends AbstractControllerIntegra
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllWithNewlyCreatedAccountTest() throws Exception {
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/config/submissiondefinitions"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", greaterThanOrEqualTo(1)))
|
||||
.andExpect(jsonPath("$.page.totalPages", greaterThanOrEqualTo(1)))
|
||||
.andExpect(jsonPath("$.page.number", is(0)))
|
||||
.andExpect(jsonPath("$._links.search.href", is(REST_SERVER_URL
|
||||
+ "config/submissiondefinitions/search")))
|
||||
//The array of browse index should have a size greater or equals to 1
|
||||
.andExpect(jsonPath("$._embedded.submissiondefinitions", hasSize(greaterThanOrEqualTo(1))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findDefault() throws Exception {
|
||||
getClient().perform(get("/api/config/submissiondefinitions/traditional"))
|
||||
@@ -84,6 +101,19 @@ public class SubmissionDefinitionsControllerIT extends AbstractControllerIntegra
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneWithNewlyCreatedAccountTest() throws Exception {
|
||||
String tokenEPerson = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(tokenEPerson).perform(get("/api/config/submissiondefinitions/traditional"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$", allOf(
|
||||
hasJsonPath("$.isDefault", is(true)),
|
||||
hasJsonPath("$.name", is("traditional")),
|
||||
hasJsonPath("$.id", is("traditional")),
|
||||
hasJsonPath("$.type", is("submissiondefinition")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByCollection() throws Exception {
|
||||
|
||||
@@ -117,6 +147,29 @@ public class SubmissionDefinitionsControllerIT extends AbstractControllerIntegra
|
||||
.matchSubmissionDefinition(true, "traditional", "traditional")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByCollectionWithNewlyCreatedAccountTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Community")
|
||||
.build();
|
||||
|
||||
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1")
|
||||
.build();
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/config/submissiondefinitions/search/findByCollection")
|
||||
.param("uuid", col1.getID().toString()))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(MockMvcResultHandlers.print())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$", SubmissionDefinitionsMatcher
|
||||
.matchSubmissionDefinition(true, "traditional", "traditional")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findCollections() throws Exception {
|
||||
|
||||
|
@@ -55,6 +55,21 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllWithNewlyCreatedAccountTest() throws Exception {
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/config/submissionforms"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", equalTo(4)))
|
||||
.andExpect(jsonPath("$.page.totalPages", equalTo(1)))
|
||||
.andExpect(jsonPath("$.page.number", is(0)))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers.startsWith(REST_SERVER_URL
|
||||
+ "config/submissionforms")))
|
||||
.andExpect(jsonPath("$._embedded.submissionforms", hasSize(equalTo(4))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findTraditionalPageOne() throws Exception {
|
||||
//When we call the root endpoint as anonymous user
|
||||
@@ -96,6 +111,34 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findTraditionalPageOneWithNewlyCreatedAccountTest() throws Exception {
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/config/submissionforms/traditionalpageone"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.id", is("traditionalpageone")))
|
||||
.andExpect(jsonPath("$.name", is("traditionalpageone")))
|
||||
.andExpect(jsonPath("$.type", is("submissionform")))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers
|
||||
.startsWith(REST_SERVER_URL + "config/submissionforms/traditionalpageone")))
|
||||
.andExpect(jsonPath("$.rows[0].fields", contains(
|
||||
SubmissionFormFieldMatcher.matchFormFieldDefinition("name", "Author",
|
||||
null, true,"Add an author", "dc.contributor.author"))))
|
||||
.andExpect(jsonPath("$.rows[1].fields", contains(
|
||||
SubmissionFormFieldMatcher.matchFormFieldDefinition("onebox", "Title",
|
||||
"You must enter a main title for this item.", false,
|
||||
"Enter the main title of the item.", "dc.title"))))
|
||||
.andExpect(jsonPath("$.rows[3].fields",contains(
|
||||
SubmissionFormFieldMatcher.matchFormFieldDefinition("date", "Date of Issue",
|
||||
"You must enter at least the year.", false,
|
||||
"Please give the date", "col-sm-4",
|
||||
"dc.date.issued"),
|
||||
SubmissionFormFieldMatcher.matchFormFieldDefinition("onebox", "Publisher",
|
||||
null, false,"Enter the name of",
|
||||
"col-sm-8","dc.publisher"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOpenRelationshipConfig() throws Exception {
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
@@ -33,7 +33,7 @@ public class SubmissionSectionsControllerIT extends AbstractControllerIntegratio
|
||||
.andExpect(status().isUnauthorized());
|
||||
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
//When we call the root endpoint
|
||||
getClient(token).perform(get("/api/config/submissionsections"))
|
||||
|
@@ -54,4 +54,19 @@ public class SubmissionUploadsControllerIT extends AbstractControllerIntegration
|
||||
.andExpect(jsonPath("$._embedded.submissionuploads", hasSize(greaterThanOrEqualTo(1))))
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findAllWithNewlyCreatedAccountTest() throws Exception {
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/config/submissionuploads"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", greaterThanOrEqualTo(1)))
|
||||
.andExpect(jsonPath("$.page.totalPages", greaterThanOrEqualTo(1)))
|
||||
.andExpect(jsonPath("$.page.number", is(0)))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
Matchers.startsWith(REST_SERVER_URL + "config/submissionuploads")))
|
||||
.andExpect(jsonPath("$._embedded.submissionuploads", hasSize(greaterThanOrEqualTo(1))));
|
||||
}
|
||||
}
|
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
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.sql.SQLException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.builder.ItemBuilder;
|
||||
import org.dspace.app.rest.matcher.VersionHistoryMatcher;
|
||||
import org.dspace.app.rest.matcher.VersionMatcher;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.VersionHistory;
|
||||
import org.dspace.versioning.service.VersionHistoryService;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class VersionHistoryRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
|
||||
VersionHistory versionHistory;
|
||||
Item item;
|
||||
Version version;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Autowired
|
||||
private VersionHistoryService versionHistoryService;
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
@Before
|
||||
public void setup() throws SQLException, AuthorizeException {
|
||||
context.turnOffAuthorisationSystem();
|
||||
versionHistory = versionHistoryService.create(context);
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||
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();
|
||||
Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2").build();
|
||||
|
||||
//2. Three public items that are readable by Anonymous with different subjects
|
||||
item = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Public item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
version = versioningService.createNewVersion(context, versionHistory, item, "test", new Date(), 0);
|
||||
context.restoreAuthSystemState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneTest() throws Exception {
|
||||
getClient().perform(get("/api/versioning/versionhistories/" + versionHistory.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", is(VersionHistoryMatcher.matchEntry(versionHistory))));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void findOneForbiddenTest() throws Exception {
|
||||
|
||||
configurationService.setProperty("versioning.item.history.view.admin", true);
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/versioning/versionhistories/" + versionHistory.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
configurationService.setProperty("versioning.item.history.view.admin", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneWrongIDTest() throws Exception {
|
||||
int wrongVersionHistoryId = (versionHistory.getID() + 5) * 57;
|
||||
getClient().perform(get("/api/versioning/versionhistories/" + wrongVersionHistoryId))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
}
|
||||
@Test
|
||||
public void findVersionsOneWrongIDTest() throws Exception {
|
||||
int wrongVersionHistoryId = (versionHistory.getID() + 5) * 57;
|
||||
getClient().perform(get("/api/versioning/versionhistories/" + wrongVersionHistoryId + "/versions"))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findVersionsOfVersionHistoryTest() throws Exception {
|
||||
Version version = versionHistoryService.getFirstVersion(context, versionHistory);
|
||||
getClient().perform(get("/api/versioning/versionhistories/" + versionHistory.getID() + "/versions"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.versions", contains(VersionMatcher.matchEntry(version))));
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
Version secondVersion = versioningService
|
||||
.createNewVersion(context, versionHistory, item, "test", new Date(), 0);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(get("/api/versioning/versionhistories/" + versionHistory.getID() + "/versions"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.versions", containsInAnyOrder(VersionMatcher.matchEntry(version),
|
||||
VersionMatcher
|
||||
.matchEntry(secondVersion))));
|
||||
|
||||
}
|
||||
@Test
|
||||
public void findVersionsOfVersionHistoryPaginationTest() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
Version version = versionHistoryService.getFirstVersion(context, versionHistory);
|
||||
Version secondVersion = versioningService
|
||||
.createNewVersion(context, versionHistory, item, "test", new Date(), 0);
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient().perform(get("/api/versioning/versionhistories/" + versionHistory.getID() + "/versions")
|
||||
.param("size", "1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.versions", contains(VersionMatcher.matchEntry(secondVersion))))
|
||||
.andExpect(jsonPath("$._embedded.versions",
|
||||
Matchers.not(contains(VersionMatcher.matchEntry(version)))));
|
||||
getClient().perform(get("/api/versioning/versionhistories/" + versionHistory.getID() + "/versions")
|
||||
.param("size", "1")
|
||||
.param("page", "1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.versions", contains(VersionMatcher.matchEntry(version))))
|
||||
.andExpect(jsonPath("$._embedded.versions",
|
||||
Matchers.not(contains(VersionMatcher.matchEntry(secondVersion)))));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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 org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.builder.ItemBuilder;
|
||||
import org.dspace.app.rest.matcher.ItemMatcher;
|
||||
import org.dspace.app.rest.matcher.VersionMatcher;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.versioning.Version;
|
||||
import org.dspace.versioning.service.VersioningService;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class VersionRestRepositoryIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
Item item;
|
||||
Version version;
|
||||
|
||||
@Autowired
|
||||
private ItemService itemService;
|
||||
|
||||
@Autowired
|
||||
private VersioningService versioningService;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||
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();
|
||||
Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2").build();
|
||||
|
||||
//2. Three public items that are readable by Anonymous with different subjects
|
||||
item = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Public item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
version = versioningService.createNewVersion(context, item);
|
||||
context.restoreAuthSystemState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneTest() throws Exception {
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(VersionMatcher.matchEntry(version))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneSubmitterNameVisisbleTest() throws Exception {
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(VersionMatcher.matchEntry(version))))
|
||||
.andExpect(jsonPath("$.submitterName", Matchers.is(version.getEPerson().getFullName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneSubmitterNameConfigurationPropertyFalseAdminUserLinkVisibleTest() throws Exception {
|
||||
|
||||
configurationService.setProperty("versioning.item.history.include.submitter", false);
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(VersionMatcher.matchEntry(version))))
|
||||
.andExpect(jsonPath("$.submitterName", Matchers.is(version.getEPerson().getFullName())));
|
||||
|
||||
configurationService.setProperty("versioning.item.history.include.submitter", true);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneSubmitterNameConfigurationPropertyTrueNormalUserLinkVisibleTest() throws Exception {
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(VersionMatcher.matchEntry(version))))
|
||||
.andExpect(jsonPath("$.submitterName", Matchers.is(version.getEPerson().getFullName())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneSubmitterNameConfigurationPropertyTrueAnonUserLinkVisibleTest() throws Exception {
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(VersionMatcher.matchEntry(version))))
|
||||
.andExpect(jsonPath("$.submitterName", Matchers.is(version.getEPerson().getFullName())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneSubmitterNameConfigurationPropertyFalseNormalUserLinkInvisibleTest() throws Exception {
|
||||
|
||||
configurationService.setProperty("versioning.item.history.include.submitter", false);
|
||||
|
||||
String adminToken = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(VersionMatcher.matchEntry(version))))
|
||||
.andExpect(jsonPath("$.submitterName").doesNotExist());
|
||||
|
||||
configurationService.setProperty("versioning.item.history.include.submitter", true);
|
||||
|
||||
}
|
||||
@Test
|
||||
public void findOneUnauthorizedTest() throws Exception {
|
||||
|
||||
getClient().perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findOneForbiddenTest() throws Exception {
|
||||
|
||||
configurationService.setProperty("versioning.item.history.view.admin", true);
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/versioning/versions/" + version.getID()))
|
||||
.andExpect(status().isForbidden());
|
||||
configurationService.setProperty("versioning.item.history.view.admin", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void versionForItemTest() throws Exception {
|
||||
|
||||
getClient().perform(get("/api/core/items/" + version.getItem().getID() + "/version"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(VersionMatcher.matchEntry(version))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void versionItemTest() throws Exception {
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + version.getID() + "/item"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", Matchers.is(ItemMatcher.matchItemProperties(version.getItem()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void versionItemTestWrongId() throws Exception {
|
||||
|
||||
String adminToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(adminToken).perform(get("/api/versioning/versions/" + ((version.getID() + 5) * 57) + "/item"))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
}
|
@@ -453,7 +453,7 @@ public class ViewEventRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
|
||||
|
||||
@Test
|
||||
public void postTestAuthenticatedUserSucces() throws Exception {
|
||||
public void postTestAuthenticatedUserSuccess() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
@@ -485,7 +485,7 @@ public class ViewEventRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
|
||||
getClient(token).perform(post("/api/statistics/viewevents")
|
||||
.content(mapper.writeValueAsBytes(viewEventRest))
|
||||
|
@@ -24,7 +24,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -34,6 +33,7 @@ import org.dspace.app.rest.builder.ClaimedTaskBuilder;
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.builder.EPersonBuilder;
|
||||
import org.dspace.app.rest.builder.ItemBuilder;
|
||||
import org.dspace.app.rest.builder.WorkflowItemBuilder;
|
||||
import org.dspace.app.rest.builder.WorkspaceItemBuilder;
|
||||
import org.dspace.app.rest.matcher.CollectionMatcher;
|
||||
@@ -668,15 +668,15 @@ public class WorkflowItemRestRepositoryIT extends AbstractControllerIntegrationT
|
||||
.andExpect(status().is(200));
|
||||
|
||||
// a workspaceitem should exist now in the submitter workspace
|
||||
getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.workspaceitems", Matchers.containsInAnyOrder(
|
||||
WorkspaceItemMatcher.matchItemWithTitleAndDateIssued(null, "Workflow Item 1",
|
||||
"2017-10-17"))))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/submission/workspaceitems")))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
|
||||
getClient(tokenSubmitter).perform(get("/api/submission/workspaceitems/search/findBySubmitter")
|
||||
.param("uuid", submitter.getID().toString()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._embedded.workspaceitems", Matchers.containsInAnyOrder(
|
||||
WorkspaceItemMatcher.matchItemWithTitleAndDateIssued(null, "Workflow Item 1",
|
||||
"2017-10-17"))))
|
||||
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/submission/workspaceitems")))
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1564,6 +1564,153 @@ public class WorkflowItemRestRepositoryIT extends AbstractControllerIntegrationT
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void findByItemUuidTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||
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")
|
||||
.withWorkflowGroup(1, admin).build();
|
||||
|
||||
//2. a workflow item
|
||||
XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1)
|
||||
.withTitle("Workflow Item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
String authToken = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
getClient(authToken).perform(get("/api/workflow/workflowitems/search/item")
|
||||
.param("uuid", String.valueOf(witem.getItem().getID())))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$",
|
||||
Matchers.is(
|
||||
WorkflowItemMatcher.matchItemWithTitleAndDateIssuedAndSubject(witem,
|
||||
"Workflow Item 1", "2017-10-17", "ExtraEntry"))));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByItemUuidMissingParameterTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||
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")
|
||||
.withWorkflowGroup(1, admin).build();
|
||||
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
getClient(token).perform(get("/api/workflow/workflowitems/search/item"))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByItemUuidDoesntExistTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||
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")
|
||||
.withWorkflowGroup(1, admin).build();
|
||||
|
||||
|
||||
Item item = ItemBuilder.createItem(context, col1).build();
|
||||
//2. a workspace item
|
||||
XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1)
|
||||
.withTitle("Workflow Item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
getClient(token).perform(get("/api/workflow/workflowitems/search/item")
|
||||
.param("uuid", String.valueOf(item.getID())))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByItemUuidForbiddenTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
context.setCurrentUser(admin);
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||
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")
|
||||
.withWorkflowGroup(1, admin).build();
|
||||
|
||||
|
||||
XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1)
|
||||
.withTitle("Workflow Item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
String token = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(token).perform(get("/api/workflow/workflowitems/search/item")
|
||||
.param("uuid", String.valueOf(witem.getItem().getID())))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByItemUuidUnAuthenticatedTest() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and two collections.
|
||||
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")
|
||||
.withWorkflowGroup(1, admin).build();
|
||||
|
||||
|
||||
XmlWorkflowItem witem = WorkflowItemBuilder.createWorkflowItem(context, col1)
|
||||
.withTitle("Workflow Item 1")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald").withAuthor("Doe, John")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
getClient().perform(get("/api/workflow/workflowitems/search/item")
|
||||
.param("uuid", String.valueOf(witem.getItem().getID())))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stepEmbedTest() throws Exception {
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user