Merge remote-tracking branch 'dspace/master' into w2p-64428_scripts-prototype-importing-and-exporting

Conflicts:
	dspace-server-webapp/src/main/java/org/dspace/app/rest/ScriptProcessesController.java
	dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ScriptRestRepository.java
This commit is contained in:
Raf Ponsaerts
2020-05-28 09:23:19 +02:00
143 changed files with 4170 additions and 971 deletions

View File

@@ -126,15 +126,26 @@ public class Application extends SpringBootServletInitializer {
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
/**
* Create a custom CORS mapping for the DSpace REST API (/api/ paths), based on configured allowed origins.
* @param registry CorsRegistry
*/
@Override
public void addCorsMappings(@NonNull CorsRegistry registry) {
String[] corsAllowedOrigins = configuration.getCorsAllowedOrigins();
boolean corsAllowCredentials = configuration.getCorsAllowCredentials();
if (corsAllowedOrigins != null) {
registry.addMapping("/api/**").allowedMethods(CorsConfiguration.ALL)
.allowedOrigins(corsAllowedOrigins).allowedHeaders("Authorization", "Content-Type",
"X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
"Access-Control-Request-Headers")
.exposedHeaders("Access-Control-Allow-Origin", "Authorization");
// Set Access-Control-Allow-Credentials to "true" and specify which origins are valid
// for our Access-Control-Allow-Origin header
.allowCredentials(corsAllowCredentials).allowedOrigins(corsAllowedOrigins)
// Whitelist of request preflight headers allowed to be sent to us from the client
.allowedHeaders("Authorization", "Content-Type", "X-Requested-With", "accept", "Origin",
"Access-Control-Request-Method", "Access-Control-Request-Headers",
"X-On-Behalf-Of")
// Whitelist of response headers allowed to be sent by us (the server)
.exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials",
"Authorization");
}
}

View File

@@ -81,7 +81,7 @@ public class RelationshipTypeRestController {
List<RelationshipType> list = relationshipTypeService.findByEntityType(context, entityType, -1, -1);
Page<RelationshipTypeRest> relationshipTypeRestPage = converter
.toRestPage(list, pageable, list.size(), utils.obtainProjection());
.toRestPage(list, pageable, utils.obtainProjection());
Page<RelationshipTypeResource> relationshipTypeResources = relationshipTypeRestPage
.map(relationshipTypeRest -> new RelationshipTypeResource(relationshipTypeRest, utils));

View File

@@ -16,6 +16,9 @@ import org.dspace.app.rest.model.ProcessRest;
import org.dspace.app.rest.model.ScriptRest;
import org.dspace.app.rest.model.hateoas.ProcessResource;
import org.dspace.app.rest.repository.ScriptRestRepository;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.core.Context;
import org.dspace.services.RequestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.rest.webmvc.ControllerUtils;
import org.springframework.hateoas.RepresentationModel;
@@ -45,6 +48,9 @@ public class ScriptProcessesController {
@Autowired
private ScriptRestRepository scriptRestRepository;
@Autowired
private RequestService requestService;
/**
* This method can be called by sending a POST request to the system/scripts/{name}/processes endpoint
* This will start a process for the script that matches the given name
@@ -60,8 +66,10 @@ public class ScriptProcessesController {
if (log.isTraceEnabled()) {
log.trace("Starting Process for Script with name: " + scriptName);
}
ProcessRest processRest = scriptRestRepository.startProcess(scriptName, files);
Context context = ContextUtil.obtainContext(requestService.getCurrentRequest().getServletRequest());
ProcessRest processRest = scriptRestRepository.startProcess(context, scriptName, files);
ProcessResource processResource = converter.toResource(processRest);
context.complete();
return ControllerUtils.toResponseEntity(HttpStatus.ACCEPTED, new HttpHeaders(), processResource);
}

View File

@@ -72,7 +72,7 @@ public class WorkflowDefinitionCollectionsLinkRepository extends AbstractDSpaceR
collectionsMappedToWorkflow.addAll(xmlWorkflowFactory.getCollectionHandlesMappedToWorklow(context,
workflowName));
Pageable pageable = optionalPageable != null ? optionalPageable : PageRequest.of(0, 20);
return converter.toRestPage(utils.getPage(collectionsMappedToWorkflow, pageable),
return converter.toRestPage(collectionsMappedToWorkflow, pageable,
projection);
} else {
throw new ResourceNotFoundException("No workflow with name " + workflowName + " is configured");

View File

@@ -55,7 +55,7 @@ public class WorkflowDefinitionStepsLinkRepository extends AbstractDSpaceRestRep
try {
List<Step> steps = xmlWorkflowFactory.getWorkflowByName(workflowName).getSteps();
Pageable pageable = optionalPageable != null ? optionalPageable : PageRequest.of(0, 20);
return converter.toRestPage(utils.getPage(steps, pageable), projection);
return converter.toRestPage(steps, pageable, projection);
} catch (WorkflowConfigurationException e) {
throw new ResourceNotFoundException("No workflow with name " + workflowName + " is configured");
}

View File

@@ -52,6 +52,6 @@ public class WorkflowStepActionsLinkRepository extends AbstractDSpaceRestReposit
Projection projection) {
List<WorkflowActionConfig> actions = xmlWorkflowFactory.getStepByName(workflowStepName).getActions();
Pageable pageable = optionalPageable != null ? optionalPageable : PageRequest.of(0, 20);
return converter.toRestPage(utils.getPage(actions, pageable), projection);
return converter.toRestPage(actions, pageable, projection);
}
}

View File

@@ -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.authorization.impl;
import java.sql.SQLException;
import org.apache.commons.lang3.StringUtils;
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.EPersonRest;
import org.dspace.app.rest.model.SiteRest;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.service.EPersonService;
import org.dspace.services.ConfigurationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* The LoginOnBehalfOf feature. It can be used by Administrators when the webui.user.assumelogin property is set to true
* to allow the admin to login as another user.
* Calling this with the Site URI will check if the current logged in user can use this feature
* without specifying a specific eperson. This will be the case if the logged in user is an Admin
* and if the webui.user.assumelogin is set to true
* Calling this with the EPerson URI will check if the current logged in user can perform the loginOnBehalfOf
* as the given user. This will then additionally check that the eperson given isn't the same as the logged in
* user and it'll also check that the eperson given isn't an admin
*/
@Component
@AuthorizationFeatureDocumentation(name = LoginOnBehalfOfFeature.NAME,
description = "It can be used by administrators to login on behalf of a different user")
public class LoginOnBehalfOfFeature implements AuthorizationFeature {
public static final String NAME = "loginOnBehalfOf";
@Autowired
private AuthorizeService authorizeService;
@Autowired
private ConfigurationService configurationService;
@Autowired
private EPersonService ePersonService;
@Override
public boolean isAuthorized(Context context, BaseObjectRest object) throws SQLException {
if (!StringUtils.equals(object.getType(), SiteRest.NAME) &&
!StringUtils.equals(object.getType(), EPersonRest.NAME)) {
return false;
}
if (!authorizeService.isAdmin(context)) {
return false;
}
if (!configurationService.getBooleanProperty("webui.user.assumelogin")) {
return false;
}
if (StringUtils.equals(object.getType(), EPersonRest.NAME)) {
EPersonRest ePersonRest = (EPersonRest) object;
EPerson currentUser = context.getCurrentUser();
if (StringUtils.equalsIgnoreCase(currentUser.getEmail(), ePersonRest.getEmail())) {
return false;
}
EPerson ePerson = ePersonService.findByEmail(context, ePersonRest.getEmail());
if (authorizeService.isAdmin(context, ePerson)) {
return false;
}
}
return true;
}
@Override
public String[] getSupportedTypes() {
return new String[] {SiteRest.CATEGORY + "." + SiteRest.NAME, EPersonRest.CATEGORY + "." + EPersonRest.NAME};
}
}

View File

@@ -10,6 +10,7 @@ package org.dspace.app.rest.converter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -19,11 +20,13 @@ import javax.annotation.PostConstruct;
import org.apache.log4j.Logger;
import org.dspace.app.rest.link.HalLinkFactory;
import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.BaseObjectRest;
import org.dspace.app.rest.model.RestAddressableModel;
import org.dspace.app.rest.model.RestModel;
import org.dspace.app.rest.model.hateoas.HALResource;
import org.dspace.app.rest.projection.DefaultProjection;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.security.DSpacePermissionEvaluator;
import org.dspace.app.rest.utils.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -34,6 +37,7 @@ import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -64,6 +68,9 @@ public class ConverterService {
@Autowired
private List<Projection> projections;
@Autowired
private DSpacePermissionEvaluator dSpacePermissionEvaluator;
/**
* Converts the given model object to a rest object, using the appropriate {@link DSpaceConverter} and
* the given projection.
@@ -86,6 +93,14 @@ public class ConverterService {
M transformedModel = projection.transformModel(modelObject);
DSpaceConverter<M, R> converter = requireConverter(modelObject.getClass());
R restObject = converter.convert(transformedModel, projection);
if (restObject instanceof BaseObjectRest) {
if (!dSpacePermissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(),
restObject, "READ")) {
log.debug("Access denied on " + restObject.getClass() + " with id: " +
((BaseObjectRest) restObject).getId());
return null;
}
}
if (restObject instanceof RestModel) {
return (R) projection.transformRest((RestModel) restObject);
}
@@ -97,7 +112,6 @@ public class ConverterService {
*
* @param modelObjects the list of model objects.
* @param pageable the pageable.
* @param total the total number of items.
* @param projection the projection to use.
* @param <M> the model object class.
* @param <R> the rest object class.
@@ -105,25 +119,48 @@ public class ConverterService {
* @throws IllegalArgumentException if there is no compatible converter.
* @throws ClassCastException if the converter's return type is not compatible with the inferred return type.
*/
public <M, R> Page<R> toRestPage(List<M> modelObjects, Pageable pageable, long total, Projection projection) {
return new PageImpl<>(modelObjects, pageable, total).map((object) -> toRest(object, projection));
public <M, R> Page<R> toRestPage(List<M> modelObjects, Pageable pageable, Projection projection) {
List<R> transformedList = new LinkedList<>();
for (M modelObject : modelObjects) {
R transformedObject = toRest(modelObject, projection);
if (transformedObject != null) {
transformedList.add(transformedObject);
}
}
if (pageable == null) {
pageable = utils.getPageable(pageable);
}
return utils.getPage(transformedList, pageable);
}
/**
* Converts a list of model objects to a page of rest objects using the given {@link Projection}.
*
* @param modelObjects the page of model objects.
* Converts a list of ModelObjects to a page of Rest Objects using the given {@link Projection}
* This method differences in the sense that we define a total here instead of the size of the list because
* this method will be called if the list is limited through a DB call already and thus we need to give the
* total amount of records in the DB; not the size of the given list
* @param modelObjects the list of model objects.
* @param pageable the pageable.
* @param total The total amount of objects
* @param projection the projection to use.
* @param <M> the model object class.
* @param <R> the rest object class.
* @return the page.
* @throws IllegalArgumentException if there is no compatible converter.
* @throws ClassCastException if the converter's return type is not compatible with the inferred return type.
*/
public <M, R> Page<R> toRestPage(Page<M> modelObjects, Projection projection) {
return modelObjects.map((object) -> toRest(object, projection));
public <M, R> Page<R> toRestPage(List<M> modelObjects, Pageable pageable, long total, Projection projection) {
List<R> transformedList = new LinkedList<>();
for (M modelObject : modelObjects) {
R transformedObject = toRest(modelObject, projection);
if (transformedObject != null) {
transformedList.add(transformedObject);
}
}
if (pageable == null) {
pageable = utils.getPageable(pageable);
}
return new PageImpl(transformedList, pageable, total);
}
/**
* Gets the converter supporting the given class as input.
*
@@ -177,6 +214,9 @@ public class ConverterService {
* @return the fully converted resource, with all automatic links and embeds applied.
*/
public <T extends HALResource> T toResource(RestModel restObject, Link... oldLinks) {
if (restObject == null) {
return null;
}
T halResource = getResource(restObject);
if (restObject instanceof RestAddressableModel) {
utils.embedOrLinkClassLevelRels(halResource, oldLinks);

View File

@@ -45,8 +45,7 @@ public class AuthorizationFeatureRestRepository extends DSpaceRestRepository<Aut
@PreAuthorize("hasAuthority('ADMIN')")
@Override
public Page<AuthorizationFeatureRest> findAll(Context context, Pageable pageable) {
return converter.toRestPage(utils.getPage(authorizationFeatureService.findAll(),
pageable), utils.obtainProjection());
return converter.toRestPage(authorizationFeatureService.findAll(), pageable, utils.obtainProjection());
}
@PreAuthorize("hasAuthority('ADMIN')")
@@ -64,6 +63,6 @@ public class AuthorizationFeatureRestRepository extends DSpaceRestRepository<Aut
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());
return converter.toRestPage(foundFeatures, pageable, utils.obtainProjection());
}
}

View File

@@ -12,6 +12,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.apache.commons.lang3.ObjectUtils;
import org.dspace.app.rest.Parameter;
import org.dspace.app.rest.SearchRestMethod;
import org.dspace.app.rest.authorization.Authorization;
@@ -155,7 +156,7 @@ public class AuthorizationRestRepository extends DSpaceRestRepository<Authorizat
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) {
if (ObjectUtils.notEqual(currUser, user)) {
// Temporarily change the Context's current user in order to retrieve
// authorizations based on that user
context.switchContextUser(user);
@@ -173,7 +174,7 @@ public class AuthorizationRestRepository extends DSpaceRestRepository<Authorizat
// restore the real current user
context.restoreContextUser();
}
return converter.toRestPage(utils.getPage(authorizations, pageable), utils.obtainProjection());
return converter.toRestPage(authorizations, pageable, utils.obtainProjection());
}
/**

View File

@@ -42,6 +42,7 @@ public class BitstreamFormatRestRepository extends DSpaceRestRepository<Bitstrea
BitstreamFormatService bitstreamFormatService;
@Override
@PreAuthorize("permitAll()")
public BitstreamFormatRest findOne(Context context, Integer id) {
BitstreamFormat bit = null;
try {
@@ -59,7 +60,7 @@ public class BitstreamFormatRestRepository extends DSpaceRestRepository<Bitstrea
public Page<BitstreamFormatRest> findAll(Context context, Pageable pageable) {
try {
List<BitstreamFormat> bit = bitstreamFormatService.findAll(context);
return converter.toRestPage(utils.getPage(bit, pageable), utils.obtainProjection());
return converter.toRestPage(bit, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -16,6 +16,7 @@ import org.dspace.browse.BrowseIndex;
import org.dspace.core.Context;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
@@ -27,6 +28,7 @@ import org.springframework.stereotype.Component;
public class BrowseIndexRestRepository extends DSpaceRestRepository<BrowseIndexRest, String> {
@Override
@PreAuthorize("permitAll()")
public BrowseIndexRest findOne(Context context, String name) {
BrowseIndexRest bi = null;
BrowseIndex bix;

View File

@@ -15,7 +15,6 @@ import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.model.BitstreamRest;
import org.dspace.app.rest.model.BundleRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService;
@@ -52,8 +51,7 @@ public class BundleBitstreamLinkRepository extends AbstractDSpaceRestRepository
throw new ResourceNotFoundException("No such bundle: " + bundleId);
}
Pageable pageable = utils.getPageable(optionalPageable);
Page<Bitstream> page = utils.getPage(bundle.getBitstreams(), pageable);
return converter.toRestPage(page, projection);
return converter.toRestPage(bundle.getBitstreams(), pageable, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}

View File

@@ -108,7 +108,7 @@ public class ClaimedTaskRestRepository extends DSpaceRestRepository<ClaimedTaskR
if (authorizeService.isAdmin(context) || userID.equals(currentUser.getID())) {
EPerson ep = epersonService.find(context, userID);
List<ClaimedTask> tasks = claimedTaskService.findByEperson(context, ep);
return converter.toRestPage(utils.getPage(tasks, pageable), utils.obtainProjection());
return converter.toRestPage(tasks, pageable, utils.obtainProjection());
} else {
throw new RESTAuthorizationException("Only administrators can search for claimed tasks of other users");
}

View File

@@ -72,6 +72,9 @@ public class CollectionBitstreamReadGroupLinkRepository extends AbstractDSpaceRe
}
List<Group> bitstreamGroups = authorizeService
.getAuthorizedGroups(context, collection, Constants.DEFAULT_BITSTREAM_READ);
if (bitstreamGroups == null || bitstreamGroups.isEmpty()) {
return null;
}
Group bitstreamReadGroup = bitstreamGroups.get(0);
if (bitstreamReadGroup == null) {

View File

@@ -175,7 +175,7 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
+ " not found");
}
List<Collection> collections = cs.findAuthorized(context, com, Constants.ADD);
return converter.toRestPage(utils.getPage(collections, pageable), utils.obtainProjection());
return converter.toRestPage(collections, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
@@ -186,7 +186,7 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
try {
Context context = obtainContext();
List<Collection> collections = cs.findAuthorizedOptimized(context, Constants.ADD);
return converter.toRestPage(utils.getPage(collections, pageable), utils.obtainProjection());
return converter.toRestPage(collections, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -201,7 +201,7 @@ public class CommunityRestRepository extends DSpaceObjectRestRepository<Communit
public Page<CommunityRest> findAllTop(Pageable pageable) {
try {
List<Community> communities = cs.findAllTop(obtainContext());
return converter.toRestPage(utils.getPage(communities, pageable), utils.obtainProjection());
return converter.toRestPage(communities, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -32,6 +32,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.multipart.MultipartFile;
/**
@@ -122,6 +123,7 @@ public abstract class DSpaceRestRepository<T extends RestAddressableModel, ID ex
* the rest object id
* @return the REST object identified by its ID
*/
@PreAuthorize("hasAuthority('ADMIN')")
public abstract T findOne(Context context, ID id);
@Override

View File

@@ -17,7 +17,6 @@ import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -51,8 +50,7 @@ public class EPersonGroupLinkRepository extends AbstractDSpaceRestRepository
if (eperson == null) {
throw new ResourceNotFoundException("No such eperson: " + epersonId);
}
Page<Group> groups = utils.getPage(eperson.getGroups(), optionalPageable);
return converter.toRestPage(groups, projection);
return converter.toRestPage(eperson.getGroups(), optionalPageable, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}

View File

@@ -18,6 +18,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.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
@@ -29,6 +30,7 @@ public class EntityTypeRestRepository extends DSpaceRestRepository<EntityTypeRes
@Autowired
private EntityTypeService entityTypeService;
@PreAuthorize("permitAll()")
public EntityTypeRest findOne(Context context, Integer integer) {
try {
EntityType entityType = entityTypeService.find(context, integer);
@@ -44,7 +46,7 @@ public class EntityTypeRestRepository extends DSpaceRestRepository<EntityTypeRes
public Page<EntityTypeRest> findAll(Context context, Pageable pageable) {
try {
List<EntityType> entityTypes = entityTypeService.findAll(context);
return converter.toRestPage(utils.getPage(entityTypes, pageable), utils.obtainProjection());
return converter.toRestPage(entityTypes, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -21,6 +21,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.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
/**
@@ -77,6 +78,7 @@ public class ExternalSourceRestRepository extends DSpaceRestRepository<ExternalS
}
@Override
@PreAuthorize("permitAll()")
public ExternalSourceRest findOne(Context context, String externalSourceName) {
ExternalDataProvider externalDataProvider = externalDataService.getExternalDataProvider(externalSourceName);
if (externalDataProvider == null) {

View File

@@ -15,7 +15,6 @@ import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -46,8 +45,7 @@ public class GroupEPersonLinkRepository extends AbstractDSpaceRestRepository
if (group == null) {
throw new ResourceNotFoundException("No such group: " + groupId);
}
Page<EPerson> ePersons = utils.getPage(group.getMembers(), optionalPageable);
return converter.toRestPage(ePersons, projection);
return converter.toRestPage(group.getMembers(), optionalPageable, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}

View File

@@ -45,8 +45,7 @@ public class GroupGroupLinkRepository extends AbstractDSpaceRestRepository
if (group == null) {
throw new ResourceNotFoundException("No such group: " + groupId);
}
Page<Group> groups = utils.getPage(group.getMemberGroups(), optionalPageable);
return converter.toRestPage(groups, projection);
return converter.toRestPage(group.getMemberGroups(), optionalPageable, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}

View File

@@ -15,7 +15,6 @@ import javax.servlet.http.HttpServletRequest;
import org.dspace.app.rest.model.BundleRest;
import org.dspace.app.rest.model.ItemRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.content.Bundle;
import org.dspace.content.Item;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
@@ -47,8 +46,7 @@ public class ItemBundleLinkRepository extends AbstractDSpaceRestRepository
if (item == null) {
throw new ResourceNotFoundException("No such item: " + itemId);
}
Page<Bundle> bundlePage = utils.getPage(item.getBundles(), optionalPageable);
return converter.toRestPage(bundlePage, projection);
return converter.toRestPage(item.getBundles(), optionalPageable, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.repository;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -49,10 +50,10 @@ public class ItemMappedCollectionLinkRepository extends AbstractDSpaceRestReposi
throw new ResourceNotFoundException("No such item: " + itemId);
}
UUID owningCollectionId = item.getOwningCollection() == null ? null : item.getOwningCollection().getID();
Page<Collection> mappedCollectionPage = utils.getPage(item.getCollections().stream()
.filter((collection) -> !collection.getID().equals(owningCollectionId))
.collect(Collectors.toList()), optionalPageable);
return converter.toRestPage(mappedCollectionPage, projection);
List<Collection> collections = item.getCollections().stream()
.filter((collection) -> !collection.getID().equals(owningCollectionId))
.collect(Collectors.toList());
return converter.toRestPage(collections, optionalPageable, projection);
} catch (SQLException e) {
throw new RuntimeException(e);
}

View File

@@ -53,6 +53,7 @@ public class MetadataFieldRestRepository extends DSpaceRestRepository<MetadataFi
MetadataSchemaService metadataSchemaService;
@Override
@PreAuthorize("permitAll()")
public MetadataFieldRest findOne(Context context, Integer id) {
MetadataField metadataField = null;
try {
@@ -70,7 +71,7 @@ public class MetadataFieldRestRepository extends DSpaceRestRepository<MetadataFi
public Page<MetadataFieldRest> findAll(Context context, Pageable pageable) {
try {
List<MetadataField> metadataFields = metadataFieldService.findAll(context);
return converter.toRestPage(utils.getPage(metadataFields, pageable), utils.obtainProjection());
return converter.toRestPage(metadataFields, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}
@@ -86,7 +87,7 @@ public class MetadataFieldRestRepository extends DSpaceRestRepository<MetadataFi
return null;
}
List<MetadataField> metadataFields = metadataFieldService.findAllInSchema(context, schema);
return converter.toRestPage(utils.getPage(metadataFields, pageable), utils.obtainProjection());
return converter.toRestPage(metadataFields, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -45,6 +45,7 @@ public class MetadataSchemaRestRepository extends DSpaceRestRepository<MetadataS
MetadataSchemaService metadataSchemaService;
@Override
@PreAuthorize("permitAll()")
public MetadataSchemaRest findOne(Context context, Integer id) {
MetadataSchema metadataSchema = null;
try {
@@ -62,7 +63,7 @@ public class MetadataSchemaRestRepository extends DSpaceRestRepository<MetadataS
public Page<MetadataSchemaRest> findAll(Context context, Pageable pageable) {
try {
List<MetadataSchema> metadataSchemas = metadataSchemaService.findAll(context);
return converter.toRestPage(utils.getPage(metadataSchemas, pageable), utils.obtainProjection());
return converter.toRestPage(metadataSchemas, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -101,7 +101,7 @@ public class PoolTaskRestRepository extends DSpaceRestRepository<PoolTaskRest, I
if (authorizeService.isAdmin(context) || userID.equals(currentUser.getID())) {
EPerson ep = epersonService.find(context, userID);
List<PoolTask> tasks = poolTaskService.findByEperson(context, ep);
return converter.toRestPage(utils.getPage(tasks, pageable), utils.obtainProjection());
return converter.toRestPage(tasks, pageable, utils.obtainProjection());
} else {
throw new RESTAuthorizationException("Only administrators can search for pool tasks of other users");
}

View File

@@ -40,6 +40,7 @@ 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;
/**
@@ -71,6 +72,7 @@ public class RelationshipRestRepository extends DSpaceRestRepository<Relationshi
private RequestService requestService;
@Override
@PreAuthorize("permitAll()")
public RelationshipRest findOne(Context context, Integer integer) {
try {
return converter.toRest(relationshipService.find(context, integer), utils.obtainProjection());

View File

@@ -17,6 +17,7 @@ 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;
/**
@@ -29,6 +30,7 @@ public class RelationshipTypeRestRepository extends DSpaceRestRepository<Relatio
private RelationshipTypeService relationshipTypeService;
@Override
@PreAuthorize("permitAll()")
public RelationshipTypeRest findOne(Context context, Integer integer) {
try {
return converter.toRest(relationshipTypeService.find(context, integer), utils.obtainProjection());
@@ -41,7 +43,7 @@ public class RelationshipTypeRestRepository extends DSpaceRestRepository<Relatio
public Page<RelationshipTypeRest> findAll(Context context, Pageable pageable) {
try {
List<RelationshipType> relationshipTypes = relationshipTypeService.findAll(context);
return converter.toRestPage(utils.getPage(relationshipTypes, pageable), utils.obtainProjection());
return converter.toRestPage(relationshipTypes, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -37,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
@@ -55,6 +56,7 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
private DSpaceRunnableParameterConverter dSpaceRunnableParameterConverter;
@Override
@PreAuthorize("permitAll()")
public ScriptRest findOne(Context context, String name) {
ScriptConfiguration scriptConfiguration = scriptService.getScriptConfiguration(name);
@@ -71,7 +73,7 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
@Override
public Page<ScriptRest> findAll(Context context, Pageable pageable) {
List<ScriptConfiguration> scriptConfigurations = scriptService.getScriptConfigurations(context);
return converter.toRestPage(utils.getPage(scriptConfigurations, pageable), utils.obtainProjection());
return converter.toRestPage(scriptConfigurations, pageable, utils.obtainProjection());
}
@Override
@@ -87,10 +89,8 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
* @throws SQLException If something goes wrong
* @throws IOException If something goes wrong
*/
public ProcessRest startProcess(String scriptName,
List<MultipartFile> files)
throws IOException, AuthorizeException, IllegalAccessException, InstantiationException {
Context context = obtainContext();
public ProcessRest startProcess(Context context, String scriptName, List<MultipartFile> files) throws SQLException,
IOException, AuthorizeException, IllegalAccessException, InstantiationException {
String properties = requestService.getCurrentRequest().getServletRequest().getParameter("properties");
List<DSpaceCommandLineParameter> dSpaceCommandLineParameters =
processPropertiesToDSpaceCommandLineParameters(properties);
@@ -104,16 +104,8 @@ public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, Strin
RestDSpaceRunnableHandler restDSpaceRunnableHandler = new RestDSpaceRunnableHandler(
context.getCurrentUser(), scriptName, dSpaceCommandLineParameters);
List<String> args = constructArgs(dSpaceCommandLineParameters);
try {
runDSpaceScript(files, context, scriptToExecute, restDSpaceRunnableHandler, args);
context.complete();
return converter.toRest(restDSpaceRunnableHandler.getProcess(), utils.obtainProjection());
} catch (SQLException e) {
log.error("Failed to create a process with user: " + context.getCurrentUser() +
" scriptname: " + scriptName + " and parameters " + DSpaceCommandLineParameter
.concatenate(dSpaceCommandLineParameters), e);
}
return null;
runDSpaceScript(files, context, scriptToExecute, restDSpaceRunnableHandler, args);
return converter.toRest(restDSpaceRunnableHandler.getProcess(context), utils.obtainProjection());
}
private List<DSpaceCommandLineParameter> processPropertiesToDSpaceCommandLineParameters(String propertiesJson)

View File

@@ -43,6 +43,7 @@ public class SiteRestRepository extends DSpaceObjectRestRepository<Site, SiteRes
}
@Override
@PreAuthorize("permitAll()")
public SiteRest findOne(Context context, UUID id) {
Site site = null;
try {
@@ -60,7 +61,7 @@ public class SiteRestRepository extends DSpaceObjectRestRepository<Site, SiteRes
public Page<SiteRest> findAll(Context context, Pageable pageable) {
try {
List<Site> sites = Arrays.asList(sitesv.findSite(context));
return converter.toRestPage(sites, pageable, 1L, utils.obtainProjection());
return converter.toRestPage(sites, pageable, utils.obtainProjection());
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -64,6 +64,6 @@ public class VersionsLinkRepository extends AbstractDSpaceRestRepository
}
List<Version> versions = versioningService.getVersionsByHistory(context, versionHistory);
Pageable pageable = optionalPageable != null ? optionalPageable : PageRequest.of(0, 20);
return converter.toRestPage(utils.getPage(versions, pageable), projection);
return converter.toRestPage(versions, pageable, projection);
}
}

View File

@@ -61,7 +61,7 @@ public class WorkflowDefinitionRestRepository extends DSpaceRestRepository<Workf
@PreAuthorize("hasAuthority('AUTHENTICATED')")
public Page<WorkflowDefinitionRest> findAll(Context context, Pageable pageable) {
List<Workflow> workflows = xmlWorkflowFactory.getAllConfiguredWorkflows();
return converter.toRestPage(utils.getPage(workflows, pageable), utils.obtainProjection());
return converter.toRestPage(workflows, pageable, utils.obtainProjection());
}
/**

View File

@@ -77,8 +77,7 @@ public class DSpaceObjectMetadataAddOperation<R extends DSpaceObject> extends Pa
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_ADD)
&& objectToMatch instanceof DSpaceObject);
}

View File

@@ -94,8 +94,7 @@ public class DSpaceObjectMetadataCopyOperation<R extends DSpaceObject> extends P
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_COPY)
&& objectToMatch instanceof DSpaceObject);
}

View File

@@ -76,8 +76,7 @@ public class DSpaceObjectMetadataMoveOperation<R extends DSpaceObject> extends P
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_MOVE)
&& objectToMatch instanceof DSpaceObject);
}

View File

@@ -39,7 +39,7 @@ public final class DSpaceObjectMetadataPatchUtils {
/**
* Path in json body of patch that uses these metadata operations
*/
protected static final String OPERATION_METADATA_PATH = "/metadata";
public static final String OPERATION_METADATA_PATH = "/metadata";
private DSpaceObjectMetadataPatchUtils() {
}

View File

@@ -99,8 +99,7 @@ public class DSpaceObjectMetadataRemoveOperation<R extends DSpaceObject> extends
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE)
&& objectToMatch instanceof DSpaceObject);
}

View File

@@ -214,8 +214,7 @@ public class DSpaceObjectMetadataReplaceOperation<R extends DSpaceObject> extend
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE)
&& objectToMatch instanceof DSpaceObject);
}

View File

@@ -214,17 +214,13 @@ public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
/**
* This method will return the process created by this handler
* @return The Process database object created by this handler
* @param context
*/
public Process getProcess() {
Context context = new Context();
public Process getProcess(Context context) {
try {
return processService.find(context, processId);
} catch (SQLException e) {
log.error("RestDSpaceRunnableHandler with process: " + processId + " could not be found", e);
} finally {
if (context.isValid()) {
context.abort();
}
}
return null;
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.AuthenticationStatusRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to AuthenticationStatusRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class AuthenticationStatusRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(AuthenticationStatusRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.AuthnRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to AuthnRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class AuthnRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(AuthnRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.AuthorizationFeatureRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to AuthorizationRest endpoints. It will return true because access can be granted
* anytime it's linked from another resource.
*/
@Component
public class AuthorizationFeatureRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(AuthorizationFeatureRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.BitstreamFormatRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to BitstreamFormatRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class BitstreamFormatRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(BitstreamFormatRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.BrowseIndexRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to BrowseIndexRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class BrowseIndexRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(BrowseIndexRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.DiscoveryResultsRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to DiscoveryResultsRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class DiscoveryResultRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(DiscoveryResultsRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -14,6 +14,7 @@ import java.util.UUID;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.model.patch.Patch;
import org.dspace.app.rest.repository.patch.operation.DSpaceObjectMetadataPatchUtils;
import org.dspace.app.rest.repository.patch.operation.EPersonPasswordReplaceOperation;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.authorize.service.AuthorizeService;
@@ -102,10 +103,11 @@ public class EPersonRestPermissionEvaluatorPlugin extends RestObjectPermissionEv
/**
* The entire Patch request should be denied if it contains operations that are
* restricted to Dspace administrators. The authenticated user is currently allowed to
* update their own password.
* update their own password and their own metadata.
*/
for (Operation op: operations) {
if (!op.getPath().contentEquals(EPersonPasswordReplaceOperation.OPERATION_PASSWORD_CHANGE)) {
if (!(op.getPath().contentEquals(EPersonPasswordReplaceOperation.OPERATION_PASSWORD_CHANGE)
|| (op.getPath().startsWith(DSpaceObjectMetadataPatchUtils.OPERATION_METADATA_PATH)))) {
return false;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.EntityTypeRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to EntityTypeRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class EntityTypeRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(EntityTypeRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.ExternalSourceEntryRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to ExternalSourceEntryRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class ExternalSourceEntryRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(ExternalSourceEntryRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.ExternalSourceRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to ExternalSourceRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class ExternalSourceRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(ExternalSourceRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.FacetConfigurationRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to FacetConfigurationRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class FacetConfigurationRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(FacetConfigurationRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.HarvestedCollectionRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to HarvestedCollectionRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class HarvestedCollectionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(HarvestedCollectionRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.HarvesterMetadataRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to HarvesterMetadataRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class HarvesterMetadataRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(HarvesterMetadataRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.MetadataFieldRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to MetadataFieldRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class MetadataFieldRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(MetadataFieldRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.MetadataSchemaRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to MetadataSchemaRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class MetadataSchemaRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(MetadataSchemaRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.RelationshipRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to RelationshipRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class RelationshipRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(RelationshipRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.RelationshipTypeRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to RelationshipTypeRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class RelationshipTypeRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(RelationshipTypeRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -9,6 +9,7 @@ package org.dspace.app.rest.security;
import java.io.Serializable;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.BaseObjectRest;
import org.dspace.app.rest.model.patch.Patch;
import org.springframework.security.core.Authentication;
@@ -34,7 +35,8 @@ public abstract class RestObjectPermissionEvaluatorPlugin implements RestPermis
public boolean hasPermission(Authentication authentication, Object targetDomainObject,
Object permission) {
BaseObjectRest restObject = (BaseObjectRest) targetDomainObject;
return hasPermission(authentication, restObject.getId(), restObject.getType(), permission);
return hasPermission(authentication, restObject.getId(), StringUtils.upperCase(restObject.getType()),
permission);
}
@Override

View File

@@ -0,0 +1,30 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.ScriptRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle Permissions for the {@link ScriptRest} object and its calls
*/
@Component
public class ScriptRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(ScriptRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SearchConfigurationRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SearchConfigurationRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SearchConfigurationRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SearchConfigurationRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SearchEventRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SearchEventRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SearchEventRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SearchEventRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SearchResultsRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SearchResultsRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SearchResultsRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SearchResultsRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SearchSupportRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SearchSupportRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SearchSupportRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SearchSupportRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SiteRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SiteRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SiteRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SiteRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -8,18 +8,29 @@
package org.dspace.app.rest.security;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.EPersonService;
import org.dspace.services.ConfigurationService;
import org.dspace.services.RequestService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.util.UUIDUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
@@ -37,12 +48,20 @@ public class StatelessAuthenticationFilter extends BasicAuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(StatelessAuthenticationFilter.class);
private static final String ON_BEHALF_OF_REQUEST_PARAM = "X-On-Behalf-Of";
private RestAuthenticationService restAuthenticationService;
private EPersonRestAuthenticationProvider authenticationProvider;
private RequestService requestService;
private AuthorizeService authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
private EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
public StatelessAuthenticationFilter(AuthenticationManager authenticationManager,
RestAuthenticationService restAuthenticationService,
EPersonRestAuthenticationProvider authenticationProvider,
@@ -58,16 +77,45 @@ public class StatelessAuthenticationFilter extends BasicAuthenticationFilter {
HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
Authentication authentication = getAuthentication(req);
Authentication authentication = null;
try {
authentication = getAuthentication(req, res);
} catch (AuthorizeException e) {
res.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
log.error(e.getMessage(), e);
return;
} catch (IllegalArgumentException | SQLException e) {
res.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
log.error(e.getMessage(), e);
return;
} catch (AccessDeniedException e) {
res.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
log.error(e.getMessage(), e);
return;
}
if (authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
restAuthenticationService.invalidateAuthenticationCookie(res);
}
chain.doFilter(req, res);
}
private Authentication getAuthentication(HttpServletRequest request) {
/**
* This method returns an Authentication object
* This Authentication object will be attempted to be for the eperson with the uuid in the parameter. Incase
* this is able to be done properly, we'll be returning the EPerson Authentication.
* If the Authentication object returned is not null, we'll be logged in as this EPerson given through from the
* request.
* If something goes wrong, we'll throw an IllegalArgumentException, AccessDeniedException or AuthorizeException
* depending on what went wrong. This will be caught in the calling method and handled appropriately with the
* corresponding response codes
* @param request The current request
* @param res The current response
* @return An Authentication object for the EPerson with the uuid in the parameter
* @throws IOException If something goes wrong
*/
private Authentication getAuthentication(HttpServletRequest request, HttpServletResponse res)
throws AuthorizeException, SQLException {
if (restAuthenticationService.hasAuthenticationData(request)) {
// parse the token.
@@ -81,15 +129,55 @@ public class StatelessAuthenticationFilter extends BasicAuthenticationFilter {
//Get the Spring authorities for this eperson
List<GrantedAuthority> authorities = authenticationProvider.getGrantedAuthorities(context, eperson);
String onBehalfOfParameterValue = request.getHeader(ON_BEHALF_OF_REQUEST_PARAM);
if (onBehalfOfParameterValue != null) {
if (configurationService.getBooleanProperty("webui.user.assumelogin")) {
return getOnBehalfOfAuthentication(context, onBehalfOfParameterValue, res);
} else {
throw new IllegalArgumentException("The login as feature is not allowed" +
" due to the current configuration");
}
}
//Return the Spring authentication object
return new DSpaceAuthentication(eperson.getEmail(), authorities);
} else {
return null;
}
} else {
if (request.getHeader(ON_BEHALF_OF_REQUEST_PARAM) != null) {
throw new AuthorizeException("Only admins are allowed to use the login as feature");
}
}
return null;
}
private Authentication getOnBehalfOfAuthentication(Context context, String onBehalfOfParameterValue,
HttpServletResponse res) throws SQLException {
if (!authorizeService.isAdmin(context)) {
throw new AccessDeniedException("Only admins are allowed to use the login as feature");
}
UUID epersonUuid = UUIDUtils.fromString(onBehalfOfParameterValue);
if (epersonUuid == null) {
throw new IllegalArgumentException("The given UUID in the X-On-Behalf-Of header " +
"was not a proper UUID");
}
EPerson onBehalfOfEPerson = ePersonService.find(context, epersonUuid);
if (onBehalfOfEPerson == null) {
throw new IllegalArgumentException("The given UUID in the X-On-Behalf-Of header " +
"was not a proper EPerson UUID");
}
if (!authorizeService.isAdmin(context, onBehalfOfEPerson)) {
requestService.setCurrentUserId(epersonUuid);
context.switchContextUser(onBehalfOfEPerson);
return new DSpaceAuthentication(onBehalfOfEPerson.getEmail(),
authenticationProvider.getGrantedAuthorities(context, onBehalfOfEPerson));
} else {
throw new IllegalArgumentException("You're unable to use the login as feature to log " +
"in as another admin");
}
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.StatisticsSupportRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to StatisticsSupportRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class StatisticsSupportRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(StatisticsSupportRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SubmissionDefinitionRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SubmissionDefinitionRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SubmissionDefinitionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SubmissionDefinitionRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SubmissionFormRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SubmissionFormRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SubmissionFormRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SubmissionFormRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SubmissionUploadRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SubmissionUploadRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SubmissionUploadRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SubmissionUploadRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.SubmissionSectionRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to SubmissionSectionRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class SubmissonSectionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(SubmissionSectionRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.TemplateItemRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to TemplateItemRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class TemplateItemRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(TemplateItemRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.ViewEventRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to ViewEventRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class ViewEventRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(ViewEventRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.WorkflowActionRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to WorkflowActionRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class WorkflowActionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(WorkflowActionRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.WorkflowDefinitionRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to WorkflowDefinitionRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class WorkflowDefinitionRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(WorkflowDefinitionRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,31 @@
/**
* 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 org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.WorkflowStepRest;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* This class will handle calls made to WorkflowStepRest endpoints.
* It will return true because access can be granted anytime it's linked from another resource
*/
@Component
public class WorkflowStepRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
DSpaceRestPermission restPermission) {
if (!StringUtils.equalsIgnoreCase(WorkflowStepRest.NAME, targetType)) {
return false;
}
return true;
}
}

View File

@@ -49,7 +49,8 @@ import org.springframework.security.crypto.keygen.KeyGenerators;
import org.springframework.stereotype.Component;
/**
* Class responsible for creating and parsing JWTs, supports both JWS and JWE
* Class responsible for creating and parsing JSON Web Tokens (JWTs), supports both JWS and JWE
* https://jwt.io/
*
* @author Frederic Van Reet (frederic dot vanreet at atmire dot com)
* @author Tom Desair (tom dot desair at atmire dot com)
@@ -95,12 +96,12 @@ public class JWTTokenHandler implements InitializingBean {
}
/**
* Retrieve EPerson from a jwt
* Retrieve EPerson from a JSON Web Token (JWT)
*
* @param token
* @param request
* @param context
* @return
* @param token token as a string
* @param request current request
* @param context current Context
* @return DSpace EPerson object parsed from the token
* @throws JOSEException
* @throws ParseException
* @throws SQLException
@@ -110,13 +111,14 @@ public class JWTTokenHandler implements InitializingBean {
if (StringUtils.isBlank(token)) {
return null;
}
// parse/decrypt the token
SignedJWT signedJWT = getSignedJWT(token);
// get the claims set from the parsed token
JWTClaimsSet jwtClaimsSet = signedJWT.getJWTClaimsSet();
// retrieve the EPerson from the claims set
EPerson ePerson = getEPerson(context, jwtClaimsSet);
// As long as the JWT is valid, parse all claims and return the EPerson
if (isValidToken(request, signedJWT, jwtClaimsSet, ePerson)) {
log.debug("Received valid token for username: " + ePerson.getEmail());
@@ -133,22 +135,25 @@ public class JWTTokenHandler implements InitializingBean {
}
/**
* Create a jwt with the EPerson details in it
* Create a JWT with the EPerson details in it
*
* @param context
* @param request
* @param previousLoginDate
* @param groups
* @return
* @param context current Context
* @param request current Request
* @param previousLoginDate date of last login (before this one)
* @param groups List of user Groups
* @return string version of signed JWT
* @throws JOSEException
*/
public String createTokenForEPerson(Context context, HttpServletRequest request, Date previousLoginDate,
List<Group> groups) throws JOSEException, SQLException {
// Update the saved session salt for the currently logged in user, returning the user object
EPerson ePerson = updateSessionSalt(context, previousLoginDate);
// Create a claims set based on currently logged in user
JWTClaimsSet claimsSet = buildJwtClaimsSet(context, request);
// Create a signed JWT from those two things
SignedJWT signedJWT = createSignedJWT(request, ePerson, claimsSet);
String token;
@@ -161,6 +166,13 @@ public class JWTTokenHandler implements InitializingBean {
return token;
}
/**
* Invalidate the current Java Web Token (JWT) in the current request
* @param token current token
* @param request current request
* @param context current Context
* @throws Exception
*/
public void invalidateToken(String token, HttpServletRequest request, Context context) throws Exception {
if (StringUtils.isNotBlank(token)) {
@@ -197,6 +209,17 @@ public class JWTTokenHandler implements InitializingBean {
return jweObject;
}
/**
* Determine if current JWT is valid for the given EPerson object.
* To be valid, current JWT *must* have been signed by the EPerson and not be expired.
* If EPerson is null or does not have a known active session, false is returned immediately.
* @param request current request
* @param signedJWT current signed JWT
* @param jwtClaimsSet claims set of current JWT
* @param ePerson EPerson parsed from current signed JWT
* @return true if valid, false otherwise
* @throws JOSEException
*/
private boolean isValidToken(HttpServletRequest request, SignedJWT signedJWT, JWTClaimsSet jwtClaimsSet,
EPerson ePerson) throws JOSEException {
if (ePerson == null || StringUtils.isBlank(ePerson.getSessionSalt())) {
@@ -213,6 +236,15 @@ public class JWTTokenHandler implements InitializingBean {
}
}
/**
* Return the signed JWT.
* If JWT encryption is enabled, decrypt the token and return.
* Otherwise, parse the string into a signed JWT
* @param token string token
* @return parsed (possibly decrypted) SignedJWT
* @throws ParseException
* @throws JOSEException
*/
private SignedJWT getSignedJWT(String token) throws ParseException, JOSEException {
SignedJWT signedJWT;
@@ -227,10 +259,26 @@ public class JWTTokenHandler implements InitializingBean {
return signedJWT;
}
/**
* Based on the given JWT claims set (which should include an EPerson ID), locate the
* corresponding EPerson in the current Context
* @param context current context
* @param jwtClaimsSet JWT claims set
* @return EPerson object (or null, if not found)
* @throws SQLException
*/
private EPerson getEPerson(Context context, JWTClaimsSet jwtClaimsSet) throws SQLException {
return ePersonClaimProvider.getEPerson(context, jwtClaimsSet);
}
/**
* Create a signed JWT from the given EPerson and claims set.
* @param request current request
* @param ePerson EPerson to create signed JWT for
* @param claimsSet claims set of JWT
* @return signed JWT
* @throws JOSEException
*/
private SignedJWT createSignedJWT(HttpServletRequest request, EPerson ePerson, JWTClaimsSet claimsSet)
throws JOSEException {
SignedJWT signedJWT = new SignedJWT(
@@ -241,6 +289,13 @@ public class JWTTokenHandler implements InitializingBean {
return signedJWT;
}
/**
* Create a new JWT claims set based on the current Context (and currently logged in user).
* Set its expiration time based on the configured expiration period.
* @param context current Context
* @param request current Request
* @return new JWTClaimsSet
*/
private JWTClaimsSet buildJwtClaimsSet(Context context, HttpServletRequest request) {
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
@@ -283,6 +338,16 @@ public class JWTTokenHandler implements InitializingBean {
return clientInfoService.getClientIp(request);
}
/**
* Update session salt information for the currently logged in user.
* The session salt is a random key that is saved to EPerson object (and database table) and used to validate
* a JWT on later requests.
* @param context current DSpace Context
* @param previousLoginDate date of last login (prior to this one)
* @return EPerson object of current user, with an updated session salt
* @throws SQLException
*/
private EPerson updateSessionSalt(final Context context, final Date previousLoginDate) throws SQLException {
EPerson ePerson;
@@ -306,6 +371,11 @@ public class JWTTokenHandler implements InitializingBean {
return ePerson;
}
/**
* Retrieve the given secret key from configuration. If not specified, generate a random 32 byte key
* @param property configuration property to check for
* @return configuration value or random 32 byte key
*/
private String getSecret(String property) {
String secret = configurationService.getProperty(property);

View File

@@ -26,15 +26,41 @@ import org.springframework.data.web.config.EnableSpringDataWebSupport;
@ComponentScan( {"org.dspace.app.rest.converter", "org.dspace.app.rest.repository", "org.dspace.app.rest.utils",
"org.dspace.app.configuration"})
public class ApplicationConfig {
// Allowed CORS origins. Defaults to * (everywhere)
// Allowed CORS origins ("Access-Control-Allow-Origin" header)
// Can be overridden in DSpace configuration
@Value("${rest.cors.allowed-origins:*}")
private String corsAllowedOrigins;
@Value("${rest.cors.allowed-origins}")
private String[] corsAllowedOrigins;
// Whether to allow credentials (cookies) in CORS requests ("Access-Control-Allow-Credentials" header)
// Defaults to true. Can be overridden in DSpace configuration
@Value("${rest.cors.allow-credentials:true}")
private boolean corsAllowCredentials;
// Configured User Interface URL (default: http://localhost:3000)
@Value("${dspace.ui.url:http://localhost:3000}")
private String uiURL;
/**
* Return the array of allowed origins (client URLs) for the CORS "Access-Control-Allow-Origin" header
* Used by Application class
* @return Array of URLs
*/
public String[] getCorsAllowedOrigins() {
// Use "rest.cors.allowed-origins" if configured. Otherwise, default to the "dspace.ui.url" setting.
if (corsAllowedOrigins != null) {
return corsAllowedOrigins.split("\\s*,\\s*");
return corsAllowedOrigins;
} else if (uiURL != null) {
return new String[] {uiURL};
}
return null;
}
/**
* Return whether to allow credentials (cookies) on CORS requests. This is used to set the
* CORS "Access-Control-Allow-Credentials" header in Application class.
* @return true or false
*/
public boolean getCorsAllowCredentials() {
return corsAllowCredentials;
}
}

View File

@@ -86,6 +86,7 @@ import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.hateoas.Link;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
@@ -668,7 +669,13 @@ public class Utils {
Object linkedObject = method.invoke(linkRepository, null, contentId, null, projection);
resource.embedResource(rel, wrapForEmbedding(resource, linkedObject, link, oldLinks));
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof RuntimeException) {
// This will be thrown from the LinkRepository if a Resource has been requested that'll try to embed
// something that we don't have READ rights to. It'll then throw an AccessDeniedException from that
// linkRepository and we want to catch it here since we don't want our entire request to fail if a
// subresource of the requested resource is not available to be embedded. Instead we'll log it here
if (e.getTargetException() instanceof AccessDeniedException) {
log.warn("Tried fetching resource: " + linkRest.name() + " for DSpaceObject with ID: " + contentId);
} else if (e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) e.getTargetException();
} else {
throw new RuntimeException(e);

View File

@@ -109,12 +109,9 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
@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())
@@ -603,12 +600,9 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
@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())
@@ -658,16 +652,20 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
getClient(token).perform(get("/api/authn/logout"))
.andExpect(status().isNoContent());
//Check if we are actually logged out (again)
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")));
}
@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())
@@ -687,16 +685,20 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
//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")));
}
@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())
@@ -713,12 +715,9 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
@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())
@@ -738,23 +737,20 @@ public class AuthenticationRestControllerIT extends AbstractControllerIntegratio
//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")));
}
@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))

View File

@@ -22,7 +22,7 @@ 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.converter.SiteConverter;
import org.dspace.app.rest.model.CollectionRest;
import org.dspace.app.rest.model.SiteRest;
import org.dspace.app.rest.projection.DefaultProjection;
@@ -60,7 +60,7 @@ public class AuthorizationFeatureServiceIT extends AbstractIntegrationTestWithDa
private SiteService siteService;
@Autowired
private ConverterService converterService;
private SiteConverter siteConverter;
@Autowired
private AuthorizationFeatureService authzFeatureService;
@@ -143,7 +143,7 @@ public class AuthorizationFeatureServiceIT extends AbstractIntegrationTestWithDa
*/
public void isAuthorizedTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, DefaultProjection.DEFAULT);
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
AuthorizationFeature alwaysTrue = authzFeatureService.find(AlwaysTrueFeature.NAME);
AuthorizationFeature alwaysFalse = authzFeatureService.find(AlwaysFalseFeature.NAME);

View File

@@ -31,7 +31,9 @@ import org.dspace.app.rest.authorization.TrueForUsersInGroupTestFeature;
import org.dspace.app.rest.builder.CommunityBuilder;
import org.dspace.app.rest.builder.EPersonBuilder;
import org.dspace.app.rest.builder.GroupBuilder;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.CommunityConverter;
import org.dspace.app.rest.converter.EPersonConverter;
import org.dspace.app.rest.converter.SiteConverter;
import org.dspace.app.rest.matcher.AuthorizationMatcher;
import org.dspace.app.rest.model.BaseObjectRest;
import org.dspace.app.rest.model.CommunityRest;
@@ -68,14 +70,18 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
private AuthorizationFeatureService authorizationFeatureService;
@Autowired
private ConverterService converterService;
private SiteConverter siteConverter;
@Autowired
private EPersonConverter ePersonConverter;
@Autowired
private CommunityConverter communityConverter;
@Autowired
private ConfigurationService configurationService;
@Autowired
private Utils utils;
private SiteService siteService;
/**
@@ -149,7 +155,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findOneTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, DefaultProjection.DEFAULT);
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
// define three authorizations that we know must exists
Authorization authAdminSite = new Authorization(admin, trueForAdmins, siteRest);
@@ -191,7 +197,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findOneUnauthorizedTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, DefaultProjection.DEFAULT);
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
// define two authorizations that we know must exists
Authorization authAdminSite = new Authorization(admin, alwaysTrue, siteRest);
@@ -215,7 +221,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
public void findOneForbiddenTest() throws Exception {
context.turnOffAuthorisationSystem();
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, DefaultProjection.DEFAULT);
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
EPerson testEPerson = EPersonBuilder.createEPerson(context)
.withEmail("test-authorization@example.com")
.withPassword(password).build();
@@ -251,8 +257,8 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
public void findOneNotFoundTest() throws Exception {
context.turnOffAuthorisationSystem();
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, DefaultProjection.DEFAULT);
EPersonRest epersonRest = converterService.toRest(eperson, DefaultProjection.DEFAULT);
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
EPersonRest epersonRest = ePersonConverter.convert(eperson, DefaultProjection.DEFAULT);
context.restoreAuthSystemState();
String epersonToken = getAuthToken(eperson.getEmail(), password);
@@ -337,7 +343,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findOneInternalServerErrorTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, DefaultProjection.DEFAULT);
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
// define two authorizations that we know will throw exceptions
Authorization authAdminSite = new Authorization(admin, alwaysException, siteRest);
Authorization authNormalUserSite = new Authorization(eperson, alwaysException, siteRest);
@@ -364,7 +370,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// disarm the alwaysThrowExceptionFeature
@@ -700,7 +706,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectUnauthorizedTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// disarm the alwaysThrowExceptionFeature
@@ -727,7 +733,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectForbiddenTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
context.turnOffAuthorisationSystem();
EPerson anotherEperson = EPersonBuilder.createEPerson(context).withEmail("another@example.com")
@@ -756,7 +762,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectInternalServerErrorTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// verify that it works for administrators
@@ -801,7 +807,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
public void findByObjectAndFeatureTest() throws Exception {
context.turnOffAuthorisationSystem();
Community com = CommunityBuilder.createCommunity(context).withName("A test community").build();
CommunityRest comRest = converterService.toRest(com, converterService.getProjection(DefaultProjection.NAME));
CommunityRest comRest = communityConverter.convert(com, DefaultProjection.DEFAULT);
String comUri = utils.linkToSingleResource(comRest, "self").getHref();
context.restoreAuthSystemState();
@@ -879,7 +885,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectAndFeatureNotGrantedTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// verify that it works for administrators
@@ -928,7 +934,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
public void findByNotExistingObjectAndFeatureTest() throws Exception {
String wrongSiteUri = "http://localhost/api/core/sites/" + UUID.randomUUID();
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// disarm the alwaysThrowExceptionFeature
@@ -1012,7 +1018,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
"http://localhost/api/core/sites/this-is-not-an-uuid"
};
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// disarm the alwaysThrowExceptionFeature
configurationService.setProperty("org.dspace.app.rest.authorization.AlwaysThrowExceptionFeature.turnoff", true);
@@ -1097,7 +1103,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectAndFeatureUnauthorizedTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// disarm the alwaysThrowExceptionFeature
@@ -1126,7 +1132,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectAndFeatureForbiddenTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
context.turnOffAuthorisationSystem();
EPerson anotherEperson = EPersonBuilder.createEPerson(context).withEmail("another@example.com")
@@ -1157,7 +1163,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void findByObjectAndFeatureInternalServerErrorTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
// verify that it works for administrators
@@ -1193,7 +1199,7 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
*/
public void verifySpecialGroupMembershipTest() throws Exception {
Site site = siteService.findSite(context);
SiteRest siteRest = converterService.toRest(site, converterService.getProjection(DefaultProjection.NAME));
SiteRest siteRest = siteConverter.convert(site, DefaultProjection.DEFAULT);
String siteUri = utils.linkToSingleResource(siteRest, "self").getHref();
context.turnOffAuthorisationSystem();
// create two normal users and put one in the test group directly
@@ -1329,5 +1335,4 @@ public class AuthorizationRestRepositoryIT extends AbstractControllerIntegration
return (epersonUuid != null ? epersonUuid + "_" : "") + featureName + "_" + type + "_"
+ id.toString();
}
}

View File

@@ -27,7 +27,7 @@ import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.builder.BitstreamFormatBuilder;
import org.dspace.app.rest.builder.EPersonBuilder;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.BitstreamFormatConverter;
import org.dspace.app.rest.matcher.BitstreamFormatMatcher;
import org.dspace.app.rest.matcher.HalMatcher;
import org.dspace.app.rest.model.BitstreamFormatRest;
@@ -51,10 +51,10 @@ import org.springframework.test.web.servlet.MvcResult;
public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrationTest {
@Autowired
ConverterService converter;
BitstreamFormatService bitstreamFormatService;
@Autowired
BitstreamFormatService bitstreamFormatService;
private BitstreamFormatConverter bitstreamFormatConverter;
private final int DEFAULT_AMOUNT_FORMATS = 80;
@@ -92,6 +92,8 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
.withMimeType("application/octet-stream")
.withDescription("Description")
.build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/bitstreamformats"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
@@ -282,7 +284,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
.build();
context.restoreAuthSystemState();
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat, Projection.DEFAULT);
String token = getAuthToken(admin.getEmail(), password);
//Update it
bitstreamFormatRest.setShortDescription("Test short UPDATED");
@@ -314,7 +316,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
.build();
context.restoreAuthSystemState();
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat, Projection.DEFAULT);
String token = getAuthToken(admin.getEmail(), password);
//Update it
bitstreamFormatRest.setShortDescription("Test short UPDATED");
@@ -352,7 +354,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
int nonExistentBitstreamFormatID = 404404404;
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat, Projection.DEFAULT);
String token = getAuthToken(admin.getEmail(), password);
//Update it with non existent ID in URL and in JSON
bitstreamFormatRest.setShortDescription("Test short UPDATED");
@@ -389,7 +391,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
int nonExistentBitstreamFormatID = 404404404;
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat, Projection.DEFAULT);
String token = getAuthToken(admin.getEmail(), password);
//Update it with non existent ID in URL
bitstreamFormatRest.setShortDescription("Test short UPDATED");
@@ -425,7 +427,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
int nonExistentBitstreamFormatID = 404404404;
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat, Projection.DEFAULT);
String token = getAuthToken(admin.getEmail(), password);
//Update it with non existent ID in JSON, but valid in URL
bitstreamFormatRest.setShortDescription("Test short UPDATED");
@@ -463,7 +465,8 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
.build();
context.restoreAuthSystemState();
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat1, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat1,
Projection.DEFAULT);
String token = getAuthToken(admin.getEmail(), password);
//Update but id in body is not same id as in URL
bitstreamFormatRest.setShortDescription("Test short UPDATED");
@@ -496,7 +499,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
.build();
context.restoreAuthSystemState();
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat, Projection.DEFAULT);
//Try to update bitstreamFormat without auth token
bitstreamFormatRest.setShortDescription("Test short UPDATED");
@@ -532,7 +535,7 @@ public class BitstreamFormatRestRepositoryIT extends AbstractControllerIntegrati
.build();
context.restoreAuthSystemState();
BitstreamFormatRest bitstreamFormatRest = converter.toRest(bitstreamFormat, Projection.DEFAULT);
BitstreamFormatRest bitstreamFormatRest = bitstreamFormatConverter.convert(bitstreamFormat, Projection.DEFAULT);
String token = getAuthToken(user.getEmail(), password);
//Try to update bitstreamFormat without non-admin auth token

View File

@@ -181,12 +181,14 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
.withAuthor("Smith, Donald").withAuthor("Doe, John")
.build();
Bitstream bitstream = BitstreamBuilder
bitstream = BitstreamBuilder
.createBitstream(context, publicItem1, is)
.withName("Test bitstream")
.withDescription("This is a bitstream to test range requests")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
//** WHEN **
//We download the bitstream
@@ -213,7 +215,6 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
//The download and head request should also be logged as a statistics record
checkNumberOfStatsRecords(bitstream, 2);
}
}
@Test
@@ -239,12 +240,14 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
.withAuthor("Smith, Donald").withAuthor("Doe, John")
.build();
Bitstream bitstream = BitstreamBuilder
bitstream = BitstreamBuilder
.createBitstream(context, publicItem1, is)
.withName("Test bitstream")
.withDescription("This is a bitstream to test range requests")
.withMimeType("text/plain")
.build();
}
context.restoreAuthSystemState();
//** WHEN **
//We download only a specific byte range of the bitstream
@@ -290,7 +293,6 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
//Check that NO statistics record was logged for the Range requests
checkNumberOfStatsRecords(bitstream, 0);
}
}
@Test
@@ -322,13 +324,15 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
.withAuthor("Smith, Donald").withAuthor("Doe, John")
.build();
Bitstream bitstream = BitstreamBuilder
bitstream = BitstreamBuilder
.createBitstream(context, publicItem1, is)
.withName("Test Embargoed Bitstream")
.withDescription("This bitstream is embargoed")
.withMimeType("text/plain")
.withEmbargoPeriod("6 months")
.build();
}
context.restoreAuthSystemState();
//** WHEN **
//We download the bitstream
@@ -339,7 +343,6 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
//An unauthorized request should not log statistics
checkNumberOfStatsRecords(bitstream, 0);
}
}
@Test
@@ -397,6 +400,7 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
.withName("Collection 1")
.build();
String bitstreamContent = "Embargoed!";
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
@@ -407,7 +411,7 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
.withAuthor("Smith, Donald")
.build();
Bitstream bitstream = BitstreamBuilder
bitstream = BitstreamBuilder
.createBitstream(context, publicItem1, is)
.withName("Test Embargoed Bitstream")
.withDescription("This bitstream is embargoed")
@@ -546,14 +550,15 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
String bitstreamContent = "Private!";
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
Bitstream bitstream = BitstreamBuilder
bitstream = BitstreamBuilder
.createBitstream(context, publicItem1, is)
.withName("Test Embargoed Bitstream")
.withDescription("This bitstream is embargoed")
.withMimeType("text/plain")
.withReaderGroup(internalGroup)
.build();
}
context.restoreAuthSystemState();
//** WHEN **
//We download the bitstream
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
@@ -564,7 +569,7 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
//An unauthorized request should not log statistics
checkNumberOfStatsRecords(bitstream, 0);
}
}
@Test
@@ -754,13 +759,14 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
.withAuthor("Smith, Donald").withAuthor("Doe, John")
.build();
Bitstream bitstream = BitstreamBuilder
bitstream = BitstreamBuilder
.createBitstream(context, publicItem1, is)
.withName("Test bitstream")
.withDescription("This is a bitstream to test the citation cover page.")
.withMimeType("application/pdf")
.build();
}
context.restoreAuthSystemState();
//** WHEN **
//We download the bitstream
byte[] content = getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/content"))
@@ -796,7 +802,6 @@ public class BitstreamRestControllerIT extends AbstractControllerIntegrationTest
//The download and head request should also be logged as a statistics record
checkNumberOfStatsRecords(bitstream, 2);
}
}
private String extractPDFText(byte[] content) throws IOException {

View File

@@ -94,6 +94,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/bitstreams/"))
@@ -146,6 +148,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/bitstreams/")
@@ -271,6 +275,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
// When full projection is requested, response should include expected properties, links, and embeds.
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID())
.param("projection", "full"))
@@ -336,6 +342,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID() + "/format"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
@@ -364,6 +372,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection")
.withLogo("logo_collection").build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/bitstreams/" + parentCommunity.getLogo().getID()))
.andExpect(status().isOk());
@@ -386,6 +396,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection")
.withLogo("logo_collection").build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/bitstreams/" + parentCommunity.getLogo().getID() + "/content"))
.andExpect(status().isOk()).andExpect(content().string("logo_community"));
@@ -409,6 +421,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/bitstreams/" + UUID.randomUUID()))
@@ -453,6 +467,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete
@@ -500,6 +516,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
// Delete using an unauthorized user
@@ -547,6 +565,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
// Delete as anonymous
getClient().perform(delete("/api/core/bitstreams/" + bitstream.getID()))
.andExpect(status().isUnauthorized());
@@ -570,6 +590,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection")
.withLogo("logo_collection").build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// trying to DELETE parentCommunity logo should work
@@ -629,6 +651,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete
@@ -700,6 +724,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
// When full projection is requested, response should include expected properties, links, and embeds.
getClient().perform(get("/api/core/bitstreams/" + bitstream.getID())
.param("projection", "full"))
@@ -751,6 +777,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
}
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// When full projection is requested, response should include expected properties, links, and embeds.
@@ -811,6 +839,8 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
.withDspaceObject(col1)
.build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);

View File

@@ -167,6 +167,8 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find which subjects are currently in the repository
getClient().perform(get("/api/discover/browses/subject/entries")
@@ -251,6 +253,8 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
.withSubject("AnotherTest")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses the items that correspond with the ExtraEntry subject query
getClient().perform(get("/api/discover/browses/subject/items")
@@ -364,23 +368,18 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
//We expect the content type to be "application/hal+json;charset=UTF-8"
.andExpect(content().contentType(contentType))
//We expect only the two public items and the embargoed item to be present
.andExpect(jsonPath("$.page.size", is(20)))
.andExpect(jsonPath("$.page.totalElements", is(3)))
.andExpect(jsonPath("$.page.totalElements", is(2)))
.andExpect(jsonPath("$.page.totalPages", is(1)))
.andExpect(jsonPath("$.page.number", is(0)))
//Verify that the title of the public and embargoed items are present and sorted descending
.andExpect(jsonPath("$._embedded.items",
contains(ItemMatcher.matchItemWithTitleAndDateIssued(publicItem2,
"Public item 2",
"2016-02-13"),
ItemMatcher.matchItemWithTitleAndDateIssued(publicItem1,
"Public item 1",
"2017-10-17"),
ItemMatcher.matchItemWithTitleAndDateIssued(embargoedItem,
"An embargoed publication",
"2017-08-10"))))
"2017-10-17"))))
//The private and internal items must not be present
.andExpect(jsonPath("$._embedded.items[*].metadata", Matchers.allOf(
@@ -508,6 +507,8 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
.withIssueDate("2016-01-12")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses the items in the Browse by date issued endpoint
//sorted ascending by tile with a page size of 5
@@ -632,6 +633,8 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
.withSubject("Science Fiction")
.build();
context.restoreAuthSystemState();
// ---- BROWSES BY ENTRIES ----
//** WHEN **
@@ -772,6 +775,9 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
.withIssueDate("2029")
.withSubject("Science Fiction")
.build();
context.restoreAuthSystemState();
// ---- BROWSES BY ITEM ----
//** WHEN **
//An anonymous user browses the items in the Browse by date issued endpoint
@@ -920,6 +926,8 @@ public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTe
.withSubject("Astronomy")
.build();
context.restoreAuthSystemState();
// ---- BROWSES BY ITEM ----
//** WHEN **

View File

@@ -215,9 +215,9 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
ObjectMapper mapper = new ObjectMapper();
BundleRest bundleRest = new BundleRest();
bundleRest.setName("Create Bundle Without Metadata");
UUID bundleUuid = null;
String token = getAuthToken(admin.getEmail(), password);
try {
MvcResult mvcResult = getClient(token).perform(post("/api/core/items/" + item.getID() + "/bundles")
.content(mapper.writeValueAsBytes(bundleRest))
.contentType(contentType))
@@ -226,7 +226,7 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String, Object> map = mapper.readValue(content, Map.class);
UUID bundleUuid = UUID.fromString(String.valueOf(map.get("uuid")));
bundleUuid = UUID.fromString(String.valueOf(map.get("uuid")));
getClient().perform(get("/api/core/bundles/" + bundleUuid)
@@ -236,12 +236,16 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
.andExpect(jsonPath("$", BundleMatcher.matchBundle(
"Create Bundle Without Metadata",
bundleUuid, null, Constants.BUNDLE, new ArrayList<>())));
} finally {
BundleBuilder.deleteBundle(bundleUuid);
}
}
@Test
public void createBundleWithMetadata() throws Exception {
ObjectMapper mapper = new ObjectMapper();
UUID bundleUuid = null;
try {
BundleRest bundleRest = new BundleRest();
bundleRest.setName("Create Bundle Without Metadata");
bundleRest.setMetadata(new MetadataRest()
@@ -261,7 +265,7 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String, Object> map = mapper.readValue(content, Map.class);
UUID bundleUuid = UUID.fromString(String.valueOf(map.get("uuid")));
bundleUuid = UUID.fromString(String.valueOf(map.get("uuid")));
getClient().perform(get("/api/core/bundles/" + bundleUuid)
@@ -277,6 +281,9 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
"A description"),
MetadataMatcher.matchMetadata("dc.relation",
"A relation"))))));
} finally {
BundleBuilder.deleteBundle(bundleUuid);
}
}
@Test
@@ -332,8 +339,8 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
.withAction(Constants.ADD)
.withDspaceObject(item).build();
context.restoreAuthSystemState();
UUID bundleUuid = null;
try {
BundleRest bundleRest = new BundleRest();
bundleRest.setName("Create Bundle Without Metadata");
@@ -349,7 +356,7 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String, Object> map = mapper.readValue(content, Map.class);
UUID bundleUuid = UUID.fromString(String.valueOf(map.get("uuid")));
bundleUuid = UUID.fromString(String.valueOf(map.get("uuid")));
getClient().perform(get("/api/core/bundles/" + bundleUuid)
@@ -359,7 +366,9 @@ public class BundleRestRepositoryIT extends AbstractControllerIntegrationTest {
.andExpect(jsonPath("$", BundleMatcher.matchBundle(
"Create Bundle Without Metadata",
bundleUuid, null, Constants.BUNDLE, new ArrayList<>())));
} finally {
BundleBuilder.deleteBundle(bundleUuid);
}
}
@Test

View File

@@ -35,6 +35,7 @@ import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
import org.dspace.workflow.WorkflowService;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -163,6 +164,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isOk())
@@ -193,6 +196,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isOk())
@@ -250,6 +255,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isOk())
@@ -281,6 +288,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/adminGroup"))
.andExpect(status().isOk())
@@ -598,6 +607,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group submittersGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/submittersGroup"))
.andExpect(status().isOk())
@@ -631,6 +642,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group submittersGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/submittersGroup"))
.andExpect(status().isOk())
@@ -652,7 +665,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/submittersGroup")
@@ -688,6 +700,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group submittersGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/submittersGroup"))
.andExpect(status().isOk())
@@ -720,6 +734,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group submittersGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/submittersGroup"))
.andExpect(status().isOk())
@@ -955,7 +971,11 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
jsonPath("$", GroupMatcher.matchGroupEntry(role.getID(), role.getName())));
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void getCollectionDefaultItemReadGroupTestParentCommunityAdmin() throws Exception {
context.turnOffAuthorisationSystem();
String itemGroupString = "ITEM";
@@ -973,7 +993,11 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
jsonPath("$", GroupMatcher.matchGroupEntry(role.getID(), role.getName())));
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void getCollectionDefaultItemReadGroupTestCollectionAdmin() throws Exception {
context.turnOffAuthorisationSystem();
String itemGroupString = "ITEM";
@@ -1057,6 +1081,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group itemReadGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/itemReadGroup"))
.andExpect(status().isOk())
@@ -1078,7 +1104,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/itemReadGroup")
@@ -1096,7 +1121,12 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void postCollectionDefaultItemReadGroupCreateDefaultItemReadGroupSuccessParentCommunityAdmin()
throws Exception {
@@ -1120,6 +1150,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group itemReadGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/itemReadGroup"))
.andExpect(status().isOk())
@@ -1129,7 +1161,12 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void postCollectionDefaultItemReadGroupCreateDefaultItemReadGroupSuccessCollectionAdmin() throws Exception {
ObjectMapper mapper = new ObjectMapper();
@@ -1152,6 +1189,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group itemReadGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/itemReadGroup"))
.andExpect(status().isOk())
@@ -1436,7 +1475,11 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
jsonPath("$", GroupMatcher.matchGroupEntry(role.getID(), role.getName())));
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void getCollectionDefaultBitstreamReadGroupTestParentCommunityAdmin() throws Exception {
context.turnOffAuthorisationSystem();
String bitstreamGroupString = "BITSTREAM";
@@ -1454,7 +1497,11 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
jsonPath("$", GroupMatcher.matchGroupEntry(role.getID(), role.getName())));
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void getCollectionDefaultBitstreamReadGroupTestCollectionAdmin() throws Exception {
context.turnOffAuthorisationSystem();
String bitstreamGroupString = "BITSTREAM";
@@ -1541,6 +1588,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group bitstreamReadGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup"))
.andExpect(status().isOk())
@@ -1563,7 +1612,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup")
@@ -1580,7 +1628,12 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void postCollectionDefaultBitstreamReadGroupCreateDefaultBitstreamReadGroupSuccessParentCommunityAdmin()
throws Exception {
@@ -1604,6 +1657,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group bitstreamReadGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup"))
.andExpect(status().isOk())
@@ -1613,7 +1668,12 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
}
// Put on ignore because there's no support to identify read rights on a group for a user in a special
// com/coll admin group
// Please refer to: https://jira.lyrasis.org/browse/DS-4505
@Test
@Ignore
public void postCollectionDefaultBitstreamReadGroupCreateDefaultBitstreamReadGroupSuccessCollectionAdmin()
throws Exception {
@@ -1637,6 +1697,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group bitstreamReadGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/bitstreamReadGroup"))
.andExpect(status().isOk())
@@ -2023,6 +2085,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group workflowGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer"))
.andExpect(status().isOk())
@@ -2053,6 +2117,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group workflowGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer"))
.andExpect(status().isOk())
@@ -2076,7 +2142,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + UUID.randomUUID() + "/workflowGroups/reviewer")
@@ -2097,7 +2162,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/workflowGroups/wrongRole")
@@ -2120,7 +2184,6 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer")
@@ -2156,6 +2219,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group workflowGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer"))
.andExpect(status().isOk())
@@ -2188,6 +2253,8 @@ public class CollectionGroupRestControllerIT extends AbstractControllerIntegrati
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the collection comes
// from a CollectionBuilder that will cleanup also related groups
Group workflowGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/core/collections/" + collection.getID() + "/workflowGroups/reviewer"))
.andExpect(status().isOk())

View File

@@ -7,6 +7,7 @@
*/
package org.dspace.app.rest;
import static com.jayway.jsonpath.JsonPath.read;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist;
@@ -23,13 +24,14 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
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.builder.ResourcePolicyBuilder;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.CollectionConverter;
import org.dspace.app.rest.matcher.CollectionMatcher;
import org.dspace.app.rest.matcher.CommunityMatcher;
import org.dspace.app.rest.matcher.HalMatcher;
@@ -55,7 +57,7 @@ import org.springframework.http.MediaType;
public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTest {
@Autowired
ConverterService converter;
CollectionConverter collectionConverter;
@Autowired
AuthorizeService authorizeService;
@@ -82,6 +84,7 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
Collection col2 = CollectionBuilder.createCollection(context, child2).withName("Collection 2").build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/collections")
.param("embed", CollectionMatcher.getEmbedsParameter()))
@@ -592,6 +595,8 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/collections/" + col1.getID().toString())
.param("embed", CollectionMatcher.getEmbedsParameter()))
@@ -608,12 +613,11 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
ObjectMapper mapper = new ObjectMapper();
CollectionRest collectionRest = converter.toRest(col1, Projection.DEFAULT);
CollectionRest collectionRest = collectionConverter.convert(col1, Projection.DEFAULT);
collectionRest.setMetadata(new MetadataRest()
.put("dc.title", new MetadataValueRest("Electronic theses and dissertations")));
context.restoreAuthSystemState();
getClient(token).perform(put("/api/core/collections/" + col1.getID().toString())
.contentType(MediaType.APPLICATION_JSON)
@@ -739,6 +743,10 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
.build();
context.restoreAuthSystemState();
AtomicReference<UUID> idRef = new AtomicReference<>();
AtomicReference<UUID> idRefNoEmbeds = new AtomicReference<>();
try {
ObjectMapper mapper = new ObjectMapper();
CollectionRest collectionRest = new CollectionRest();
// We send a name but the created collection should set this to the title
@@ -783,7 +791,10 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
"Custom Copyright Text"),
MetadataMatcher.matchMetadata("dc.title",
"Title Text")
)))));
)))))
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));;
getClient(authToken).perform(post("/api/core/collections")
.content(mapper.writeValueAsBytes(collectionRest))
@@ -791,7 +802,13 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()));
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()))
.andDo(result -> idRefNoEmbeds
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));
} finally {
CollectionBuilder.deleteCollection(idRef.get());
CollectionBuilder.deleteCollection(idRefNoEmbeds.get());
}
}
@Test
@@ -828,6 +845,8 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
authorizeService.addPolicy(context, parentCommunity, Constants.ADD, eperson);
context.restoreAuthSystemState();
AtomicReference<UUID> idRef = new AtomicReference<UUID>();
try {
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(post("/api/core/collections")
@@ -853,8 +872,12 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
"Custom Copyright Text"),
MetadataMatcher.matchMetadata("dc.title",
"Title Text")
)))));
)))))
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));
} finally {
CollectionBuilder.deleteCollection(idRef.get());
}
}
@Test
@@ -993,7 +1016,7 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
String token = getAuthToken(eperson.getEmail(), password);
ObjectMapper mapper = new ObjectMapper();
CollectionRest collectionRest = converter.toRest(col1, Projection.DEFAULT);
CollectionRest collectionRest = collectionConverter.convert(col1, Projection.DEFAULT);
collectionRest.setMetadata(new MetadataRest()
.put("dc.title", new MetadataValueRest("Electronic theses and dissertations")));
@@ -1146,6 +1169,8 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
Collection col2 = CollectionBuilder.createCollection(context, child2).withName("Collection 2").build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/collections")
.param("embed", CollectionMatcher.getEmbedsParameter()))
@@ -1182,6 +1207,8 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
.build();
Collection col2 = CollectionBuilder.createCollection(context, child1child).withName("Collection 2").build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/collections/" + col1.getID())
@@ -1262,6 +1289,8 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
.withLogo("TestingContentForLogo")
.build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/collections/" + col1.getID())
.param("projection", "level")
.param("embedLevelDepth", "100"))
@@ -1287,6 +1316,8 @@ public class CollectionRestRepositoryIT extends AbstractControllerIntegrationTes
.withLogo("TestingContentForLogo")
.build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/collections/" + col1.getID())
.param("projection", "level"))
.andExpect(status().isBadRequest());

View File

@@ -138,6 +138,8 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerInteg
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the community comes
// from a CommunityBuilder that will cleanup also related groups
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID()))
.andExpect(status().isOk())
@@ -167,6 +169,8 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerInteg
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the community comes
// from a CommunityBuilder that will cleanup also related groups
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID()))
.andExpect(status().isOk())
@@ -190,7 +194,6 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerInteg
groupRest.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<>();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/communities/" + parentCommunity.getID() + "/adminGroup")
@@ -227,6 +230,8 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerInteg
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id")))
);
// no needs to explicitly cleanup the group created as the community comes
// from a CommunityBuilder that will cleanup also related groups
Group adminGroup = groupService.find(context, idRef.get());
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID()))
.andExpect(status().isOk())

View File

@@ -33,7 +33,7 @@ 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.converter.CommunityConverter;
import org.dspace.app.rest.matcher.CollectionMatcher;
import org.dspace.app.rest.matcher.CommunityMatcher;
import org.dspace.app.rest.matcher.HalMatcher;
@@ -66,7 +66,7 @@ import org.springframework.test.web.servlet.MvcResult;
public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest {
@Autowired
ConverterService converter;
CommunityConverter communityConverter;
@Autowired
CommunityService communityService;
@@ -357,6 +357,7 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
.withName("Sub Community")
.build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/communities").param("size", "2")
.param("embed", CommunityMatcher.getFullEmbedsParameters()))
@@ -429,6 +430,8 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context).withName("test").build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/communities")
.param("embed", CommunityMatcher.getFullEmbedsParameters()))
.andExpect(status().isOk())
@@ -463,6 +466,8 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
.withName(orderedTitles.get(2))
.build();
context.restoreAuthSystemState();
ObjectMapper mapper = new ObjectMapper();
MvcResult result = getClient().perform(get("/api/core/communities")).andReturn();
String response = result.getResponse().getContentAsString();
@@ -1329,6 +1334,8 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/communities/" + parentCommunity.getID().toString())
.param("embed", CommunityMatcher.getFullEmbedsParameters()))
.andExpect(status().isOk())
@@ -1349,9 +1356,11 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
String token = getAuthToken(admin.getEmail(), password);
context.turnOffAuthorisationSystem();
ObjectMapper mapper = new ObjectMapper();
CommunityRest communityRest = converter.toRest(parentCommunity, Projection.DEFAULT);
CommunityRest communityRest = communityConverter.convert(parentCommunity, Projection.DEFAULT);
communityRest.setMetadata(new MetadataRest()
.put("dc.title", new MetadataValueRest("Electronic theses and dissertations")));
@@ -1551,6 +1560,8 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
.withName("Sub Community")
.build();
context.restoreAuthSystemState();
getClient().perform(get("/api/core/communities/" + parentCommunity.getID().toString())
.param("embed", CommunityMatcher.getFullEmbedsParameters()))
.andExpect(status().isOk())
@@ -1569,9 +1580,11 @@ public class CommunityRestRepositoryIT extends AbstractControllerIntegrationTest
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/core/communities")))
;
context.turnOffAuthorisationSystem();
ObjectMapper mapper = new ObjectMapper();
CommunityRest communityRest = converter.toRest(parentCommunity, Projection.DEFAULT);
CommunityRest communityRest = communityConverter.convert(parentCommunity, Projection.DEFAULT);
communityRest.setMetadata(new MetadataRest()
.put("dc.title", new MetadataValueRest("Electronic theses and dissertations")));

View File

@@ -142,6 +142,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the objects in the system and enters a size of 2
getClient().perform(get("/api/discover/facets/author")
@@ -212,6 +214,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withAuthor("test2, test2").withAuthor("Maybe, Maybe")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the objects in the system and enters a size of 2
getClient().perform(get("/api/discover/facets/author?prefix=smith")
@@ -284,6 +288,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the authors by the facets and doesn't enter a size
getClient().perform(get("/api/discover/facets/author"))
@@ -357,6 +363,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the authors by the facet
//The user enters a size of two and wants to see page 1, this is the second page.
@@ -429,6 +437,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore")
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the authors by the facet
//The user enters a small query, namely the title has to contain 'test'
@@ -510,6 +521,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore")
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the dateIssued results by the facet
getClient().perform(get("/api/discover/facets/dateIssued"))
@@ -578,6 +592,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the author results by the facet
//With a certain scope
@@ -710,6 +726,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the dateIssued results by the facet
//And a size of 2
@@ -785,6 +803,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore")
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the dateIssued results by the facet
//With a query stating that the title needs to contain 'test'
@@ -904,6 +925,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the objects in the system
getClient().perform(get("/api/discover/search/objects"))
@@ -986,6 +1009,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the objects in the system
getClient().perform(get("/api/discover/search/objects"))
@@ -1076,6 +1101,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
getClient().perform(get("/api/discover/search/objects"))
@@ -1155,6 +1182,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withAuthor("test2, test2").withAuthor("Maybe, Maybe")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a query that says that the title has to contain 'test'
@@ -1235,6 +1264,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore")
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a scope 'test'
@@ -1317,6 +1349,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a dsoType 'item'
@@ -1393,6 +1427,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a dsoType 'item'
@@ -1537,6 +1573,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find dateIssued facet values
getClient().perform(get("/api/discover/facets/dateIssued"))
@@ -1611,6 +1649,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("h").withSubject("i").withSubject("j")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a size 2
@@ -1702,6 +1742,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//Run the filter media to make the text in the bitstream searchable through the query
runDSpaceScript("filter-media", "-f", "-i", publicItem1.getHandle());
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a query stating 'ThisIsSomeDummyText'
@@ -1947,6 +1989,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
UUID scope = col2.getID();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
@@ -2024,6 +2068,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.makeUnDiscoverable()
.build();
context.restoreAuthSystemState();
UUID scope = col2.getID();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
@@ -2104,6 +2150,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String query = "Public";
//** WHEN **
@@ -2181,6 +2228,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.makeUnDiscoverable()
.build();
context.restoreAuthSystemState();
String query = "Public";
//** WHEN **
@@ -2248,6 +2296,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore").withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
UUID scope = col2.getID();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
@@ -2321,6 +2371,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore").withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
UUID scope = col2.getID();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
@@ -2400,6 +2452,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("h").withSubject("i").withSubject("j")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a size 2
@@ -2483,6 +2537,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("h").withSubject("i").withSubject("j")
.build();
context.restoreAuthSystemState();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
//With a size 2
@@ -2543,6 +2599,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore").withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
UUID scope = col2.getID();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
@@ -2615,6 +2673,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore").withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
UUID scope = col2.getID();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
@@ -2688,6 +2748,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore").withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
UUID scope = col2.getID();
//** WHEN **
//An anonymous user browses this endpoint to find the the objects in the system
@@ -2773,6 +2835,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
//Run the filter media to make the text in the bitstream searchable through the query
runDSpaceScript("filter-media", "-f", "-i", publicItem1.getHandle());
context.restoreAuthSystemState();
//** WHEN **
getClient().perform(get("/api/discover/search/objects")
.param("query", "dc.date.issued:\"2010-02-13\""))
@@ -2855,6 +2919,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore")
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
getClient().perform(get("/api/discover/search/objects")
.param("query", "((dc.date.issued:2010 OR dc.date.issued:1990-02-13)" +
@@ -2923,6 +2990,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore")
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
getClient().perform(get("/api/discover/search/objects")
.param("query", "\"Faithful Infidel: Exploring Conformity (2nd edition)\""))
@@ -2990,6 +3060,9 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.withSubject("AnotherTest").withSubject("TestingForMore")
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
//** WHEN **
getClient().perform(get("/api/discover/search/objects")
.param("query", "OR"))
@@ -3078,6 +3151,8 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
XmlWorkflowItem wfItem1Admin = WorkflowItemBuilder.createWorkflowItem(context, col2)
.withTitle("Admin Workflow Item 1").build();
context.restoreAuthSystemState();
//** WHEN **
// An anonymous user, the submitter and the admin that browse this endpoint to find the public objects in the
// system should not retrieve the inprogress submissions and related objects
@@ -3866,6 +3941,7 @@ public class DiscoveryRestControllerIT extends AbstractControllerIntegrationTest
.makeUnDiscoverable()
.build();
context.restoreAuthSystemState();
String query = "Test";
//** WHEN **

View File

@@ -7,8 +7,10 @@
*/
package org.dspace.app.rest;
import static com.jayway.jsonpath.JsonPath.read;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
@@ -25,6 +27,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.ArrayList;
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;
@@ -36,6 +39,7 @@ import org.dspace.app.rest.builder.ItemBuilder;
import org.dspace.app.rest.matcher.EPersonMatcher;
import org.dspace.app.rest.matcher.GroupMatcher;
import org.dspace.app.rest.matcher.HalMatcher;
import org.dspace.app.rest.matcher.MetadataMatcher;
import org.dspace.app.rest.model.EPersonRest;
import org.dspace.app.rest.model.MetadataRest;
import org.dspace.app.rest.model.MetadataValueRest;
@@ -56,13 +60,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
@Test
public void createTest() throws Exception {
context.turnOffAuthorisationSystem();
// we should check how to get it from Spring
ObjectMapper mapper = new ObjectMapper();
EPersonRest data = new EPersonRest();
EPersonRest dataFull = new EPersonRest();
MetadataRest metadataRest = new MetadataRest();
data.setEmail("createtest@fake-email.com");
data.setEmail("createtest@example.com");
data.setCanLogIn(true);
MetadataValueRest surname = new MetadataValueRest();
surname.setValue("Doe");
@@ -71,11 +74,16 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
firstname.setValue("John");
metadataRest.put("eperson.firstname", firstname);
data.setMetadata(metadataRest);
dataFull.setEmail("createtestFull@fake-email.com");
dataFull.setEmail("createtestFull@example.com");
dataFull.setCanLogIn(true);
dataFull.setMetadata(metadataRest);
AtomicReference<UUID> idRef = new AtomicReference<UUID>();
AtomicReference<UUID> idRefNoEmbeds = new AtomicReference<UUID>();
String authToken = getAuthToken(admin.getEmail(), password);
try {
getClient(authToken).perform(post("/api/eperson/epersons")
.content(mapper.writeValueAsBytes(data))
.contentType(contentType)
@@ -87,7 +95,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
hasJsonPath("$.uuid", not(empty())),
// is it what you expect? EPerson.getName() returns the email...
//hasJsonPath("$.name", is("Doe John")),
hasJsonPath("$.email", is("createtest@fake-email.com")),
hasJsonPath("$.email", is("createtest@example.com")),
hasJsonPath("$.type", is("eperson")),
hasJsonPath("$.canLogIn", is(true)),
hasJsonPath("$.requireCertificate", is(false)),
@@ -95,15 +103,23 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
hasJsonPath("$.metadata", Matchers.allOf(
matchMetadata("eperson.firstname", "John"),
matchMetadata("eperson.lastname", "Doe")
)))));
)))))
.andDo(result -> idRef
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));
getClient(authToken).perform(post("/api/eperson/epersons")
.content(mapper.writeValueAsBytes(dataFull))
.contentType(contentType))
.andExpect(status().isCreated())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()));
// TODO cleanup the context!!!
.andExpect(jsonPath("$", HalMatcher.matchNoEmbeds()))
.andDo(result -> idRefNoEmbeds
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));;
} finally {
EPersonBuilder.deleteEPerson(idRef.get());
EPersonBuilder.deleteEPerson(idRefNoEmbeds.get());
}
}
@Test
@@ -112,9 +128,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson newUser = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/eperson"))
.andExpect(status().isOk())
@@ -154,9 +172,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson testEPerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
// NOTE: /eperson/epersons endpoint returns users sorted by email
// using size = 2 the first page will contain our new test user and default 'admin' ONLY
@@ -203,14 +223,16 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
context.restoreAuthSystemState();
// When full projection is requested, response should include expected properties, links, and embeds.
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/" + ePerson2.getID()).param("projection", "full"))
@@ -247,7 +269,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Bob", "Smith")
.withEmail("bobsmith@fake-email.com")
.withEmail("bobsmith@example.com")
.build();
context.restoreAuthSystemState();
@@ -263,14 +285,15 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson1 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
context.restoreAuthSystemState();
// Verify admin can access information about any user (and only one user is included in response)
String authToken = getAuthToken(admin.getEmail(), password);
@@ -312,14 +335,16 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson testEPerson1 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
EPerson testEPerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/" + UUID.randomUUID()))
.andExpect(status().isNotFound());
@@ -345,16 +370,18 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
// create a second eperson to put the previous one in a no special position (is not the first as we have default
// epersons is not the latest created)
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/search/byEmail")
.param("email", ePerson.getEmail()))
@@ -394,29 +421,31 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
EPerson ePerson3 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Tom", "Doe")
.withEmail("tomdoe@fake-email.com")
.withEmail("tomdoe@example.com")
.build();
EPerson ePerson4 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Dirk", "Doe-Postfix")
.withEmail("dirkdoepostfix@fake-email.com")
.withEmail("dirkdoepostfix@example.com")
.build();
EPerson ePerson5 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Harry", "Prefix-Doe")
.withEmail("harrydoeprefix@fake-email.com")
.withEmail("harrydoeprefix@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", ePerson.getLastName()))
@@ -449,29 +478,31 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
EPerson ePerson3 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Smith")
.withEmail("tomdoe@fake-email.com")
.withEmail("tomdoe@example.com")
.build();
EPerson ePerson4 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John-Postfix", "Smath")
.withEmail("dirkdoepostfix@fake-email.com")
.withEmail("dirkdoepostfix@example.com")
.build();
EPerson ePerson5 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Prefix-John", "Smoth")
.withEmail("harrydoeprefix@fake-email.com")
.withEmail("harrydoeprefix@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", ePerson.getFirstName()))
@@ -504,29 +535,31 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
EPerson ePerson3 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Tom", "Doe")
.withEmail("tomdoe@fake-email.com")
.withEmail("tomdoe@example.com")
.build();
EPerson ePerson4 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Dirk", "Doe-Postfix")
.withEmail("dirkdoepostfix@fake-email.com")
.withEmail("dirkdoepostfix@example.com")
.build();
EPerson ePerson5 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Harry", "Prefix-Doe")
.withEmail("harrydoeprefix@fake-email.com")
.withEmail("harrydoeprefix@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", ePerson.getEmail()))
@@ -553,29 +586,31 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("janesmith@fake-email.com")
.withEmail("janesmith@example.com")
.build();
EPerson ePerson3 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Tom", "Doe")
.withEmail("tomdoe@fake-email.com")
.withEmail("tomdoe@example.com")
.build();
EPerson ePerson4 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Dirk", "Doe-Postfix")
.withEmail("dirkdoepostfix@fake-email.com")
.withEmail("dirkdoepostfix@example.com")
.build();
EPerson ePerson5 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Harry", "Prefix-Doe")
.withEmail("harrydoeprefix@fake-email.com")
.withEmail("harrydoeprefix@example.com")
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", String.valueOf(ePerson.getID())))
@@ -635,9 +670,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// Delete
@@ -654,9 +691,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
// login as a basic user
String token = getAuthToken(eperson.getEmail(), password);
@@ -677,9 +716,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
// Delete as anonymous user
getClient().perform(delete("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isUnauthorized());
@@ -699,7 +740,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Sample", "Submitter")
.withEmail("submitter@fake-email.com")
.withEmail("submitter@example.com")
.build();
// force the use of the new user for subsequent operation
@@ -715,9 +756,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
.withLogo("logo_collection").build();
// 3. Create an item that will prevent the deletation of the eperson account (it is the submitter)
// 3. Create an item that will prevent the deletion of the eperson account (it is the submitter)
Item item = ItemBuilder.createItem(context, col).build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// 422 error when trying to DELETE the eperson=submitter
@@ -736,9 +779,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/netid", "newNetId");
ops.add(replaceOperation);
@@ -767,9 +812,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/netid", "newNetId");
ops.add(replaceOperation);
@@ -795,10 +842,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withNetId("testId")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/netid", "newNetId");
ops.add(replaceOperation);
@@ -812,7 +861,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.netid", Matchers.is("newNetId")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.canLogIn", Matchers.is(false)));
}
@@ -824,10 +873,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withNetId("testId")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -843,7 +894,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.netid", Matchers.is("testId")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.canLogIn", Matchers.is(true)));
// String should be converted to boolean.
@@ -857,7 +908,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.netid", Matchers.is("testId")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.canLogIn", Matchers.is(false)));
}
@@ -869,9 +920,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/netid", "newNetId");
ops.add(replaceOperation);
@@ -887,7 +940,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.netid", Matchers.nullValue()));
}
@@ -899,10 +952,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withNetId("testId")
.build();
context.restoreAuthSystemState();
String newId = "newId";
String token = getAuthToken(admin.getEmail(), password);
@@ -935,7 +990,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.netid", Matchers.is(newId)))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.canLogIn", Matchers.is(false)));
@@ -948,9 +1003,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/canLogin", true);
ops.add(replaceOperation);
@@ -964,7 +1021,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.canLogIn", Matchers.is(true)))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.netid", Matchers.nullValue()));
@@ -977,9 +1034,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -1010,7 +1069,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.canLogIn", Matchers.is(true)))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.requireCertificate", Matchers.is(false)));
}
@@ -1022,9 +1081,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
// Boolean operations should accept either string or boolean as value. Try boolean.
ReplaceOperation replaceOperation = new ReplaceOperation("/certificate", false);
@@ -1039,7 +1100,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.requireCertificate", Matchers.is(false)))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.netid", Matchers.nullValue()));
}
@@ -1051,9 +1112,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -1083,7 +1146,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.requireCertificate", Matchers.is(true)))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@fake-email.com")))
.andExpect(jsonPath("$.email", Matchers.is("johndoe@example.com")))
.andExpect(jsonPath("$.canLogIn", Matchers.is(false)));
@@ -1096,10 +1159,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
context.restoreAuthSystemState();
String newPassword = "newpassword";
List<Operation> ops = new ArrayList<Operation>();
@@ -1129,16 +1194,18 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson1 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Doe")
.withEmail("Janedoe@fake-email.com")
.withEmail("Janedoe@example.com")
.withPassword(password)
.build();
context.restoreAuthSystemState();
String newPassword = "newpassword";
List<Operation> ops = new ArrayList<Operation>();
@@ -1168,14 +1235,14 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
String newPassword = "newpassword";
context.restoreAuthSystemState();
String newPassword = "newpassword";
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/password", newPassword);
ops.add(replaceOperation);
@@ -1203,9 +1270,11 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
String newPassword = "newpassword";
List<Operation> ops = new ArrayList<Operation>();
@@ -1228,7 +1297,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("CanLogin@fake-email.com")
.withEmail("CanLogin@example.com")
.withPassword(password)
.build();
@@ -1255,7 +1324,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("CanLogin@fake-email.com")
.withEmail("CanLogin@example.com")
.withPassword(password)
.build();
@@ -1283,10 +1352,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword("testpass79bC")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
String newPassword = "newpass";
@@ -1328,10 +1399,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
context.restoreAuthSystemState();
String newEmail = "janedoe@real-email.com";
List<Operation> ops = new ArrayList<Operation>();
@@ -1361,7 +1434,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
@@ -1391,10 +1464,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -1422,10 +1497,12 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withNetId("testId")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -1455,11 +1532,14 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation0 = new ReplaceOperation("/canLogin", true);
ops.add(replaceOperation0);
@@ -1509,13 +1589,128 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Exception {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("user@test.com").build();
EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("user@example.com").build();
context.restoreAuthSystemState();
String token = getAuthToken(asUser.getEmail(), password);
new MetadataPatchSuite().runWith(getClient(token), "/api/eperson/epersons/" + ePerson.getID(), expectedStatus);
}
@Test
public void patchMetadataByAdmin() throws Exception {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@example.com")
.build();
String newName = "JohnReplace";
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/eperson.firstname", newName);
ops.add(replaceOperation);
String patchBody = getPatchContent(ops);
String token = getAuthToken(admin.getEmail(), password);
// should be allowed, and eperson.firstname should be replaced.
getClient(token).perform(patch("/api/eperson/epersons/" + ePerson.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.metadata", Matchers.allOf(
MetadataMatcher.matchMetadata("eperson.firstname", newName))));
// The replacement of the eperson.firstname value is persisted
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasJsonPath("$.metadata", allOf(
matchMetadata("eperson.firstname", newName)))));
}
@Test
public void patchOwnMetadataByNonAdminUser() throws Exception {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
String newName = "JohnReplace";
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/eperson.firstname", newName);
ops.add(replaceOperation);
String patchBody = getPatchContent(ops);
String token = getAuthToken(ePerson.getEmail(), password);
// replace operation on eperson.firstname by owning user
getClient(token).perform(patch("/api/eperson/epersons/" + ePerson.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.metadata", Matchers.allOf(
MetadataMatcher.matchMetadata("eperson.firstname", newName))));
// The replacement of the eperson.firstname value is persisted
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasJsonPath("$.metadata", allOf(
matchMetadata("eperson.firstname", newName)))));
}
@Test
public void patchNotOwnMetadataByNonAdminUser() throws Exception {
context.turnOffAuthorisationSystem();
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
EPerson ePerson2 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Jane", "Smith")
.withEmail("Janesmith@example.com")
.withPassword(password)
.build();
String newName = "JohnReplace";
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/eperson.firstname", newName);
ops.add(replaceOperation);
String patchBody = getPatchContent(ops);
String token2 = getAuthToken(ePerson2.getEmail(), password);
String token = getAuthToken(ePerson.getEmail(), password);
// attempts to replace eperson.firstname, not allowed, only allowed by admin or owning user
getClient(token2).perform(patch("/api/eperson/epersons/" + ePerson.getID())
.content(patchBody)
.contentType(MediaType.APPLICATION_JSON_PATCH_JSON))
.andExpect(status().isForbidden());
// No replacement of the eperson.firstname
getClient(token).perform(get("/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", hasJsonPath("$.metadata", allOf(
matchMetadata("eperson.firstname", "John")))));
}
@Test
public void newlyCreatedAccountHasNoGroups() throws Exception {
context.turnOffAuthorisationSystem();
@@ -1551,7 +1746,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
EPerson ePerson = EPersonBuilder.createEPerson(context)
.withNameInMetadata("John", "Doe")
.withEmail("Johndoe@fake-email.com")
.withEmail("Johndoe@example.com")
.withPassword(password)
.build();
@@ -1575,6 +1770,7 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
.addMember(ePerson)
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/epersons/" + ePerson.getID() + "/groups"))

View File

@@ -238,6 +238,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
.withName(testGroupName)
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
// When full projection is requested, response should include expected properties, links, and embeds.
@@ -281,6 +282,8 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
.addMember(eperson)
.build();
context.restoreAuthSystemState();
//Admin can access
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + group2.getID()))
@@ -341,6 +344,8 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
.withName(testGroupName)
.build();
context.restoreAuthSystemState();
String generatedGroupId = group.getID().toString();
String groupIdCall = "/api/eperson/groups/" + UUID.randomUUID();
getClient().perform(get(groupIdCall))
@@ -382,6 +387,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(get("/api/eperson/groups/search/byMetadata")
.param("query", group1.getName()))
@@ -571,6 +577,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
childGroup1 = context.reloadEntity(childGroup1);
childGroup2 = context.reloadEntity(childGroup2);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups")
@@ -634,6 +641,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
childGroup1 = context.reloadEntity(childGroup1);
childGroup2 = context.reloadEntity(childGroup2);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups")
@@ -693,6 +701,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
childGroup1 = context.reloadEntity(childGroup1);
childGroup2 = context.reloadEntity(childGroup2);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups")
@@ -737,6 +746,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
childGroup1 = context.reloadEntity(childGroup1);
childGroup2 = context.reloadEntity(childGroup2);
context.restoreAuthSystemState();
getClient().perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/subgroups")
.contentType(parseMediaType(TEXT_URI_LIST_VALUE))
@@ -780,6 +790,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
childGroup1 = context.reloadEntity(childGroup1);
childGroup2 = context.reloadEntity(childGroup2);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + UUID.randomUUID() + "/subgroups")
@@ -827,6 +838,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
childGroup1 = context.reloadEntity(childGroup1);
childGroup2 = context.reloadEntity(childGroup2);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
@@ -881,6 +893,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
member1 = context.reloadEntity(member1);
member2 = context.reloadEntity(member2);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/epersons")
@@ -944,6 +957,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
member1 = context.reloadEntity(member1);
member2 = context.reloadEntity(member2);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/epersons")
@@ -1004,6 +1018,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
member1 = context.reloadEntity(member1);
member2 = context.reloadEntity(member2);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/epersons")
@@ -1049,6 +1064,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
member1 = context.reloadEntity(member1);
member2 = context.reloadEntity(member2);
context.restoreAuthSystemState();
getClient().perform(
post("/api/eperson/groups/" + parentGroup.getID() + "/epersons")
.contentType(parseMediaType(TEXT_URI_LIST_VALUE))
@@ -1093,6 +1109,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
member1 = context.reloadEntity(member1);
member2 = context.reloadEntity(member2);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
post("/api/eperson/groups/" + UUID.randomUUID() + "/epersons")
@@ -1138,6 +1155,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
member1 = context.reloadEntity(member1);
member2 = context.reloadEntity(member2);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
@@ -1181,6 +1199,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
childGroup = context.reloadEntity(childGroup);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID())
@@ -1229,6 +1248,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
childGroup = context.reloadEntity(childGroup);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID())
@@ -1273,6 +1293,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
childGroup = context.reloadEntity(childGroup);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID())
@@ -1307,6 +1328,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
childGroup = context.reloadEntity(childGroup);
context.restoreAuthSystemState();
getClient().perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/subgroups/" + childGroup.getID())
).andExpect(status().isUnauthorized());
@@ -1342,6 +1364,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
childGroup = context.reloadEntity(childGroup);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
@@ -1379,6 +1402,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
childGroup = context.reloadEntity(childGroup);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
@@ -1417,6 +1441,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
member = context.reloadEntity(member);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID())
@@ -1468,6 +1493,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
member = context.reloadEntity(member);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID())
@@ -1514,6 +1540,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
member = context.reloadEntity(member);
context.restoreAuthSystemState();
String authToken = getAuthToken(eperson.getEmail(), password);
getClient(authToken).perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID())
@@ -1550,6 +1577,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
member = context.reloadEntity(member);
context.restoreAuthSystemState();
getClient().perform(
delete("/api/eperson/groups/" + parentGroup.getID() + "/epersons/" + member.getID())
).andExpect(status().isUnauthorized());
@@ -1585,6 +1613,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
member = context.reloadEntity(member);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(
@@ -1622,6 +1651,7 @@ public class GroupRestRepositoryIT extends AbstractControllerIntegrationTest {
parentGroup = context.reloadEntity(parentGroup);
member = context.reloadEntity(member);
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(

View File

@@ -52,7 +52,7 @@ public class ItemOwningCollectionUpdateRestControllerIT extends AbstractControll
.withAuthor("Smith, Donald")
.build();
context.restoreAuthSystemState();
//When we call this owningCollection/move endpoint
getClient().perform(
put("/api/core/items/" + publicItem1.getID() + "/owningCollection/")
@@ -85,6 +85,7 @@ public class ItemOwningCollectionUpdateRestControllerIT extends AbstractControll
.withAuthor("Smith, Donald")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
@@ -140,6 +141,7 @@ public class ItemOwningCollectionUpdateRestControllerIT extends AbstractControll
.withAction(Constants.ADD)
.withDspaceObject(col2).build();
context.restoreAuthSystemState();
String token = getAuthToken(itemMoveEperson.getEmail(), "test");
getClient(token)
@@ -186,7 +188,7 @@ public class ItemOwningCollectionUpdateRestControllerIT extends AbstractControll
.withAction(Constants.WRITE)
.withDspaceObject(publicItem1).build();
context.restoreAuthSystemState();
String token = getAuthToken(itemMoveEperson.getEmail(), "test");
getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/")
@@ -227,7 +229,7 @@ public class ItemOwningCollectionUpdateRestControllerIT extends AbstractControll
.withAction(Constants.ADD)
.withDspaceObject(col2).build();
context.restoreAuthSystemState();
String token = getAuthToken(itemMoveEperson.getEmail(), "test");
getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/")
@@ -268,7 +270,7 @@ public class ItemOwningCollectionUpdateRestControllerIT extends AbstractControll
.withAction(Constants.ADD)
.withDspaceObject(col2).build();
context.restoreAuthSystemState();
String token = getAuthToken(itemMoveEperson.getEmail(), "test");
getClient(token).perform(put("/api/core/items/" + publicItem1.getID() + "/owningCollection/")

View File

@@ -7,6 +7,7 @@
*/
package org.dspace.app.rest;
import static com.jayway.jsonpath.JsonPath.read;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist;
@@ -26,6 +27,7 @@ import java.util.ArrayList;
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 com.fasterxml.jackson.databind.ObjectMapper;
@@ -107,6 +109,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/items"))
@@ -171,6 +174,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/items")
@@ -253,6 +257,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
Matcher<? super Object> publicItem1Matcher = ItemMatcher.matchItemWithTitleAndDateIssued(publicItem1,
"Public item 1", "2017-10-17");
@@ -332,6 +337,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
}
context.restoreAuthSystemState();
getClient().perform(get("/api/core/items/" + publicItem1.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", Matchers.is(
@@ -379,6 +385,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
Collection col2 = CollectionBuilder.createCollection(context, child1).withName("Collection 2").build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/core/items/" + UUID.randomUUID()))
@@ -410,6 +417,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
// A token must be provided for withdraw operation. The person
// is used in the provenance note.
String token = getAuthToken(admin.getEmail(), password);
@@ -468,6 +476,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
List<Operation> ops = new ArrayList<Operation>();
ReplaceOperation replaceOperation = new ReplaceOperation("/withdrawn", true);
ops.add(replaceOperation);
@@ -513,6 +522,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
// try to use an unauthorized user
String token = getAuthToken(eperson.getEmail(), password);
@@ -573,6 +583,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withdrawn()
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -632,6 +643,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withdrawn()
.build();
context.restoreAuthSystemState();
// A token must be provided for reinstate operation. The person
// is used in the provenance note.
String token = getAuthToken(admin.getEmail(), password);
@@ -693,6 +705,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withdrawn()
.build();
context.restoreAuthSystemState();
String tokenAdmin = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -741,6 +754,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withdrawn()
.build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
String tokenAdmin = getAuthToken(admin.getEmail(), password);
@@ -786,6 +800,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.makeUnDiscoverable()
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -839,6 +854,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.makeUnDiscoverable()
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -882,6 +898,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.makeUnDiscoverable()
.build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
String tokenAdmin = getAuthToken(admin.getEmail(), password);
@@ -925,6 +942,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -970,6 +988,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -1016,6 +1035,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -1059,6 +1079,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
String tokenAdmin = getAuthToken(admin.getEmail(), password);
@@ -1113,6 +1134,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.makeUnDiscoverable()
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
List<Operation> ops = new ArrayList<Operation>();
@@ -1180,6 +1202,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
}
context.restoreAuthSystemState();
// Check publicItem creation
getClient().perform(get("/api/core/items/" + publicItem.getID()))
.andExpect(status().isOk());
@@ -1224,6 +1247,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
Item templateItem = col1.getTemplateItem();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
//Trying to delete a templateItem should fail with 422
@@ -1252,6 +1276,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
WorkspaceItem workspaceItem = WorkspaceItemBuilder.createWorkspaceItem(context, col1)
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
//Trying to delete a workspaceItem should fail with 422
@@ -1711,8 +1736,11 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
UUID idRef = null;
AtomicReference<UUID> idRefNoEmbeds = new AtomicReference<UUID>();
try {
ObjectMapper mapper = new ObjectMapper();
ItemRest itemRest = new ItemRest();
ItemRest itemRestFull = new ItemRest();
@@ -1755,8 +1783,9 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
String itemUuidString = String.valueOf(map.get("uuid"));
String itemHandleString = String.valueOf(map.get("handle"));
idRef = UUID.fromString(itemUuidString);
//TODO Refactor this to use the converter to Item instead of checking every property separately
getClient(token).perform(get("/api/core/items/" + itemUuidString))
getClient(token).perform(get("/api/core/items/" + idRef.toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", Matchers.allOf(
hasJsonPath("$.id", is(itemUuidString)),
@@ -1777,12 +1806,18 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
"Title Text")
)))));
MvcResult mvcResultFull = getClient(token).perform(post("/api/core/items?owningCollection=" +
getClient(token).perform(post("/api/core/items?owningCollection=" +
col1.getID().toString()).param("projection", "full")
.content(mapper.writeValueAsBytes(itemRestFull)).contentType(contentType))
.andExpect(status().isCreated())
.andExpect(jsonPath("$", ItemMatcher.matchFullEmbeds()))
.andReturn();
.andDo(result -> idRefNoEmbeds
.set(UUID.fromString(read(result.getResponse().getContentAsString(), "$.id"))));
} finally {
ItemBuilder.deleteItem(idRef);
ItemBuilder.deleteItem(idRefNoEmbeds.get());
}
}
@Test
@@ -1799,6 +1834,10 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
String itemUuidString = null;
try {
ObjectMapper mapper = new ObjectMapper();
ItemRest itemRest = new ItemRest();
itemRest.setName("Practices of research data curation in institutional repositories:" +
@@ -1818,7 +1857,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String,Object> map = mapper.readValue(content, Map.class);
String itemUuidString = String.valueOf(map.get("uuid"));
itemUuidString = String.valueOf(map.get("uuid"));
String itemHandleString = String.valueOf(map.get("handle"));
itemRest.setMetadata(new MetadataRest()
@@ -1831,14 +1870,10 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
itemRest.setUuid(itemUuidString);
itemRest.setHandle(itemHandleString);
mvcResult = getClient(token).perform(put("/api/core/items/" + itemUuidString)
getClient(token).perform(put("/api/core/items/" + itemUuidString)
.content(mapper.writeValueAsBytes(itemRest))
.contentType(contentType))
.andExpect(status().isOk())
.andReturn();
map = mapper.readValue(content, Map.class);
itemUuidString = String.valueOf(map.get("uuid"));
itemHandleString = String.valueOf(map.get("handle"));
.andExpect(status().isOk());
//TODO Refactor this to use the converter to Item instead of checking every property separately
getClient(token).perform(get("/api/core/items/" + itemUuidString))
@@ -1861,6 +1896,9 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
matchMetadata("dc.title",
"New title")
)))));
} finally {
ItemBuilder.deleteItem(UUID.fromString(itemUuidString));
}
}
@@ -1880,7 +1918,9 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
String itemUuidString = null;
try {
ObjectMapper mapper = new ObjectMapper();
ItemRest itemRest = new ItemRest();
itemRest.setName("Practices of research data curation in institutional repositories:" +
@@ -1906,7 +1946,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String,Object> map = mapper.readValue(content, Map.class);
String itemUuidString = String.valueOf(map.get("uuid"));
itemUuidString = String.valueOf(map.get("uuid"));
String itemHandleString = String.valueOf(map.get("handle"));
//TODO Refactor this to use the converter to Item instead of checking every property separately
@@ -1936,6 +1976,9 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
getClient(token).perform(get("/api/core/items/" + itemUuidString))
.andExpect(status().isNotFound());
} finally {
ItemBuilder.deleteItem(UUID.fromString(itemUuidString));
}
}
@Test
@@ -1953,8 +1996,10 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
String itemUuidString = null;
try {
ObjectMapper mapper = new ObjectMapper();
ItemRest itemRest = new ItemRest();
itemRest.setName("Practices of research data curation in institutional repositories:" +
@@ -1980,7 +2025,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String,Object> map = mapper.readValue(content, Map.class);
String itemUuidString = String.valueOf(map.get("uuid"));
itemUuidString = String.valueOf(map.get("uuid"));
String itemHandleString = String.valueOf(map.get("handle"));
//TODO Refactor this to use the converter to Item instead of checking every property separately
@@ -2010,6 +2055,9 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
getClient(token).perform(get("/api/core/items/" + itemUuidString))
.andExpect(status().isOk());
} finally {
ItemBuilder.deleteItem(UUID.fromString(itemUuidString));
}
}
@Test
@@ -2032,7 +2080,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.withSubject("ExtraEntry")
.build();
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
//Delete public item
@@ -2084,7 +2132,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
ObjectMapper mapper = new ObjectMapper();
ItemRest itemRest = new ItemRest();
itemRest.setName("Practices of research data curation in institutional repositories:" +
@@ -2122,7 +2170,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
context.restoreAuthSystemState();
ObjectMapper mapper = new ObjectMapper();
ItemRest itemRest = new ItemRest();
itemRest.setName("Practices of research data curation in institutional repositories:" +
@@ -2161,6 +2209,8 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
context.restoreAuthSystemState();
String itemUuidString = null;
try {
ObjectMapper mapper = new ObjectMapper();
ItemRest itemRest = new ItemRest();
itemRest.setName("Practices of research data curation in institutional repositories:" +
@@ -2180,7 +2230,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String,Object> map = mapper.readValue(content, Map.class);
String itemUuidString = String.valueOf(map.get("uuid"));
itemUuidString = String.valueOf(map.get("uuid"));
String itemHandleString = String.valueOf(map.get("handle"));
itemRest.setMetadata(new MetadataRest()
@@ -2199,6 +2249,9 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.content(mapper.writeValueAsBytes(itemRest))
.contentType(contentType))
.andExpect(status().isForbidden());
} finally {
ItemBuilder.deleteItem(UUID.fromString(itemUuidString));
}
}
@Test
@@ -2217,6 +2270,8 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
context.restoreAuthSystemState();
String itemUuidString = null;
try {
ObjectMapper mapper = new ObjectMapper();
String token = getAuthToken(admin.getEmail(), password);
MvcResult mvcResult = getClient(token).perform(post("/api/core/items?owningCollection="
@@ -2228,7 +2283,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
String content = mvcResult.getResponse().getContentAsString();
Map<String,Object> map = mapper.readValue(content, Map.class);
String itemUuidString = String.valueOf(map.get("uuid"));
itemUuidString = String.valueOf(map.get("uuid"));
String itemHandleString = String.valueOf(map.get("handle"));
getClient(token).perform(get("/api/core/items/" + itemUuidString))
@@ -2241,6 +2296,9 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
hasJsonPath("$.metadata", Matchers.allOf(
matchMetadata("dc.contributor.author", "Donald, Smith")
)))));
} finally {
ItemBuilder.deleteItem(UUID.fromString(itemUuidString));
}
}
@Test
@@ -2250,7 +2308,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.contentType(org.springframework.http.MediaType.parseMediaType(
org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/integration/externalsources/" +
"mock/entryValues/one")).andExpect(status().isBadRequest()).andReturn();
"mock/entryValues/one")).andExpect(status().isBadRequest());
}
@Test
@@ -2260,7 +2318,7 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
.contentType(org.springframework.http.MediaType.parseMediaType(
org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/integration/externalsources/" +
"mock/entryValues/one")).andExpect(status().isBadRequest()).andReturn();
"mock/entryValues/one")).andExpect(status().isBadRequest());
}
@Test
@@ -2279,7 +2337,6 @@ public class ItemRestRepositoryIT extends AbstractControllerIntegrationTest {
context.restoreAuthSystemState();
ObjectMapper mapper = new ObjectMapper();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(post("/api/core/items?owningCollection=" + col1.getID().toString())
.contentType(org.springframework.http.MediaType.parseMediaType(

View File

@@ -0,0 +1,348 @@
/**
* 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.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;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.InputStream;
import java.util.Map;
import java.util.UUID;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.CharEncoding;
import org.dspace.app.rest.builder.BitstreamBuilder;
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.PoolTaskBuilder;
import org.dspace.app.rest.matcher.EPersonMatcher;
import org.dspace.app.rest.matcher.WorkflowItemMatcher;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.content.Bitstream;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.Item;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
import org.dspace.services.ConfigurationService;
import org.dspace.xmlworkflow.storedcomponents.PoolTask;
import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
public class LoginAsEPersonIT extends AbstractControllerIntegrationTest {
@Autowired
private ConfigurationService configurationService;
@Autowired
private GroupService groupService;
@Before
public void setup() {
configurationService.setProperty("webui.user.assumelogin", true);
}
@Test
public void loggedInUserRetrievalTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.param("projection", "full"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.eperson", EPersonMatcher.matchEPersonOnEmail(admin.getEmail())));
}
@Test
public void loggedInAsOtherUserRetrievalTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.param("projection", "full")
.header("X-On-Behalf-Of", eperson.getID()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.eperson",
EPersonMatcher.matchEPersonOnEmail(eperson.getEmail())));
}
@Test
public void loggedInAsOtherUserNotAUuidInHeaderBadRequestRetrievalTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.param("projection", "full")
.header("X-On-Behalf-Of", "not-a-uuid"))
.andExpect(status().isBadRequest());
}
@Test
public void loggedInAsOtherUserWrongUuidInHeaderBadRequestRetrievalTest() throws Exception {
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.param("projection", "full")
.header("X-On-Behalf-Of", UUID.randomUUID()))
.andExpect(status().isBadRequest());
}
@Test
public void loggedInAsOtherUserNoPermissionForbiddenRetrievalTest() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.param("projection", "full")
.header("X-On-Behalf-Of", eperson.getID()))
.andExpect(status().isForbidden());
}
@Test
public void loggedInUserPropertyFalseTest() throws Exception {
configurationService.setProperty("webui.user.assumelogin", false);
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.header("X-On-Behalf-Of", eperson.getID()))
.andExpect(status().isBadRequest());
}
@Test
public void loggedInUserOtherAdminTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson testEperson = EPersonBuilder.createEPerson(context).withEmail("loginasuseradmin@test.com").build();
Group adminGroup = groupService.findByName(context, Group.ADMIN);
groupService.addMember(context, adminGroup, testEperson);
context.restoreAuthSystemState();
String token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/authn/status")
.header("X-On-Behalf-Of", testEperson.getID()))
.andExpect(status().isBadRequest());
}
/**
* This test will try to create an empty Workspace item whilst using the LoginOnBehalfOf feature
* It'll then check that the submitter of that workspace item is indeed the eperson that was being
* impersonated by the loginOnBehalfOf feature
* @throws Exception
*/
@Test
public void createEmptyWorkspaceItemLoginOnBehalfOfCheckSubmitterTest() 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")
.withSubmitterGroup(eperson)
.build();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
// create a workspaceitem explicitly in the col1
MvcResult mvcResult = getClient(authToken).perform(post("/api/submission/workspaceitems")
.param("owningCollection", col1.getID().toString())
.header("X-On-Behalf-Of", eperson.getID())
.contentType(org.springframework
.http.MediaType.APPLICATION_JSON))
.andExpect(status().isCreated())
.andExpect(jsonPath("$._embedded.collection.id",
is(col1.getID().toString()))).andReturn();
ObjectMapper mapper = new ObjectMapper();
String content = mvcResult.getResponse().getContentAsString();
Map<String,Object> map = mapper.readValue(content, Map.class);
String workspaceItemId = String.valueOf(map.get("id"));
getClient(authToken).perform(get("/api/submission/workspaceitems/" + workspaceItemId))
.andExpect(jsonPath("$._embedded.submitter", EPersonMatcher.matchProperties(eperson)));
}
@Test
/**
* Test claiming of a pool task with the LoginOnBehalfOf header. Thus checking that an admin can impersonate
* an eperson to claim a pooltask and checking later on that the owner of this claimedTask is indeed
* the reviwer
*
* @throws Exception
*/
public void claimTaskLoginOnBehalfOfTest() throws Exception {
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. a reviewer
EPerson reviewer = EPersonBuilder.createEPerson(context)
.withEmail("reviewer@example.com")
.withPassword(password)
.build();
//2. A community-collection structure with one parent community with sub-community and one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1")
.withWorkflowGroup(1, reviewer).build();
//3. create a normal user to use as submitter
EPerson submitter = EPersonBuilder.createEPerson(context)
.withEmail("submitter@example.com")
.withPassword(password)
.build();
context.setCurrentUser(submitter);
//4. a pool task
PoolTask poolTask = PoolTaskBuilder.createPoolTask(context, col1, reviewer)
.withTitle("Workflow Item 1")
.withIssueDate("2017-10-17")
.withAuthor("Smith, Donald").withAuthor("Doe, John")
.withSubject("ExtraEntry")
.build();
XmlWorkflowItem witem = poolTask.getWorkflowItem();
context.restoreAuthSystemState();
String authToken = getAuthToken(admin.getEmail(), password);
getClient(authToken).perform(post("/api/workflow/pooltasks/" + poolTask.getID())
.header("X-On-Behalf-Of", reviewer.getID())
.contentType(MediaType.APPLICATION_FORM_URLENCODED))
.andExpect(status().isNoContent());
// verify that the pool task no longer exists
getClient(authToken).perform(get("/api/workflow/pooltasks/" + poolTask.getID()))
.andExpect(status().isNotFound());
// verify that the task has been claimed
getClient(authToken).perform(get("/api/workflow/claimedtasks/search/findByUser")
.param("uuid", reviewer.getID().toString()))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.claimedtasks",
Matchers.contains(
Matchers.allOf(
hasJsonPath("$._links.self.href",
Matchers.containsString("/api/workflow/claimedtasks/")),
hasJsonPath("$.type", Matchers.is("claimedtask")),
hasJsonPath("$._embedded.owner",
Matchers.is(EPersonMatcher.matchEPersonOnEmail(
reviewer.getEmail()))),
hasJsonPath("$._embedded.workflowitem",
Matchers.is(WorkflowItemMatcher
.matchItemWithTitleAndDateIssuedAndSubject(
witem, "Workflow Item 1", "2017-10-17", "ExtraEntry")))
))))
.andExpect(jsonPath("$._links.self.href",
Matchers.containsString("/api/workflow/claimedtasks")))
.andExpect(jsonPath("$.page.size", is(20)))
.andExpect(jsonPath("$.page.totalElements", is(1)));
}
/**
* This test will try to delete an archived item whilst using the LoginOnBehalfOf feature to impersonate as a
* normal eperson and thus requiring it to fail with a forbidden flag
* @throws Exception
*/
@Test
public void deleteOneArchivedLoginOnBehalfOfNonAdminForbiddenTest() throws Exception {
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community with one collection.
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.build();
Collection col1 = CollectionBuilder
.createCollection(context, parentCommunity).withName("Collection 1").build();
//2. One public item, one workspace item and one template item.
Item publicItem = ItemBuilder.createItem(context, col1)
.withTitle("Public item 1")
.withIssueDate("2017-10-17")
.withAuthor("Smith, Donald").withAuthor("Doe, John")
.withSubject("ExtraEntry")
.build();
//Add a bitstream to an item
String bitstreamContent = "ThisIsSomeDummyText";
Bitstream bitstream = null;
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
bitstream = BitstreamBuilder.
createBitstream(context, publicItem, is)
.withName("Bitstream1")
.withMimeType("text/plain")
.build();
}
// Check publicItem creation
getClient().perform(get("/api/core/items/" + publicItem.getID()))
.andExpect(status().isOk());
// Check publicItem bitstream creation (shuold be stored in bundle)
getClient().perform(get("/api/core/items/" + publicItem.getID() + "/bundles"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._links.self.href", Matchers
.containsString("/api/core/items/" + publicItem.getID() + "/bundles")));
String token = getAuthToken(admin.getEmail(), password);
//Delete public item
getClient(token).perform(delete("/api/core/items/" + publicItem.getID())
.header("X-On-Behalf-Of", eperson.getID()))
.andExpect(status().isForbidden());
}
}

View File

@@ -24,20 +24,11 @@ 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.CollectionService;
import org.dspace.content.service.ItemService;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
public class MappedCollectionRestRepositoryIT extends AbstractControllerIntegrationTest {
@Autowired
private CollectionService collectionService;
@Autowired
private ItemService itemService;
@Test
public void itemHasNoExtraCollectionsAndCollectionHasNoExtraItemsTest() throws Exception {
context.turnOffAuthorisationSystem();

View File

@@ -22,7 +22,7 @@ import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.app.rest.builder.MetadataSchemaBuilder;
import org.dspace.app.rest.converter.ConverterService;
import org.dspace.app.rest.converter.MetadataSchemaConverter;
import org.dspace.app.rest.matcher.HalMatcher;
import org.dspace.app.rest.matcher.MetadataschemaMatcher;
import org.dspace.app.rest.model.MetadataSchemaRest;
@@ -46,9 +46,9 @@ public class MetadataSchemaRestRepositoryIT extends AbstractControllerIntegratio
private static final String TEST_NAME_UPDATED = "testSchemaNameUpdated";
private static final String TEST_NAMESPACE_UPDATED = "testSchemaNameSpaceUpdated";
@Autowired
ConverterService converter;
@Autowired
private MetadataSchemaConverter metadataSchemaConverter;
@Test
public void findAll() throws Exception {
@@ -90,7 +90,7 @@ public class MetadataSchemaRestRepositoryIT extends AbstractControllerIntegratio
.build();
context.restoreAuthSystemState();
MetadataSchemaRest metadataSchemaRest = converter.toRest(metadataSchema, Projection.DEFAULT);
MetadataSchemaRest metadataSchemaRest = metadataSchemaConverter.convert(metadataSchema, Projection.DEFAULT);
metadataSchemaRest.setPrefix(TEST_NAME);
metadataSchemaRest.setNamespace(TEST_NAMESPACE);
@@ -98,6 +98,7 @@ public class MetadataSchemaRestRepositoryIT extends AbstractControllerIntegratio
AtomicReference<Integer> idRef = new AtomicReference<>();
try {
getClient(authToken)
.perform(post("/api/core/metadataschemas")
.content(new ObjectMapper().writeValueAsBytes(metadataSchemaRest))
@@ -109,6 +110,9 @@ public class MetadataSchemaRestRepositoryIT extends AbstractControllerIntegratio
getClient().perform(get("/api/core/metadataschemas/" + idRef.get()))
.andExpect(status().isOk())
.andExpect(jsonPath("$", MetadataschemaMatcher.matchEntry(TEST_NAME, TEST_NAMESPACE)));
} finally {
MetadataSchemaBuilder.deleteMetadataSchema(idRef.get());
}
}
@Test

View File

@@ -178,7 +178,7 @@ public class MetadatafieldRestRepositoryIT extends AbstractControllerIntegration
String authToken = getAuthToken(admin.getEmail(), password);
AtomicReference<Integer> idRef = new AtomicReference<>();
try {
assertThat(metadataFieldService.findByElement(context, metadataSchema, ELEMENT, QUALIFIER), nullValue());
getClient(authToken)
@@ -194,6 +194,9 @@ public class MetadatafieldRestRepositoryIT extends AbstractControllerIntegration
.andExpect(status().isOk())
.andExpect(jsonPath("$", MetadataFieldMatcher.matchMetadataFieldByKeys(
metadataSchema.getName(), "testElementForCreate", "testQualifierForCreate")));
} finally {
MetadataFieldBuilder.deleteMetadataField(idRef.get());
}
}
@Test

Some files were not shown because too many files have changed in this diff Show More