Merge branch 'DS-4466_new' of https://github.com/4science/DSpace into DS-4466_new

This commit is contained in:
Danilo Di Nuzzo
2020-06-22 18:29:49 +02:00
60 changed files with 1960 additions and 1157 deletions

View File

@@ -590,8 +590,11 @@ public class AuthorizeUtil {
authorizeManageAdminGroup(context, collection);
return;
}
// if we reach this point, it means that the group is related
// to a collection but as it is not the submitters, nor the administrators,
// nor a workflow groups it must be a default item/bitstream groups
authorizeManageDefaultReadGroup(context, collection);
return;
}
if (parentObject.getType() == Constants.COMMUNITY) {
Community community = (Community) parentObject;
@@ -601,4 +604,38 @@ public class AuthorizeUtil {
throw new AuthorizeException("not authorized to manage this group");
}
/**
* This method checks if the community Admin can manage accounts
*
* @return true if is able
*/
public static boolean canCommunityAdminManageAccounts() {
boolean isAble = false;
if (AuthorizeConfiguration.canCommunityAdminManagePolicies()
|| AuthorizeConfiguration.canCommunityAdminManageAdminGroup()
|| AuthorizeConfiguration.canCommunityAdminManageCollectionPolicies()
|| AuthorizeConfiguration.canCommunityAdminManageCollectionSubmitters()
|| AuthorizeConfiguration.canCommunityAdminManageCollectionWorkflows()
|| AuthorizeConfiguration.canCommunityAdminManageCollectionAdminGroup()) {
isAble = true;
}
return isAble;
}
/**
* This method checks if the Collection Admin can manage accounts
*
* @return true if is able
*/
public static boolean canCollectionAdminManageAccounts() {
boolean isAble = false;
if (AuthorizeConfiguration.canCollectionAdminManagePolicies()
|| AuthorizeConfiguration.canCollectionAdminManageSubmitters()
|| AuthorizeConfiguration.canCollectionAdminManageWorkflows()
|| AuthorizeConfiguration.canCollectionAdminManageAdminGroup()) {
isAble = true;
}
return isAble;
}
}

View File

@@ -430,7 +430,11 @@ public class AuthorizeServiceImpl implements AuthorizeService {
public boolean isCommunityAdmin(Context c) throws SQLException {
EPerson e = c.getCurrentUser();
return isCommunityAdmin(c, e);
}
@Override
public boolean isCommunityAdmin(Context c, EPerson e) throws SQLException {
if (e != null) {
List<ResourcePolicy> policies = resourcePolicyService.find(c, e,
groupService.allMemberGroups(c, e),
@@ -446,7 +450,11 @@ public class AuthorizeServiceImpl implements AuthorizeService {
public boolean isCollectionAdmin(Context c) throws SQLException {
EPerson e = c.getCurrentUser();
return isCollectionAdmin(c, e);
}
@Override
public boolean isCollectionAdmin(Context c, EPerson e) throws SQLException {
if (e != null) {
List<ResourcePolicy> policies = resourcePolicyService.find(c, e,
groupService.allMemberGroups(c, e),

View File

@@ -213,6 +213,26 @@ public interface AuthorizeService {
public boolean isCollectionAdmin(Context c) throws SQLException;
/**
* Check to see if a specific user is Community admin
*
* @param c current context
* @param e the user to check
* @return true if user is an admin of some community
* @throws SQLException
*/
public boolean isCommunityAdmin(Context c, EPerson e) throws SQLException;
/**
* Check to see if a specific user is Collection admin
*
* @param c current context
* @param e the user to check
* @return true if user is an admin of some collection
* @throws SQLException if database error
*/
public boolean isCollectionAdmin(Context c, EPerson e) throws SQLException;
///////////////////////////////////////////////
// policy manipulation methods
///////////////////////////////////////////////

View File

@@ -23,7 +23,9 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.dspace.authorize.AuthorizeConfiguration;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject;
import org.dspace.content.DSpaceObjectServiceImpl;
@@ -76,6 +78,8 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
@Autowired(required = true)
protected AuthorizeService authorizeService;
@Autowired(required = true)
protected ResourcePolicyService resourcePolicyService;
protected GroupServiceImpl() {
super();
@@ -654,6 +658,23 @@ public class GroupServiceImpl extends DSpaceObjectServiceImpl<Group> implements
return collectionService.getParentObject(context, collection);
}
}
} else {
if (AuthorizeConfiguration.canCollectionAdminManagePolicies()
|| AuthorizeConfiguration.canCommunityAdminManagePolicies()
|| AuthorizeConfiguration.canCommunityAdminManageCollectionWorkflows()) {
List<Group> groups = new ArrayList<Group>();
groups.add(group);
List<ResourcePolicy> policies = resourcePolicyService.find(context, null, groups,
Constants.DEFAULT_ITEM_READ, Constants.COLLECTION);
if (policies.size() > 0) {
return policies.get(0).getdSpaceObject();
}
policies = resourcePolicyService.find(context, null, groups,
Constants.DEFAULT_BITSTREAM_READ, Constants.COLLECTION);
if (policies.size() > 0) {
return policies.get(0).getdSpaceObject();
}
}
}
}
if (AuthorizeConfiguration.canCommunityAdminManageAdminGroup()) {

View File

@@ -7,8 +7,10 @@
*/
package org.dspace.app.rest.converter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -17,6 +19,7 @@ import java.util.Set;
import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.app.rest.link.HalLinkFactory;
import org.dspace.app.rest.link.HalLinkService;
@@ -26,18 +29,22 @@ 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.repository.DSpaceRestRepository;
import org.dspace.app.rest.security.DSpacePermissionEvaluator;
import org.dspace.app.rest.security.WebSecurityExpressionEvaluator;
import org.dspace.app.rest.utils.Utils;
import org.dspace.services.RequestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.data.domain.Page;
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.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@@ -71,6 +78,12 @@ public class ConverterService {
@Autowired
private DSpacePermissionEvaluator dSpacePermissionEvaluator;
@Autowired
private WebSecurityExpressionEvaluator webSecurityExpressionEvaluator;
@Autowired
private RequestService requestService;
/**
* Converts the given model object to a rest object, using the appropriate {@link DSpaceConverter} and
* the given projection.
@@ -94,8 +107,15 @@ public class ConverterService {
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")) {
BaseObjectRest baseObjectRest = (BaseObjectRest) restObject;
// This section will verify whether the current user has permissions to retrieve the
// rest object. It'll only return the REST object if the permission is granted.
// If permission isn't granted, it'll return null
String preAuthorizeValue = getPreAuthorizeAnnotationForBaseObject(baseObjectRest);
if (!webSecurityExpressionEvaluator
.evaluate(preAuthorizeValue, requestService.getCurrentRequest().getHttpServletRequest(),
requestService.getCurrentRequest().getHttpServletResponse(),
String.valueOf(baseObjectRest.getId()))) {
log.debug("Access denied on " + restObject.getClass() + " with id: " +
((BaseObjectRest) restObject).getId());
return null;
@@ -107,6 +127,48 @@ public class ConverterService {
return restObject;
}
private String getPreAuthorizeAnnotationForBaseObject(BaseObjectRest restObject) {
Annotation preAuthorize = getAnnotationForRestObject(restObject);
if (preAuthorize == null) {
preAuthorize = getDefaultFindOnePreAuthorize();
}
return parseAnnotation(preAuthorize);
}
private String parseAnnotation(Annotation preAuthorize) {
if (preAuthorize != null) {
return (String) AnnotationUtils.getValue(preAuthorize);
}
return null;
}
private Annotation getAnnotationForRestObject(BaseObjectRest restObject) {
BaseObjectRest baseObjectRest = restObject;
DSpaceRestRepository repositoryToUse = utils
.getResourceRepositoryByCategoryAndModel(baseObjectRest.getCategory(), baseObjectRest.getType());
Annotation preAuthorize = null;
for (Method m : repositoryToUse.getClass().getMethods()) {
if (StringUtils.equalsIgnoreCase(m.getName(), "findOne")) {
preAuthorize = AnnotationUtils.findAnnotation(m, PreAuthorize.class);
}
}
return preAuthorize;
}
private Annotation getDefaultFindOnePreAuthorize() {
for (Method m : DSpaceRestRepository.class.getMethods()) {
if (StringUtils.equalsIgnoreCase(m.getName(), "findOne")) {
Annotation annotation = AnnotationUtils.findAnnotation(m, PreAuthorize.class);
if (annotation != null) {
return annotation;
}
}
}
return null;
}
/**
* Converts a list of model objects to a page of rest objects using the given {@link Projection}.
*
@@ -328,19 +390,19 @@ public class ConverterService {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(EntityModel.class));
Set<BeanDefinition> beanDefinitions = provider.findCandidateComponents(
HALResource.class.getPackage().getName().replaceAll("\\.", "/"));
HALResource.class.getPackage().getName().replaceAll("\\.", "/"));
for (BeanDefinition beanDefinition : beanDefinitions) {
String resourceClassName = beanDefinition.getBeanClassName();
String resourceClassSimpleName = resourceClassName.substring(resourceClassName.lastIndexOf(".") + 1);
String restClassSimpleName = resourceClassSimpleName
.replaceAll("ResourceWrapper$", "RestWrapper")
.replaceAll("Resource$", "Rest");
.replaceAll("ResourceWrapper$", "RestWrapper")
.replaceAll("Resource$", "Rest");
String restClassName = RestModel.class.getPackage().getName() + "." + restClassSimpleName;
try {
Class<? extends RestModel> restClass =
(Class<? extends RestModel>) Class.forName(restClassName);
(Class<? extends RestModel>) Class.forName(restClassName);
Class<HALResource<? extends RestModel>> resourceClass =
(Class<HALResource<? extends RestModel>>) Class.forName(resourceClassName);
(Class<HALResource<? extends RestModel>>) Class.forName(resourceClassName);
Constructor compatibleConstructor = null;
for (Constructor constructor : resourceClass.getDeclaredConstructors()) {
if (constructor.getParameterCount() == 2 && constructor.getParameterTypes()[1] == Utils.class) {
@@ -354,11 +416,11 @@ public class ConverterService {
resourceConstructors.put(restClass, compatibleConstructor);
} else {
log.warn("Skipping registration of resource class " + resourceClassName
+ "; compatible constructor not found");
+ "; compatible constructor not found");
}
} catch (ClassNotFoundException e) {
log.warn("Skipping registration of resource class " + resourceClassName
+ "; rest class not found: " + restClassName);
+ "; rest class not found: " + restClassName);
}
}
}

View File

@@ -22,7 +22,9 @@ import org.springframework.stereotype.Component;
/**
* This filter assures that when the dspace instance supports multiple languages
* they are noted in the Content-Language Header of the response
* they are noted in the Content-Language Header of the response. Where
* appropriate the single endpoint can set the Content-Language header directly
* to note that the response is specific for a language
*
* @author Mykhaylo Boychuk (at 4science.it)
*/
@@ -36,20 +38,17 @@ public class ContentLanguageHeaderResponseFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if (!httpServletResponse.containsHeader("Content-Language")) {
Locale[] locales = I18nUtil.getSupportedLocales();
StringBuilder locsStr = new StringBuilder();
for (Locale locale : locales) {
if (locsStr.length() > 0) {
locsStr.append(",");
}
locsStr.append(locale.getLanguage());
Locale[] locales = I18nUtil.getSupportedLocales();
StringBuilder locsStr = new StringBuilder();
for (Locale locale : locales) {
if (locsStr.length() > 0) {
locsStr.append(",");
}
httpServletResponse.setHeader("Content-Language", locsStr.toString());
locsStr.append(locale.getLanguage());
}
httpServletResponse.setHeader("Content-Language", locsStr.toString());
chain.doFilter(request, response);
}
@Override

View File

@@ -12,7 +12,7 @@ import org.dspace.app.rest.ExternalSourcesRestController;
/**
* This class serves as a REST representation for an entry of external data
*/
public class ExternalSourceEntryRest extends BaseObjectRest<String> {
public class ExternalSourceEntryRest extends RestAddressableModel {
public static final String NAME = "externalSourceEntry";
public static final String PLURAL_NAME = "externalSourceEntries";

View File

@@ -48,7 +48,7 @@ public class AuthorizationFeatureRestRepository extends DSpaceRestRepository<Aut
return converter.toRestPage(authorizationFeatureService.findAll(), pageable, utils.obtainProjection());
}
@PreAuthorize("hasAuthority('ADMIN')")
@PreAuthorize("permitAll()")
@Override
public AuthorizationFeatureRest findOne(Context context, String id) {
AuthorizationFeature authzFeature = authorizationFeatureService.find(id);

View File

@@ -74,11 +74,11 @@ public class BundleRestRepository extends DSpaceObjectRestRepository<Bundle, Bun
this.bundleService = dsoService;
}
@PreAuthorize("hasPermission(#uuid, 'BUNDLE', 'READ')")
public BundleRest findOne(Context context, UUID uuid) {
@PreAuthorize("hasPermission(#id, 'BUNDLE', 'READ')")
public BundleRest findOne(Context context, UUID id) {
Bundle bundle = null;
try {
bundle = bundleService.find(context, uuid);
bundle = bundleService.find(context, id);
} catch (SQLException e) {
throw new RuntimeException(e.getMessage(), e);
}

View File

@@ -155,7 +155,7 @@ public class EPersonRestRepository extends DSpaceObjectRestRepository<EPerson, E
* contains the pagination information
* @return a Page of EPersonRest instances matching the user query
*/
@PreAuthorize("hasAuthority('ADMIN')")
@PreAuthorize("hasAuthority('ADMIN') || hasAuthority('MANAGE_ACCESS_GROUP')")
@SearchRestMethod(name = "byMetadata")
public Page<EPersonRest> findByMetadata(@Parameter(value = "query", required = true) String query,
Pageable pageable) {

View File

@@ -30,6 +30,7 @@ public class EntityTypeRestRepository extends DSpaceRestRepository<EntityTypeRes
@Autowired
private EntityTypeService entityTypeService;
@Override
@PreAuthorize("permitAll()")
public EntityTypeRest findOne(Context context, Integer integer) {
try {
@@ -43,6 +44,7 @@ public class EntityTypeRestRepository extends DSpaceRestRepository<EntityTypeRes
}
}
@Override
public Page<EntityTypeRest> findAll(Context context, Pageable pageable) {
try {
List<EntityType> entityTypes = entityTypeService.findAll(context);
@@ -52,6 +54,7 @@ public class EntityTypeRestRepository extends DSpaceRestRepository<EntityTypeRes
}
}
@Override
public Class<EntityTypeRest> getDomainClass() {
return EntityTypeRest.class;
}

View File

@@ -131,7 +131,7 @@ public class GroupRestRepository extends DSpaceObjectRestRepository<Group, Group
* @param pageable contains the pagination information
* @return a Page of GroupRest instances matching the user query
*/
@PreAuthorize("hasAuthority('ADMIN')")
@PreAuthorize("hasAuthority('ADMIN') || hasAuthority('MANAGE_ACCESS_GROUP')")
@SearchRestMethod(name = "byMetadata")
public Page<GroupRest> findByMetadata(@Parameter(value = "query", required = true) String query,
Pageable pageable) {

View File

@@ -7,7 +7,10 @@
*/
package org.dspace.app.rest.repository;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
@@ -16,10 +19,6 @@ import org.dspace.app.rest.model.AccessConditionOptionRest;
import org.dspace.app.rest.model.SubmissionUploadRest;
import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.utils.DateMathParser;
import org.dspace.app.util.SubmissionConfig;
import org.dspace.app.util.SubmissionConfigReader;
import org.dspace.app.util.SubmissionConfigReaderException;
import org.dspace.app.util.SubmissionStepConfig;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
@@ -28,7 +27,6 @@ import org.dspace.submit.model.UploadConfiguration;
import org.dspace.submit.model.UploadConfigurationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
@@ -45,8 +43,6 @@ public class SubmissionUploadRestRepository extends DSpaceRestRepository<Submiss
private static final Logger log = org.apache.logging.log4j.LogManager
.getLogger(SubmissionUploadRestRepository.class);
private SubmissionConfigReader submissionConfigReader;
@Autowired
private SubmissionFormRestRepository submissionFormRestRepository;
@@ -58,10 +54,6 @@ public class SubmissionUploadRestRepository extends DSpaceRestRepository<Submiss
DateMathParser dateMathParser = new DateMathParser();
public SubmissionUploadRestRepository() throws SubmissionConfigReaderException {
submissionConfigReader = new SubmissionConfigReader();
}
@PreAuthorize("hasAuthority('AUTHENTICATED')")
@Override
public SubmissionUploadRest findOne(Context context, String submitName) {
@@ -77,27 +69,21 @@ public class SubmissionUploadRestRepository extends DSpaceRestRepository<Submiss
@PreAuthorize("hasAuthority('AUTHENTICATED')")
@Override
public Page<SubmissionUploadRest> findAll(Context context, Pageable pageable) {
List<SubmissionConfig> subConfs = new ArrayList<SubmissionConfig>();
subConfs = submissionConfigReader.getAllSubmissionConfigs(pageable.getPageSize(),
Math.toIntExact(pageable.getOffset()));
Collection<UploadConfiguration> uploadConfigs = uploadConfigurationService.getMap().values();
Projection projection = utils.obtainProjection();
List<SubmissionUploadRest> results = new ArrayList<>();
for (SubmissionConfig config : subConfs) {
for (int i = 0; i < config.getNumberOfSteps(); i++) {
SubmissionStepConfig step = config.getStep(i);
if (SubmissionStepConfig.UPLOAD_STEP_NAME.equals(step.getType())) {
UploadConfiguration uploadConfig = uploadConfigurationService.getMap().get(step.getId());
if (uploadConfig != null) {
try {
results.add(convert(context, uploadConfig, projection));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
List<String> configNames = new ArrayList<String>();
for (UploadConfiguration uploadConfig : uploadConfigs) {
if (!configNames.contains(uploadConfig.getName())) {
configNames.add(uploadConfig.getName());
try {
results.add(convert(context, uploadConfig, projection));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
return new PageImpl<SubmissionUploadRest>(results, pageable, results.size());
return utils.getPage(results, pageable);
}
@Override
@@ -105,20 +91,31 @@ public class SubmissionUploadRestRepository extends DSpaceRestRepository<Submiss
return SubmissionUploadRest.class;
}
private SubmissionUploadRest convert(Context context, UploadConfiguration config, Projection projection)
throws Exception {
private SubmissionUploadRest convert(Context context, UploadConfiguration config, Projection projection) {
SubmissionUploadRest result = new SubmissionUploadRest();
result.setProjection(projection);
for (AccessConditionOption option : config.getOptions()) {
AccessConditionOptionRest optionRest = new AccessConditionOptionRest();
if (option.getGroupName() != null) {
Group group = groupService.findByName(context, option.getGroupName());
Group group;
try {
group = groupService.findByName(context, option.getGroupName());
} catch (SQLException e) {
throw new IllegalStateException("Wrong group name configuration for the access condition "
+ "option named " + option.getName());
}
if (group != null) {
optionRest.setGroupUUID(group.getID());
}
}
if (option.getSelectGroupName() != null) {
Group group = groupService.findByName(context, option.getSelectGroupName());
Group group;
try {
group = groupService.findByName(context, option.getSelectGroupName());
} catch (SQLException e) {
throw new IllegalStateException("Wrong select group name configuration for the access condition "
+ "option named " + option.getName());
}
if (group != null) {
optionRest.setSelectGroupUUID(group.getID());
}
@@ -126,10 +123,20 @@ public class SubmissionUploadRestRepository extends DSpaceRestRepository<Submiss
optionRest.setHasStartDate(option.getHasStartDate());
optionRest.setHasEndDate(option.getHasEndDate());
if (StringUtils.isNotBlank(option.getStartDateLimit())) {
optionRest.setMaxStartDate(dateMathParser.parseMath(option.getStartDateLimit()));
try {
optionRest.setMaxStartDate(dateMathParser.parseMath(option.getStartDateLimit()));
} catch (ParseException e) {
throw new IllegalStateException("Wrong start date limit configuration for the access condition "
+ "option named " + option.getName());
}
}
if (StringUtils.isNotBlank(option.getEndDateLimit())) {
optionRest.setMaxEndDate(dateMathParser.parseMath(option.getEndDateLimit()));
try {
optionRest.setMaxEndDate(dateMathParser.parseMath(option.getEndDateLimit()));
} catch (ParseException e) {
throw new IllegalStateException("Wrong end date limit configuration for the access condition "
+ "option named " + option.getName());
}
}
optionRest.setName(option.getName());
result.getAccessConditionOptions().add(optionRest);

View File

@@ -28,6 +28,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;
/**
@@ -49,6 +50,7 @@ public class TemplateItemRestRepository extends DSpaceRestRepository<TemplateIte
ResourcePatch<Item> resourcePatch;
@Override
@PreAuthorize("permitAll()")
public TemplateItemRest findOne(Context context, UUID uuid) {
Item item = null;
try {

View File

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -18,6 +18,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.util.AuthorizeUtil;
import org.dspace.authenticate.AuthenticationMethod;
import org.dspace.authenticate.service.AuthenticationService;
import org.dspace.authorize.service.AuthorizeService;
@@ -47,6 +48,8 @@ public class EPersonRestAuthenticationProvider implements AuthenticationProvider
private static final Logger log = LoggerFactory.getLogger(EPersonRestAuthenticationProvider.class);
public static final String MANAGE_ACCESS_GROUP = "MANAGE_ACCESS_GROUP";
@Autowired
private AuthenticationService authenticationService;
@@ -140,14 +143,21 @@ public class EPersonRestAuthenticationProvider implements AuthenticationProvider
if (eperson != null) {
boolean isAdmin = false;
boolean isCommunityAdmin = false;
boolean isCollectionAdmin = false;
try {
isAdmin = authorizeService.isAdmin(context, eperson);
isCommunityAdmin = authorizeService.isCommunityAdmin(context, eperson);
isCollectionAdmin = authorizeService.isCollectionAdmin(context, eperson);
} catch (SQLException e) {
log.error("SQL error while checking for admin rights", e);
}
if (isAdmin) {
authorities.add(new SimpleGrantedAuthority(ADMIN_GRANT));
} else if ((isCommunityAdmin && AuthorizeUtil.canCommunityAdminManageAccounts())
|| (isCollectionAdmin && AuthorizeUtil.canCollectionAdminManageAccounts())) {
authorities.add(new SimpleGrantedAuthority(MANAGE_ACCESS_GROUP));
}
authorities.add(new SimpleGrantedAuthority(AUTHENTICATED_GRANT));

View File

@@ -17,6 +17,7 @@ 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.app.util.AuthorizeUtil;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
@@ -74,9 +75,13 @@ public class EPersonRestPermissionEvaluatorPlugin extends RestObjectPermissionEv
// anonymous user
if (ePerson == null) {
return false;
}
if (dsoId.equals(ePerson.getID())) {
} else if (dsoId.equals(ePerson.getID())) {
return true;
} else if (authorizeService.isCommunityAdmin(context, ePerson)
&& AuthorizeUtil.canCommunityAdminManageAccounts()) {
return true;
} else if (authorizeService.isCollectionAdmin(context, ePerson)
&& AuthorizeUtil.canCollectionAdminManageAccounts()) {
return true;
}

View File

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -12,6 +12,8 @@ import java.sql.SQLException;
import java.util.UUID;
import org.dspace.app.rest.utils.ContextUtil;
import org.dspace.app.util.AuthorizeUtil;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
@@ -44,6 +46,9 @@ public class GroupRestPermissionEvaluatorPlugin extends RestObjectPermissionEval
@Autowired
private EPersonService ePersonService;
@Autowired
AuthorizeService authorizeService;
@Override
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId,
String targetType, DSpaceRestPermission permission) {
@@ -64,7 +69,16 @@ public class GroupRestPermissionEvaluatorPlugin extends RestObjectPermissionEval
Group group = groupService.find(context, dsoId);
if (groupService.isMember(context, ePerson, group)) {
// anonymous user
if (ePerson == null) {
return false;
} else if (groupService.isMember(context, ePerson, group)) {
return true;
} else if (authorizeService.isCommunityAdmin(context, ePerson)
&& AuthorizeUtil.canCommunityAdminManageAccounts()) {
return true;
} else if (authorizeService.isCollectionAdmin(context, ePerson)
&& AuthorizeUtil.canCollectionAdminManageAccounts()) {
return true;
}

View File

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,30 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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,95 @@
/**
* 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.util.List;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.GenericTypeResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Component;
/**
* This class will contain the logic to allow us to evaluate an expression given through a String.
* This will be used by the {@link org.dspace.app.rest.converter.ConverterService} for parsing
* the {@link org.springframework.security.access.prepost.PreAuthorize} annotations used on the findOne
* methods of RestRepositories. A String will be given to the evaluate method and that String will then
* be parsed and a boolean will be returned based on the condition in the String.
* For example: "hasPermission(#id, 'ITEM', 'READ')" is such a String
* This will be evaluated and if the current user has the permission to read an item with the given id,
* a true will be returned, if not it'll be false.
* This works on all the methods in {@link org.springframework.security.access.expression.SecurityExpressionRoot}
*/
@Component
public class WebSecurityExpressionEvaluator {
private static final FilterChain EMPTY_CHAIN = (request, response) -> {
throw new UnsupportedOperationException();
};
private final List<SecurityExpressionHandler> securityExpressionHandlers;
/**
* Constructor for this class that sets all the {@link SecurityExpressionHandler} objects in a list
* @param securityExpressionHandlers The {@link SecurityExpressionHandler} for this class
*/
public WebSecurityExpressionEvaluator(List<SecurityExpressionHandler> securityExpressionHandlers) {
this.securityExpressionHandlers = securityExpressionHandlers;
}
/**
* This method will have to be used to evaluate the String given. It'll parse the String and resolve
* it to a method in {@link org.springframework.security.access.expression.SecurityExpressionRoot}
* and evaluate it to then return a boolean
* @param securityExpression The String that resembles the expression that has to be parsed
* @param request The current request
* @param response The current response
* @param id The id for the Object that is the subject of the permission
* @return A boolean indicating whether the currentUser adheres to the
* permissions in the securityExpression String or not
*/
public boolean evaluate(String securityExpression, HttpServletRequest request, HttpServletResponse response,
String id) {
SecurityExpressionHandler handler = getFilterSecurityHandler();
Expression expression = handler.getExpressionParser().parseExpression(securityExpression);
EvaluationContext evaluationContext = createEvaluationContext(handler, request, response);
evaluationContext.setVariable("id", id);
return ExpressionUtils.evaluateAsBoolean(expression, evaluationContext);
}
@SuppressWarnings("unchecked")
private EvaluationContext createEvaluationContext(SecurityExpressionHandler handler, HttpServletRequest request,
HttpServletResponse response) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
FilterInvocation filterInvocation = new FilterInvocation(request, response, EMPTY_CHAIN);
return handler.createEvaluationContext(authentication, filterInvocation);
}
private SecurityExpressionHandler getFilterSecurityHandler() {
return securityExpressionHandlers.stream()
.filter(handler ->
FilterInvocation.class.equals(
GenericTypeResolver.resolveTypeArgument(handler.getClass(),
SecurityExpressionHandler.class)))
.findAny()
.orElseThrow(() -> new IllegalStateException("No filter invocation security" +
" expression handler has been found! Handlers: " +
securityExpressionHandlers.size()));
}
}

View File

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -1,31 +0,0 @@
/**
* 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

@@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
/**
* Test suite for the Authorization Feature endpoint
*
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*
*/
@@ -50,10 +50,10 @@ public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerInte
// verify that only the admin can access the endpoint (see subsequent call in the method)
getClient(adminToken).perform(get("/api/authz/features")).andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(expReturn))))
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$.page.size", is(20)))
.andExpect(jsonPath("$.page.totalElements", is(featuresNum)));
.andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(expReturn))))
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$.page.size", is(20)))
.andExpect(jsonPath("$.page.totalElements", is(featuresNum)));
// verify that anonymous user cannot access
getClient().perform(get("/api/authz/features")).andExpect(status().isUnauthorized());
// verify that normal user cannot access
@@ -78,21 +78,21 @@ public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerInte
AtomicReference<String> idRef = new AtomicReference<String>();
getClient(adminToken)
.perform(get("/api/authz/features").param("page", String.valueOf(page)).param("size", "1"))
.andExpect(status().isOk()).andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(1))))
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features")))
.andExpect(
(page == 0) ? jsonPath("$._links.prev.href").doesNotExist()
: jsonPath("$._links.prev.href", Matchers.containsString("/api/authz/features")))
.andExpect((page == featuresNum - 1)
? jsonPath("$._links.next.href").doesNotExist()
: jsonPath("$._links.next.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$._links.first.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$._links.last.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$.page.size", is(1)))
.andExpect(jsonPath("$.page.totalElements", is(Integer.valueOf(featuresNum))))
.andDo(result -> idRef
.set(read(result.getResponse().getContentAsString(), "$._embedded.features[0].id")));
.perform(get("/api/authz/features").param("page", String.valueOf(page)).param("size", "1"))
.andExpect(status().isOk()).andExpect(jsonPath("$._embedded.features", Matchers.hasSize(is(1))))
.andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/authz/features")))
.andExpect(
(page == 0) ? jsonPath("$._links.prev.href").doesNotExist()
: jsonPath("$._links.prev.href", Matchers.containsString("/api/authz/features")))
.andExpect((page == featuresNum - 1)
? jsonPath("$._links.next.href").doesNotExist()
: jsonPath("$._links.next.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$._links.first.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$._links.last.href", Matchers.containsString("/api/authz/features")))
.andExpect(jsonPath("$.page.size", is(1)))
.andExpect(jsonPath("$.page.totalElements", is(Integer.valueOf(featuresNum))))
.andDo(result -> idRef
.set(read(result.getResponse().getContentAsString(), "$._embedded.features[0].id")));
if (idRef.get() == null || featureIDs.contains(idRef.get())) {
fail("Duplicate feature " + idRef.get() + " returned at page " + page);
@@ -108,30 +108,17 @@ public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerInte
* @throws Exception
*/
public void findOneTest() throws Exception {
String adminToken = getAuthToken(admin.getEmail(), password);
// verify that only the admin can access the endpoint (see subsequent call in the method)
getClient(adminToken).perform(get("/api/authz/features/withdrawItem")).andExpect(status().isOk())
.andExpect(jsonPath("$.id", is("withdrawItem")))
.andExpect(jsonPath("$.description", Matchers.any(String.class)))
.andExpect(jsonPath("$.resourcetypes", Matchers.contains("core.item")))
.andExpect(jsonPath("$.type", is("feature")));
// verify that anonymous user cannot access
getClient().perform(get("/api/authz/features/withdrawItem")).andExpect(status().isUnauthorized());
// verify that normal user cannot access
String epersonAuthToken = getAuthToken(eperson.getEmail(), password);
getClient(epersonAuthToken).perform(get("/api/authz/features/withdrawItem")).andExpect(status().isForbidden());
getClient().perform(get("/api/authz/features/withdrawItem")).andExpect(status().isOk())
.andExpect(jsonPath("$.id", is("withdrawItem")))
.andExpect(jsonPath("$.description", Matchers.any(String.class)))
.andExpect(jsonPath("$.resourcetypes", Matchers.contains("core.item")))
.andExpect(jsonPath("$.type", is("feature")));
}
@Test
public void findOneNotFoundTest() throws Exception {
String adminToken = getAuthToken(admin.getEmail(), password);
// verify that only the admin can access the endpoint and get the not found response code
// (see subsequent calls in the method for unauthorized and forbidden attempts)
getClient(adminToken).perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isNotFound());
// verify that anonymous user cannot access, without information disclosure
getClient().perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isUnauthorized());
// verify that normal user cannot access, without information disclosure
getClient(adminToken).perform(get("/api/authz/features/1")).andExpect(status().isNotFound());
getClient().perform(get("/api/authz/features/not-existing-feature")).andExpect(status().isNotFound());
}
@Test
@@ -146,27 +133,28 @@ public class AuthorizationFeatureRestRepositoryIT extends AbstractControllerInte
for (String type : alwaysTrueFeature.getSupportedTypes()) {
// verify that only the admin can access the endpoint (see subsequent call in the method)
getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", type))
.andExpect(status().isOk())
.andExpect(jsonPath("$",
JsonPathMatchers.hasJsonPath("$._embedded.features",
Matchers.everyItem(
JsonPathMatchers.hasJsonPath("$.resourcetypes",
Matchers.hasItem(is(type))))
)))
.andExpect(
jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/features/search/resourcetype")));
.andExpect(status().isOk())
.andExpect(jsonPath("$",
JsonPathMatchers.hasJsonPath("$._embedded.features",
Matchers.everyItem(
JsonPathMatchers.hasJsonPath(
"$.resourcetypes",
Matchers.hasItem(is(type))))
)))
.andExpect(
jsonPath("$._links.self.href",
Matchers.containsString("/api/authz/features/search/resourcetype")));
}
// verify that the right response code is returned also for not existing types
getClient(adminToken).perform(get("/api/authz/features/search/resourcetype").param("type", "NOT-EXISTING"))
.andExpect(status().isOk()).andExpect(jsonPath("$.page.totalElements", is(0)));
.andExpect(status().isOk()).andExpect(jsonPath("$.page.totalElements", is(0)));
// verify that anonymous user cannot access, without information disclosure
getClient().perform(get("/api/authz/features/search/resourcetype").param("type", "core.item"))
.andExpect(status().isUnauthorized());
.andExpect(status().isUnauthorized());
// verify that normal user cannot access, without information disclosure
String epersonAuthToken = getAuthToken(eperson.getEmail(), password);
getClient(epersonAuthToken).perform(get("/api/authz/features/search/resourcetype").param("type", "core.item"))
.andExpect(status().isForbidden());
.andExpect(status().isForbidden());
}

View File

@@ -35,7 +35,6 @@ 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;
@@ -971,11 +970,7 @@ 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";
@@ -993,11 +988,7 @@ 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";
@@ -1120,13 +1111,7 @@ 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 {
@@ -1161,12 +1146,7 @@ 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();
@@ -1475,11 +1455,7 @@ 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";
@@ -1497,11 +1473,7 @@ 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";
@@ -1627,13 +1599,7 @@ 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 {
@@ -1668,12 +1634,7 @@ 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 {

View File

@@ -10,6 +10,7 @@ package org.dspace.app.rest;
import static com.jayway.jsonpath.JsonPath.read;
import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata;
import static org.hamcrest.Matchers.allOf;
import static org.springframework.http.MediaType.parseMediaType;
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;
@@ -20,21 +21,31 @@ 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.GroupBuilder;
import org.dspace.app.rest.matcher.EPersonMatcher;
import org.dspace.app.rest.matcher.GroupMatcher;
import org.dspace.app.rest.model.GroupRest;
import org.dspace.app.rest.model.MetadataRest;
import org.dspace.app.rest.model.MetadataValueRest;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.core.Constants;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.dspace.eperson.service.GroupService;
import org.dspace.services.ConfigurationService;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
public class CommunityAdminGroupRestControllerIT extends AbstractControllerIntegrationTest {
@@ -48,10 +59,19 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerInteg
@Autowired
private AuthorizeService authorizeService;
@Autowired
private CollectionService collectionService;
@Autowired
private ConfigurationService configurationService;
Collection collection;
@Before
public void setup() {
context.turnOffAuthorisationSystem();
parentCommunity = CommunityBuilder.createCommunity(context).withName("test").build();
collection = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build();
context.restoreAuthSystemState();
}
@@ -437,4 +457,328 @@ public class CommunityAdminGroupRestControllerIT extends AbstractControllerInteg
getClient(token).perform(delete("/api/core/communities/" + UUID.randomUUID() + "/adminGroup"))
.andExpect(status().isNotFound());
}
@Test
public void communityAdminAddMembersToCommunityAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = communityService.createAdministrators(context, parentCommunity);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build();
configurationService.setProperty("core.authorization.community-admin.admin-group", false);
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/epersons")
.contentType(parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/epersons"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.epersons", Matchers.not(Matchers.hasItem(
EPersonMatcher.matchEPersonOnEmail(ePerson.getEmail())
))));
}
@Test
public void communityAdminRemoveMembersFromCommunityAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = communityService.createAdministrators(context, parentCommunity);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/epersons")
.contentType(parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/epersons/" + ePerson.getID()));
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/epersons"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.epersons", Matchers.hasItem(
EPersonMatcher.matchEPersonOnEmail(ePerson.getEmail())
)));
configurationService.setProperty("core.authorization.community-admin.admin-group", false);
getClient(token).perform(delete("/api/eperson/groups/" + adminGroup.getID() + "/epersons/" + ePerson.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/epersons"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.epersons", Matchers.hasItem(
EPersonMatcher.matchEPersonOnEmail(ePerson.getEmail())
)));
}
@Test
public void communityAdminAddChildGroupToCommunityAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = communityService.createAdministrators(context, parentCommunity);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
Group group = GroupBuilder.createGroup(context).withName("testGroup").build();
configurationService.setProperty("core.authorization.community-admin.admin-group", false);
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/subgroups")
.contentType(parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/groups/" + group.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.not(Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
))));
}
@Test
public void communityAdminRemoveChildGroupFromCommunityAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = communityService.createAdministrators(context, parentCommunity);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
Group group = GroupBuilder.createGroup(context).withName("testGroup").build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/subgroups")
.contentType(parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/groups/" + group.getID()));
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
)));
configurationService.setProperty("core.authorization.community-admin.admin-group", false);
getClient(token).perform(delete("/api/eperson/groups/" + adminGroup.getID() + "/subgroups/" + group.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
)));
}
@Test
public void communityAdminAddChildGroupToCollectionAdminGroupSuccess() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
Group group = GroupBuilder.createGroup(context).withName("testGroup").build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/subgroups")
.contentType(MediaType.parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/groups/" + group.getID()));
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
)));
}
@Test
public void communityAdminRemoveChildGroupFromCollectionAdminGroupSuccess() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
Group group = GroupBuilder.createGroup(context).withName("testGroup").build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/subgroups")
.contentType(MediaType.parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/groups/" + group.getID()));
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
)));
getClient(token).perform(delete("/api/eperson/groups/" + adminGroup.getID() + "/subgroups/" + group.getID()))
.andExpect(status().isNoContent());
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.not(Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
))));
}
@Test
public void communityAdminAddMembersToCollectionAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build();
configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false);
configurationService.setProperty("core.authorization.collection-admin.admin-group", false);
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/epersons")
.contentType(MediaType.parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/epersons/" + ePerson.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/epersons"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.epersons", Matchers.not(Matchers.hasItem(
EPersonMatcher.matchEPersonOnEmail(ePerson.getEmail())
))));
}
@Test
public void communityAdminRemoveMembersFromCollectionAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
EPerson ePerson = EPersonBuilder.createEPerson(context).withEmail("testToAdd@test.com").build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/epersons")
.contentType(MediaType.parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/epersons/" + ePerson.getID()));
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/epersons"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.epersons", Matchers.hasItem(
EPersonMatcher.matchEPersonOnEmail(ePerson.getEmail())
)));
configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false);
configurationService.setProperty("core.authorization.collection-admin.admin-group", false);
getClient(token).perform(delete("/api/eperson/groups/" + adminGroup.getID() + "/epersons/" + ePerson.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/epersons"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.epersons", Matchers.hasItem(
EPersonMatcher.matchEPersonOnEmail(ePerson.getEmail())
)));
}
@Test
public void communityAdminAddChildGroupToCollectionAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
Group group = GroupBuilder.createGroup(context).withName("testGroup").build();
configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false);
configurationService.setProperty("core.authorization.collection-admin.admin-group", false);
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/subgroups")
.contentType(MediaType.parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/groups/" + group.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.not(Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
))));
}
@Test
public void communityAdminRemoveChildGroupFromCollectionAdminGroupPropertySetToFalse() throws Exception {
context.turnOffAuthorisationSystem();
Group adminGroup = collectionService.createAdministrators(context, collection);
authorizeService.addPolicy(context, parentCommunity, Constants.ADMIN, eperson);
Group group = GroupBuilder.createGroup(context).withName("testGroup").build();
context.restoreAuthSystemState();
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(
post("/api/eperson/groups/" + adminGroup.getID() + "/subgroups")
.contentType(MediaType.parseMediaType
(org.springframework.data.rest.webmvc.RestMediaTypes
.TEXT_URI_LIST_VALUE))
.content("https://localhost:8080/server/api/eperson/groups/" + group.getID()));
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
)));
configurationService.setProperty("core.authorization.community-admin.collection.admin-group", false);
configurationService.setProperty("core.authorization.collection-admin.admin-group", false);
getClient(token).perform(delete("/api/eperson/groups/" + adminGroup.getID() + "/subgroups/" + group.getID()))
.andExpect(status().isForbidden());
token = getAuthToken(admin.getEmail(), password);
getClient(token).perform(get("/api/eperson/groups/" + adminGroup.getID() + "/subgroups"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.subgroups", Matchers.hasItem(
GroupMatcher.matchGroupWithName(group.getName())
)));
}
}

View File

@@ -25,6 +25,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
@@ -48,15 +49,20 @@ import org.dspace.app.rest.model.patch.ReplaceOperation;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.app.rest.test.MetadataPatchSuite;
import org.dspace.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.services.ConfigurationService;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
@Autowired
private ConfigurationService configurationService;
@Test
public void createTest() throws Exception {
@@ -1787,6 +1793,167 @@ public class EPersonRestRepositoryIT extends AbstractControllerIntegrationTest {
}
@Test
public void findByMetadataByCommAdminAndByColAdminTest() throws Exception {
context.turnOffAuthorisationSystem();
EPerson adminChild1 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Oliver", "Rossi")
.withEmail("adminChild1@example.com")
.withPassword(password)
.build();
EPerson adminCol1 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("James", "Rossi")
.withEmail("adminCol1@example.com")
.withPassword(password)
.build();
EPerson colSubmitter = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Carl", "Rossi")
.withEmail("colSubmitter@example.com")
.withPassword(password)
.build();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.withAdminGroup(eperson)
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.withAdminGroup(adminChild1)
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1)
.withName("Collection 1")
.withAdminGroup(adminCol1)
.withSubmitterGroup(colSubmitter)
.build();
context.restoreAuthSystemState();
String tokenAdminComm = getAuthToken(adminChild1.getEmail(), password);
String tokenAdminCol = getAuthToken(adminCol1.getEmail(), password);
String tokencolSubmitter = getAuthToken(colSubmitter.getEmail(), password);
getClient(tokenAdminComm).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", "Rossi"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.epersons", Matchers.containsInAnyOrder(
EPersonMatcher.matchEPersonEntry(adminChild1),
EPersonMatcher.matchEPersonEntry(adminCol1),
EPersonMatcher.matchEPersonEntry(colSubmitter)
)))
.andExpect(jsonPath("$.page.totalElements", is(3)));
getClient(tokenAdminCol).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", "Rossi"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.epersons", Matchers.containsInAnyOrder(
EPersonMatcher.matchEPersonEntry(adminChild1),
EPersonMatcher.matchEPersonEntry(adminCol1),
EPersonMatcher.matchEPersonEntry(colSubmitter)
)))
.andExpect(jsonPath("$.page.totalElements", is(3)));
getClient(tokencolSubmitter).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", "Rossi"))
.andExpect(status().isForbidden());
}
@Test
public void findByMetadataByCommAdminAndByColAdminWithoutAuthorizationsTest() throws Exception {
context.turnOffAuthorisationSystem();
List<String> confPropsCollectionAdmins = new LinkedList<>();
confPropsCollectionAdmins.add("core.authorization.collection-admin.policies");
confPropsCollectionAdmins.add("core.authorization.collection-admin.workflows");
confPropsCollectionAdmins.add("core.authorization.collection-admin.submitters");
confPropsCollectionAdmins.add("core.authorization.collection-admin.admin-group");
List<String> confPropsCommunityAdmins = new LinkedList<>();
confPropsCommunityAdmins.add("core.authorization.community-admin.policies");
confPropsCommunityAdmins.add("core.authorization.community-admin.admin-group");
confPropsCommunityAdmins.add("core.authorization.community-admin.collection.policies");
confPropsCommunityAdmins.add("core.authorization.community-admin.collection.workflows");
confPropsCommunityAdmins.add("core.authorization.community-admin.collection.submitters");
confPropsCommunityAdmins.add("core.authorization.community-admin.collection.admin-group");
EPerson adminChild1 = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Oliver", "Rossi")
.withEmail("adminChild1@example.com")
.withPassword(password)
.build();
EPerson adminCol = EPersonBuilder.createEPerson(context)
.withNameInMetadata("James", "Rossi")
.withEmail("adminCol1@example.com")
.withPassword(password)
.build();
EPerson col1Submitter = EPersonBuilder.createEPerson(context)
.withNameInMetadata("Carl", "Rossi")
.withEmail("col1Submitter@example.com")
.withPassword(password)
.build();
parentCommunity = CommunityBuilder.createCommunity(context)
.withName("Parent Community")
.withAdminGroup(eperson)
.build();
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.withAdminGroup(adminChild1)
.build();
Collection col1 = CollectionBuilder.createCollection(context, child1)
.withName("Collection 1")
.withAdminGroup(adminCol)
.withSubmitterGroup(col1Submitter)
.build();
context.restoreAuthSystemState();
String tokenAdminCol = getAuthToken(adminCol.getEmail(), password);
String tokenAdminComm = getAuthToken(adminChild1.getEmail(), password);
for (String prop : confPropsCollectionAdmins) {
getClient(tokenAdminCol).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", "Rossi"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.epersons", Matchers.containsInAnyOrder(
EPersonMatcher.matchEPersonEntry(adminChild1),
EPersonMatcher.matchEPersonEntry(adminCol),
EPersonMatcher.matchEPersonEntry(col1Submitter)
)))
.andExpect(jsonPath("$.page.totalElements", is(3)));
configurationService.setProperty(prop, false);
}
getClient(tokenAdminCol).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", "Rossi"))
.andExpect(status().isForbidden());
for (String prop : confPropsCommunityAdmins) {
getClient(tokenAdminComm).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", "Rossi"))
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$._embedded.epersons", Matchers.containsInAnyOrder(
EPersonMatcher.matchEPersonEntry(adminChild1),
EPersonMatcher.matchEPersonEntry(adminCol),
EPersonMatcher.matchEPersonEntry(col1Submitter)
)))
.andExpect(jsonPath("$.page.totalElements", is(3)));
configurationService.setProperty(prop, false);
}
getClient(tokenAdminComm).perform(get("/api/eperson/epersons/search/byMetadata")
.param("query", "Rossi"))
.andExpect(status().isForbidden());
}
@Test
public void discoverableNestedLinkTest() throws Exception {
String token = getAuthToken(eperson.getEmail(), password);

View File

@@ -18,6 +18,7 @@ import org.dspace.content.authority.ChoiceAuthorityServiceImpl;
import org.dspace.core.LegacyPluginServiceImpl;
import org.dspace.eperson.EPerson;
import org.dspace.services.ConfigurationService;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -42,6 +43,8 @@ public class LanguageSupportIT extends AbstractControllerIntegrationTest {
}
@Test
@Ignore("This test fails due to a bug in the MockHttpResponseServlet,"
+ " see https://github.com/spring-projects/spring-framework/issues/25281")
public void checkEnabledMultipleLanguageSupportTest() throws Exception {
context.turnOffAuthorisationSystem();
String[] supportedLanguage = {"uk","it"};
@@ -75,7 +78,7 @@ public class LanguageSupportIT extends AbstractControllerIntegrationTest {
.andExpect(header().stringValues("Content-Language","uk, it"));
getClient(tokenEPersonFR).perform(get("/api").locale(it))
.andExpect(header().stringValues("Content-Language","en"));
.andExpect(header().stringValues("Content-Language","uk, it"));
configurationService.setProperty("webui.supported.locales",null);
legacyPluginService.clearNamedPluginClasses();

View File

@@ -43,6 +43,13 @@ public class ProcessRestRepositoryIT extends AbstractControllerIntegrationTest {
@Before
public void setup() throws SQLException {
CollectionUtils.emptyIfNull(processService.findAll(context)).stream().forEach(process -> {
try {
processService.delete(context, process);
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
parameters.add(new DSpaceCommandLineParameter("-r", "test"));
parameters.add(new DSpaceCommandLineParameter("-i", null));

View File

@@ -258,7 +258,7 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe
+ " Як що вмiст вайлу не є текстовим, наприклад є фотографiєю, тодi вибрати (N/A)",
"dc.language.iso"))));
resetPropertyFile();
resetLocalesConfiguration();
}
@Test
@@ -331,7 +331,7 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe
+ " Як що вмiст вайлу не є текстовим, наприклад є фотографiєю, тодi вибрати (N/A)",
"dc.language.iso"))));
resetPropertyFile();
resetLocalesConfiguration();
}
@Test
@@ -377,7 +377,7 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe
+ " Se il contenuto non ha davvero una lingua"
+ " (ad esempio, se è un set di dati o un'immagine) selezionare (N/A)", "dc.language.iso"))));
resetPropertyFile();
resetLocalesConfiguration();
}
@Test
@@ -408,10 +408,11 @@ public class SubmissionFormsControllerIT extends AbstractControllerIntegrationTe
"\u00C8 necessario inserire un titolo principale per questo item", false,
"Inserisci titolo principale di questo item", "dc.title"))));
resetPropertyFile();
resetLocalesConfiguration();
}
private void resetPropertyFile() throws DCInputsReaderException {
private void resetLocalesConfiguration() throws DCInputsReaderException {
configurationService.setProperty("default.locale","en");
configurationService.setProperty("webui.supported.locales",null);
submissionFormRestRepository.reload();
}

View File

@@ -13,6 +13,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.HashMap;
@@ -41,6 +42,9 @@ import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Tests functionality of {@link ConverterService}.
@@ -76,6 +80,11 @@ public class ConverterServiceIT extends AbstractControllerIntegrationTest {
mockHttpServletRequest.setAttribute("dspace.context", new Context());
MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse();
requestService.startRequest(mockHttpServletRequest, mockHttpServletResponse);
Authentication authentication = mock(Authentication.class);
SecurityContext securityContext = mock(SecurityContext.class);
when(securityContext.getAuthentication()).thenReturn(authentication);
SecurityContextHolder.setContext(securityContext);
when(SecurityContextHolder.getContext().getAuthentication().getPrincipal()).thenReturn(eperson);
}
/**
* When calling {@code toRest} with an object for which an appropriate {@link DSpaceConverter} can't be found,
@@ -103,6 +112,10 @@ public class ConverterServiceIT extends AbstractControllerIntegrationTest {
/**
* When calling {@code toRest} with the default projection, the converter should run and no changes should be made.
* This converter.toRest will now also check permissions through the PreAuthorize annotation on the
* Repository's findOne method. Therefor a repository has been added for this MockObjectRest namely
* {@link org.dspace.app.rest.repository.MockObjectRestRepository} and added PreAuthorize annotations
* on the methods of this Repository
*/
@Test
public void toRestWithDefaultProjection() {

View File

@@ -0,0 +1,41 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.repository;
import org.dspace.app.rest.model.MockObjectRest;
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;
/**
* This class has been added to allow the MockObjectRest to act as an actual BaseObjectRest since they're
* expected to have a RestRepository
*/
@Component(MockObjectRest.CATEGORY + "." + MockObjectRest.NAME)
public class MockObjectRestRepository extends DSpaceRestRepository<MockObjectRest, Long> {
// Added a permitAll preAuthorize annotation to allow the object to be used in tests by every user
@Override
@PreAuthorize("permitAll()")
public MockObjectRest findOne(Context context, Long aLong) {
return null;
}
@Override
@PreAuthorize("permitAll()")
public Page<MockObjectRest> findAll(Context context, Pageable pageable) {
return null;
}
@Override
public Class<MockObjectRest> getDomainClass() {
return MockObjectRest.class;
}
}