mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-15 14:03:17 +00:00
bulk access controll
This commit is contained in:

committed by
eskander

parent
6b40f2eea6
commit
4e64afbe3b
@@ -0,0 +1,456 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkaccesscontrol;
|
||||||
|
|
||||||
|
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
|
||||||
|
import static org.dspace.authorize.ResourcePolicy.TYPE_CUSTOM;
|
||||||
|
import static org.dspace.authorize.ResourcePolicy.TYPE_INHERITED;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.commons.cli.ParseException;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.app.bulkaccesscontrol.exception.BulkAccessControlException;
|
||||||
|
import org.dspace.app.bulkaccesscontrol.model.AccessCondition;
|
||||||
|
import org.dspace.app.bulkaccesscontrol.model.AccessConditionBitstream;
|
||||||
|
import org.dspace.app.bulkaccesscontrol.model.AccessControl;
|
||||||
|
import org.dspace.app.bulkaccesscontrol.model.BulkAccessConditionConfiguration;
|
||||||
|
import org.dspace.app.bulkaccesscontrol.service.BulkAccessConditionConfigurationService;
|
||||||
|
import org.dspace.app.util.DSpaceObjectUtilsImpl;
|
||||||
|
import org.dspace.app.util.service.DSpaceObjectUtils;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.authorize.service.ResourcePolicyService;
|
||||||
|
import org.dspace.content.Bitstream;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.BitstreamService;
|
||||||
|
import org.dspace.content.service.BundleService;
|
||||||
|
import org.dspace.content.service.CollectionService;
|
||||||
|
import org.dspace.content.service.CommunityService;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.discovery.DiscoverQuery;
|
||||||
|
import org.dspace.discovery.SearchService;
|
||||||
|
import org.dspace.discovery.SearchServiceException;
|
||||||
|
import org.dspace.discovery.SearchUtils;
|
||||||
|
import org.dspace.discovery.indexobject.IndexableItem;
|
||||||
|
import org.dspace.discovery.indexobject.factory.IndexObjectFactoryFactory;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||||
|
import org.dspace.handle.factory.HandleServiceFactory;
|
||||||
|
import org.dspace.handle.service.HandleService;
|
||||||
|
import org.dspace.scripts.DSpaceRunnable;
|
||||||
|
import org.dspace.services.ConfigurationService;
|
||||||
|
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||||
|
import org.dspace.submit.model.AccessConditionOption;
|
||||||
|
import org.dspace.util.MultiFormatDateParser;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link DSpaceRunnable} to perform a bulk access control via json file.
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BulkAccessControl extends DSpaceRunnable<BulkAccessControlScriptConfiguration<BulkAccessControl>> {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(BulkAccessControl.class);
|
||||||
|
|
||||||
|
private DSpaceObjectUtils dSpaceObjectUtils;
|
||||||
|
|
||||||
|
private SearchService searchService;
|
||||||
|
|
||||||
|
private IndexObjectFactoryFactory indexObjectServiceFactory;
|
||||||
|
|
||||||
|
private CommunityService communityService;
|
||||||
|
|
||||||
|
private CollectionService collectionService;
|
||||||
|
|
||||||
|
private ConfigurationService configurationService;
|
||||||
|
|
||||||
|
private ItemService itemService;
|
||||||
|
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
private String filename;
|
||||||
|
|
||||||
|
private String[] uuids;
|
||||||
|
|
||||||
|
private String [] targetUuids;
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
private BundleService bundleService;
|
||||||
|
|
||||||
|
private BitstreamService bitstreamService;
|
||||||
|
|
||||||
|
private BulkAccessConditionConfigurationService bulkAccessConditionConfigurationService;
|
||||||
|
|
||||||
|
private ResourcePolicyService resourcePolicyService;
|
||||||
|
|
||||||
|
private Map<String, AccessConditionOption> itemAccessConditions;
|
||||||
|
|
||||||
|
private Map<String, AccessConditionOption> uploadAccessConditions;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void setup() throws ParseException {
|
||||||
|
|
||||||
|
this.searchService = SearchUtils.getSearchService();
|
||||||
|
this.indexObjectServiceFactory = IndexObjectFactoryFactory.getInstance();
|
||||||
|
this.communityService = ContentServiceFactory.getInstance().getCommunityService();
|
||||||
|
this.collectionService = ContentServiceFactory.getInstance().getCollectionService();
|
||||||
|
this.itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
this.authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
|
||||||
|
this.bundleService = ContentServiceFactory.getInstance().getBundleService();
|
||||||
|
this.bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
|
||||||
|
this.resourcePolicyService = AuthorizeServiceFactory.getInstance().getResourcePolicyService();
|
||||||
|
this.configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||||
|
this.bulkAccessConditionConfigurationService = new DSpace().getServiceManager().getServiceByName(
|
||||||
|
"bulkAccessConditionConfigurationService", BulkAccessConditionConfigurationService.class);
|
||||||
|
this.dSpaceObjectUtils = new DSpace().getServiceManager().getServiceByName(
|
||||||
|
DSpaceObjectUtilsImpl.class.getName(), DSpaceObjectUtilsImpl.class);
|
||||||
|
|
||||||
|
BulkAccessConditionConfiguration bulkAccessConditionConfiguration =
|
||||||
|
bulkAccessConditionConfigurationService.getBulkAccessConditionConfiguration("default");
|
||||||
|
|
||||||
|
itemAccessConditions = bulkAccessConditionConfiguration
|
||||||
|
.getItemAccessConditionOptions()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(AccessConditionOption::getName, Function.identity()));
|
||||||
|
|
||||||
|
uploadAccessConditions = bulkAccessConditionConfiguration
|
||||||
|
.getBitstreamAccessConditionOptions()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(AccessConditionOption::getName, Function.identity()));
|
||||||
|
|
||||||
|
filename = commandLine.getOptionValue('f');
|
||||||
|
uuids = commandLine.getOptionValues('u');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void internalRun() throws Exception {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
AccessControl accessControl;
|
||||||
|
context = new Context(Context.Mode.BATCH_EDIT);
|
||||||
|
assignCurrentUserInContext();
|
||||||
|
assignSpecialGroupsInContext();
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
if (uuids == null) {
|
||||||
|
handler.logError("A target uuid must be provided (run with -h flag for details)");
|
||||||
|
throw new IllegalArgumentException("A target uuid must be provided");
|
||||||
|
} else if (uuids.length <= 0) {
|
||||||
|
handler.logError("A target uuid must be provided with at least on uuid");
|
||||||
|
throw new IllegalArgumentException("A target uuid must be provided with at least on uuid");
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream inputStream = handler.getFileStream(context, filename)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("Error reading file, the file couldn't be "
|
||||||
|
+ "found for filename: " + filename));
|
||||||
|
|
||||||
|
try {
|
||||||
|
accessControl = mapper.readValue(inputStream, AccessControl.class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
handler.logError("Error parsing json file");
|
||||||
|
throw new IllegalArgumentException("Error parsing json file", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
validate(accessControl);
|
||||||
|
updateItemsAndBitstreamsPolices(accessControl);
|
||||||
|
context.complete();
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
} catch (Exception e) {
|
||||||
|
handler.handleException(e);
|
||||||
|
context.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validate(AccessControl accessControl) {
|
||||||
|
|
||||||
|
if (Objects.isNull(accessControl.getItem()) && Objects.isNull(accessControl.getBitstream())) {
|
||||||
|
handler.logError("item or bitstream nodes must be provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Objects.nonNull(accessControl.getItem())) {
|
||||||
|
if (StringUtils.isNotEmpty(accessControl.getItem().getMode()) &&
|
||||||
|
!(accessControl.getItem().getMode().equals("add") ||
|
||||||
|
accessControl.getItem().getMode().equals("replace"))) {
|
||||||
|
handler.logError("wrong value for item mode<" + accessControl.getItem().getMode() + ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AccessCondition accessCondition : accessControl.getItem().getAccessConditions()) {
|
||||||
|
validateAccessCondition(accessCondition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Objects.nonNull(accessControl.getBitstream())) {
|
||||||
|
if (StringUtils.isNotEmpty(accessControl.getBitstream().getMode()) &&
|
||||||
|
!(accessControl.getBitstream().getMode().equals("add") ||
|
||||||
|
accessControl.getBitstream().getMode().equals("replace"))) {
|
||||||
|
handler.logError("wrong value for bitstream mode<" + accessControl.getBitstream().getMode() + ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AccessCondition accessCondition : accessControl.getBitstream().getAccessConditions()) {
|
||||||
|
validateAccessCondition(accessCondition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateAccessCondition(AccessCondition accessCondition) {
|
||||||
|
|
||||||
|
if (!itemAccessConditions.containsKey(accessCondition.getName())) {
|
||||||
|
handler.logError("wrong access condition <" + accessCondition.getName() + ">");
|
||||||
|
throw new IllegalArgumentException("wrong access condition <" + accessCondition.getName() + ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
itemAccessConditions.get(accessCondition.getName()).validateResourcePolicy(
|
||||||
|
context, accessCondition.getName(), accessCondition.getStartDate(), accessCondition.getEndDate());
|
||||||
|
} catch (Exception e) {
|
||||||
|
handler.logError("invalid access condition");
|
||||||
|
handler.handleException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateItemsAndBitstreamsPolices(AccessControl accessControl)
|
||||||
|
throws SQLException, SearchServiceException, AuthorizeException {
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
int start = 0;
|
||||||
|
int limit = 20;
|
||||||
|
|
||||||
|
String query = buildSolrQuery(uuids);
|
||||||
|
|
||||||
|
Iterator<Item> itemIterator = findItems(query, start, limit);
|
||||||
|
|
||||||
|
while (itemIterator.hasNext()) {
|
||||||
|
|
||||||
|
Item item = itemIterator.next();
|
||||||
|
|
||||||
|
if (Objects.nonNull(accessControl.getItem())) {
|
||||||
|
updateItemPolicies(item, accessControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Objects.nonNull(accessControl.getBitstream())) {
|
||||||
|
updateBitstreamsPolicies(item, accessControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.commit();
|
||||||
|
context.uncacheEntity(item);
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (counter == limit) {
|
||||||
|
start += limit;
|
||||||
|
itemIterator = findItems(query, start, limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildSolrQuery(String[] uuids) throws SQLException {
|
||||||
|
HandleService handleService = HandleServiceFactory.getInstance().getHandleService();
|
||||||
|
String [] query = new String[uuids.length];
|
||||||
|
for (int i = 0 ; i < query.length ; i++) {
|
||||||
|
DSpaceObject dso = dSpaceObjectUtils.findDSpaceObject(context, UUID.fromString(uuids[i]));
|
||||||
|
if (dso.getType() == Constants.COMMUNITY) {
|
||||||
|
query[i] = "location.comm:" + dso.getID();
|
||||||
|
} else if (dso.getType() == Constants.COLLECTION) {
|
||||||
|
query[i] = "location.coll:" + dso.getID();
|
||||||
|
} else if (dso.getType() == Constants.ITEM) {
|
||||||
|
query[i] = "search.resourceid:" + dso.getID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return StringUtils.joinWith(" OR ", query);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Iterator<Item> findItems(String query, int start, int limit)
|
||||||
|
throws SearchServiceException {
|
||||||
|
|
||||||
|
DiscoverQuery discoverQuery = buildDiscoveryQuery(query, start, limit);
|
||||||
|
|
||||||
|
return searchService.search(context, discoverQuery)
|
||||||
|
.getIndexableObjects()
|
||||||
|
.stream()
|
||||||
|
.map(indexableObject ->
|
||||||
|
((IndexableItem) indexableObject).getIndexedObject())
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DiscoverQuery buildDiscoveryQuery(String query, int start, int limit) {
|
||||||
|
DiscoverQuery discoverQuery = new DiscoverQuery();
|
||||||
|
discoverQuery.setDSpaceObjectFilter(IndexableItem.TYPE);
|
||||||
|
discoverQuery.setQuery(query);
|
||||||
|
discoverQuery.setStart(start);
|
||||||
|
discoverQuery.setMaxResults(limit);
|
||||||
|
|
||||||
|
return discoverQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateItemPolicies(Item item, AccessControl accessControl) throws SQLException, AuthorizeException {
|
||||||
|
|
||||||
|
if ("replace".equals(accessControl.getItem().getMode())) {
|
||||||
|
removeReadPolicies(item, TYPE_CUSTOM);
|
||||||
|
removeReadPolicies(item, TYPE_INHERITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
setItemPolicies(item, accessControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setItemPolicies(Item item, AccessControl accessControl) throws SQLException, AuthorizeException {
|
||||||
|
if (isAppendModeDisabled() && item.isArchived()) {
|
||||||
|
// change to add
|
||||||
|
itemService.adjustItemPolicies(context, item, item.getOwningCollection());
|
||||||
|
}
|
||||||
|
|
||||||
|
accessControl
|
||||||
|
.getItem()
|
||||||
|
.getAccessConditions()
|
||||||
|
.forEach(accessCondition -> createResourcePolicy(item, accessCondition,
|
||||||
|
itemAccessConditions.get(accessCondition.getName())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBitstreamsPolicies(Item item, AccessControl accessControl) {
|
||||||
|
|
||||||
|
if (containsConstraints(accessControl)) {
|
||||||
|
findMatchedBitstreams(item, accessControl.getBitstream().getConstraint().getUuids())
|
||||||
|
.forEach(bitstream ->
|
||||||
|
updateBitstreamPolicies(bitstream, item, accessControl));
|
||||||
|
} else {
|
||||||
|
item.getBundles()
|
||||||
|
.stream()
|
||||||
|
.flatMap(bundle -> bundle.getBitstreams().stream())
|
||||||
|
.forEach(bitstream ->
|
||||||
|
updateBitstreamPolicies(bitstream, item, accessControl));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsConstraints(AccessControl accessControl) {
|
||||||
|
AccessConditionBitstream controlBitstream = accessControl.getBitstream();
|
||||||
|
|
||||||
|
return Objects.nonNull(controlBitstream) &&
|
||||||
|
Objects.nonNull(controlBitstream.getConstraint()) &&
|
||||||
|
isNotEmpty(controlBitstream.getConstraint().getUuids());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Bitstream> findMatchedBitstreams(Item item, List<String> uuids) {
|
||||||
|
return item.getBundles().stream()
|
||||||
|
.flatMap(bundle -> bundle.getBitstreams().stream())
|
||||||
|
.filter(bitstream -> uuids.contains(bitstream.getID().toString()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBitstreamPolicies(Bitstream bitstream, Item item, AccessControl accessControl) {
|
||||||
|
|
||||||
|
if ("replace".equals(accessControl.getBitstream().getMode())) {
|
||||||
|
removeReadPolicies(bitstream, TYPE_CUSTOM);
|
||||||
|
removeReadPolicies(bitstream, TYPE_INHERITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setBitstreamPolicies(bitstream, item, accessControl);
|
||||||
|
} catch (SQLException | AuthorizeException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeReadPolicies(DSpaceObject dso, String type) {
|
||||||
|
try {
|
||||||
|
resourcePolicyService.removePolicies(context, dso, type, Constants.READ);
|
||||||
|
} catch (SQLException | AuthorizeException e) {
|
||||||
|
throw new BulkAccessControlException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBitstreamPolicies(Bitstream bitstream, Item item, AccessControl accessControl)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
if (isAppendModeDisabled() && item.isArchived()) {
|
||||||
|
itemService.adjustBitstreamPolicies(context, item, item.getOwningCollection(), bitstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
accessControl.getBitstream()
|
||||||
|
.getAccessConditions()
|
||||||
|
.forEach(accessCondition -> createResourcePolicy(bitstream, accessCondition,
|
||||||
|
uploadAccessConditions.get(accessCondition.getName())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createResourcePolicy(DSpaceObject obj, AccessCondition accessCondition,
|
||||||
|
AccessConditionOption AccessConditionOption) {
|
||||||
|
|
||||||
|
String name = accessCondition.getName();
|
||||||
|
String description = accessCondition.getDescription();
|
||||||
|
Date startDate = accessCondition.getStartDate();
|
||||||
|
Date endDate = accessCondition.getEndDate();
|
||||||
|
|
||||||
|
try {
|
||||||
|
AccessConditionOption.createResourcePolicy(context, obj, name, description, startDate, endDate);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// private void rollback() {
|
||||||
|
// try {
|
||||||
|
// context.rollback();
|
||||||
|
// } catch (SQLException e) {
|
||||||
|
// throw new SQLRuntimeException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private void assignCurrentUserInContext() throws SQLException {
|
||||||
|
UUID uuid = getEpersonIdentifier();
|
||||||
|
if (uuid != null) {
|
||||||
|
EPerson ePerson = EPersonServiceFactory.getInstance().getEPersonService().find(context, uuid);
|
||||||
|
context.setCurrentUser(ePerson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assignSpecialGroupsInContext() throws SQLException {
|
||||||
|
for (UUID uuid : handler.getSpecialGroups()) {
|
||||||
|
context.setSpecialGroup(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date parseDate(String date) {
|
||||||
|
return MultiFormatDateParser.parse(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAppendModeDisabled() {
|
||||||
|
return !configurationService.getBooleanProperty(
|
||||||
|
"core.authorization.installitem.inheritance-read.append-mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public BulkAccessControlScriptConfiguration<BulkAccessControl> getScriptConfiguration() {
|
||||||
|
return new DSpace().getServiceManager()
|
||||||
|
.getServiceByName("bulk-access-control",BulkAccessControlScriptConfiguration.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkaccesscontrol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link BulkAccessControl} for CLI.
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BulkAccessControlCli extends BulkAccessControl {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkaccesscontrol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link BulkAccessControlScriptConfiguration} for CLI.
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BulkAccessControlCliScriptConfiguration<T extends BulkAccessControlCli>
|
||||||
|
extends BulkAccessControlScriptConfiguration<T> {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkaccesscontrol;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.cli.Options;
|
||||||
|
import org.dspace.app.util.DSpaceObjectUtilsImpl;
|
||||||
|
import org.dspace.app.util.service.DSpaceObjectUtils;
|
||||||
|
import org.dspace.content.DSpaceObject;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||||
|
import org.dspace.scripts.configuration.ScriptConfiguration;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Script configuration for {@link BulkAccessControl}.
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*
|
||||||
|
* @param <T> the {@link BulkAccessControl} type
|
||||||
|
*/
|
||||||
|
public class BulkAccessControlScriptConfiguration<T extends BulkAccessControl> extends ScriptConfiguration<T> {
|
||||||
|
|
||||||
|
private Class<T> dspaceRunnableClass;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowedToExecute(Context context, List<DSpaceCommandLineParameter> commandLineParameters) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Objects.isNull(commandLineParameters)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
} else if (commandLineParameters.stream()
|
||||||
|
.map(DSpaceCommandLineParameter::getName)
|
||||||
|
.noneMatch("-u"::equals)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
} else {
|
||||||
|
List<String> dspaceObjectIDs =
|
||||||
|
commandLineParameters.stream()
|
||||||
|
.filter(parameter -> "-u".equals(parameter.getName()))
|
||||||
|
.map(DSpaceCommandLineParameter::getValue)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
DSpaceObjectUtils dSpaceObjectUtils = new DSpace().getServiceManager().getServiceByName(
|
||||||
|
DSpaceObjectUtilsImpl.class.getName(), DSpaceObjectUtilsImpl.class);
|
||||||
|
|
||||||
|
for (String dspaceObjectID : dspaceObjectIDs) {
|
||||||
|
|
||||||
|
DSpaceObject dso = dSpaceObjectUtils.findDSpaceObject(context, UUID.fromString(dspaceObjectID));
|
||||||
|
|
||||||
|
if (Objects.isNull(dso)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authorizeService.isAdmin(context, dso)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Options getOptions() {
|
||||||
|
if (options == null) {
|
||||||
|
Options options = new Options();
|
||||||
|
|
||||||
|
options.addOption("u", "target", true, "target uuids of communities/collections/items");
|
||||||
|
options.getOption("u").setType(String.class);
|
||||||
|
options.getOption("u").setRequired(true);
|
||||||
|
|
||||||
|
options.addOption("f", "file", true, "source json file");
|
||||||
|
options.getOption("f").setType(InputStream.class);
|
||||||
|
options.getOption("f").setRequired(true);
|
||||||
|
|
||||||
|
options.addOption("h", "help", false, "help");
|
||||||
|
|
||||||
|
super.options = options;
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getDspaceRunnableClass() {
|
||||||
|
return dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic setter for the dspaceRunnableClass
|
||||||
|
*
|
||||||
|
* @param dspaceRunnableClass The dspaceRunnableClass to be set on this
|
||||||
|
* BulkImportScriptConfiguration
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setDspaceRunnableClass(Class<T> dspaceRunnableClass) {
|
||||||
|
this.dspaceRunnableClass = dspaceRunnableClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.bulkaccesscontrol.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception for errors that occurs during the bulk access control
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BulkAccessControlException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -74730626862418515L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with error message and cause.
|
||||||
|
*
|
||||||
|
* @param message the error message
|
||||||
|
* @param cause the error cause
|
||||||
|
*/
|
||||||
|
public BulkAccessControlException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with error message.
|
||||||
|
*
|
||||||
|
* @param message the error message
|
||||||
|
*/
|
||||||
|
public BulkAccessControlException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with error cause.
|
||||||
|
*
|
||||||
|
* @param cause the error cause
|
||||||
|
*/
|
||||||
|
public BulkAccessControlException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkaccesscontrol.model;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that model the value of ACCESS_CONDITION_CELL
|
||||||
|
* of sheet BITSTREAM_METADATA of the Bulk import excel.
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*/
|
||||||
|
public class AccessCondition {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Date startDate;
|
||||||
|
|
||||||
|
private Date endDate;
|
||||||
|
|
||||||
|
public AccessCondition() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessCondition(String name, String description, Date startDate, Date endDate) {
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.startDate = startDate;
|
||||||
|
this.endDate = endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getStartDate() {
|
||||||
|
return startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getEndDate() {
|
||||||
|
return endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.bulkaccesscontrol.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*/
|
||||||
|
public class AccessConditionBitstream {
|
||||||
|
|
||||||
|
private String mode;
|
||||||
|
|
||||||
|
private Constraint constraint;
|
||||||
|
|
||||||
|
private List<AccessCondition> accessConditions;
|
||||||
|
|
||||||
|
public String getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(String mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constraint getConstraint() {
|
||||||
|
return constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConstraint(Constraint constraint) {
|
||||||
|
this.constraint = constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AccessCondition> getAccessConditions() {
|
||||||
|
return accessConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessConditions(List<AccessCondition> accessConditions) {
|
||||||
|
this.accessConditions = accessConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Constraint {
|
||||||
|
|
||||||
|
private List<String> uuids;
|
||||||
|
|
||||||
|
public List<String> getUuids() {
|
||||||
|
return uuids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuids(List<String> uuids) {
|
||||||
|
this.uuids = uuids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkaccesscontrol.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*/
|
||||||
|
public class AccessConditionItem {
|
||||||
|
|
||||||
|
String mode;
|
||||||
|
|
||||||
|
List<AccessCondition> accessConditions;
|
||||||
|
|
||||||
|
public String getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(String mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AccessCondition> getAccessConditions() {
|
||||||
|
return accessConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessConditions(List<AccessCondition> accessConditions) {
|
||||||
|
this.accessConditions = accessConditions;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.bulkaccesscontrol.model;
|
||||||
|
|
||||||
|
public class AccessControl {
|
||||||
|
|
||||||
|
AccessConditionItem item;
|
||||||
|
|
||||||
|
AccessConditionBitstream bitstream;
|
||||||
|
|
||||||
|
public AccessControl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessControl(AccessConditionItem item,
|
||||||
|
AccessConditionBitstream bitstream) {
|
||||||
|
this.item = item;
|
||||||
|
this.bitstream = bitstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessConditionItem getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(AccessConditionItem item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessConditionBitstream getBitstream() {
|
||||||
|
return bitstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBitstream(AccessConditionBitstream bitstream) {
|
||||||
|
this.bitstream = bitstream;
|
||||||
|
}
|
||||||
|
}
|
@@ -232,6 +232,15 @@ public class ResourcePolicyServiceImpl implements ResourcePolicyService {
|
|||||||
c.restoreAuthSystemState();
|
c.restoreAuthSystemState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePolicies(Context c, DSpaceObject o, String type, int action)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
resourcePolicyDAO.deleteByDsoAndTypeAndAction(c, o, type, action);
|
||||||
|
c.turnOffAuthorisationSystem();
|
||||||
|
contentServiceFactory.getDSpaceObjectService(o).updateLastModified(c, o);
|
||||||
|
c.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeDsoGroupPolicies(Context context, DSpaceObject dso, Group group)
|
public void removeDsoGroupPolicies(Context context, DSpaceObject dso, Group group)
|
||||||
throws SQLException, AuthorizeException {
|
throws SQLException, AuthorizeException {
|
||||||
|
@@ -39,6 +39,9 @@ public interface ResourcePolicyDAO extends GenericDAO<ResourcePolicy> {
|
|||||||
|
|
||||||
public List<ResourcePolicy> findByDSoAndAction(Context context, DSpaceObject dso, int actionId) throws SQLException;
|
public List<ResourcePolicy> findByDSoAndAction(Context context, DSpaceObject dso, int actionId) throws SQLException;
|
||||||
|
|
||||||
|
public void deleteByDsoAndTypeAndAction(Context context, DSpaceObject dSpaceObject, String type, int action)
|
||||||
|
throws SQLException;
|
||||||
|
|
||||||
public List<ResourcePolicy> findByTypeGroupAction(Context context, DSpaceObject dso, Group group, int action)
|
public List<ResourcePolicy> findByTypeGroupAction(Context context, DSpaceObject dso, Group group, int action)
|
||||||
throws SQLException;
|
throws SQLException;
|
||||||
|
|
||||||
|
@@ -103,6 +103,19 @@ public class ResourcePolicyDAOImpl extends AbstractHibernateDAO<ResourcePolicy>
|
|||||||
return list(context, criteriaQuery, false, ResourcePolicy.class, -1, -1);
|
return list(context, criteriaQuery, false, ResourcePolicy.class, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteByDsoAndTypeAndAction(Context context, DSpaceObject dso, String type, int actionId)
|
||||||
|
throws SQLException {
|
||||||
|
String queryString = "delete from ResourcePolicy where dSpaceObject.id = :dsoId "
|
||||||
|
+ "AND rptype = :rptype AND actionId= :actionId";
|
||||||
|
Query query = createQuery(context, queryString);
|
||||||
|
query.setParameter("dsoId", dso.getID());
|
||||||
|
query.setParameter("rptype", type);
|
||||||
|
query.setParameter("actionId", actionId);
|
||||||
|
query.executeUpdate();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ResourcePolicy> findByTypeGroupAction(Context context, DSpaceObject dso, Group group, int action)
|
public List<ResourcePolicy> findByTypeGroupAction(Context context, DSpaceObject dso, Group group, int action)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
|
@@ -93,6 +93,9 @@ public interface ResourcePolicyService extends DSpaceCRUDService<ResourcePolicy>
|
|||||||
|
|
||||||
public void removePolicies(Context c, DSpaceObject o, String type) throws SQLException, AuthorizeException;
|
public void removePolicies(Context c, DSpaceObject o, String type) throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
|
public void removePolicies(Context c, DSpaceObject o, String type, int action)
|
||||||
|
throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
public void removeDsoGroupPolicies(Context context, DSpaceObject dso, Group group)
|
public void removeDsoGroupPolicies(Context context, DSpaceObject dso, Group group)
|
||||||
throws SQLException, AuthorizeException;
|
throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
|
@@ -940,13 +940,38 @@ public class ItemServiceImpl extends DSpaceObjectServiceImpl<Item> implements It
|
|||||||
|
|
||||||
for (Bitstream bitstream : mybundle.getBitstreams()) {
|
for (Bitstream bitstream : mybundle.getBitstreams()) {
|
||||||
// if come from InstallItem: remove all submission/workflow policies
|
// if come from InstallItem: remove all submission/workflow policies
|
||||||
|
removeAllPoliciesAndAddDefault(context, bitstream, defaultItemPolicies, defaultCollectionPolicies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void adjustBitstreamPolicies(Context context, Item item, Collection collection , Bitstream bitstream)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
|
List<ResourcePolicy> defaultCollectionPolicies = authorizeService
|
||||||
|
.getPoliciesActionFilter(context, collection, Constants.DEFAULT_BITSTREAM_READ);
|
||||||
|
|
||||||
|
List<ResourcePolicy> defaultItemPolicies = authorizeService.findPoliciesByDSOAndType(context, item,
|
||||||
|
ResourcePolicy.TYPE_CUSTOM);
|
||||||
|
if (defaultCollectionPolicies.size() < 1) {
|
||||||
|
throw new SQLException("Collection " + collection.getID()
|
||||||
|
+ " (" + collection.getHandle() + ")"
|
||||||
|
+ " has no default bitstream READ policies");
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all policies from bitstream, add new ones
|
||||||
|
removeAllPoliciesAndAddDefault(context, bitstream, defaultItemPolicies, defaultCollectionPolicies);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeAllPoliciesAndAddDefault(Context context, Bitstream bitstream,
|
||||||
|
List<ResourcePolicy> defaultItemPolicies,
|
||||||
|
List<ResourcePolicy> defaultCollectionPolicies)
|
||||||
|
throws SQLException, AuthorizeException {
|
||||||
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_SUBMISSION);
|
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_SUBMISSION);
|
||||||
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_WORKFLOW);
|
authorizeService.removeAllPoliciesByDSOAndType(context, bitstream, ResourcePolicy.TYPE_WORKFLOW);
|
||||||
addCustomPoliciesNotInPlace(context, bitstream, defaultItemPolicies);
|
addCustomPoliciesNotInPlace(context, bitstream, defaultItemPolicies);
|
||||||
addDefaultPoliciesNotInPlace(context, bitstream, defaultCollectionPolicies);
|
addDefaultPoliciesNotInPlace(context, bitstream, defaultCollectionPolicies);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void adjustItemPolicies(Context context, Item item, Collection collection)
|
public void adjustItemPolicies(Context context, Item item, Collection collection)
|
||||||
|
@@ -507,6 +507,25 @@ public interface ItemService
|
|||||||
public void adjustBundleBitstreamPolicies(Context context, Item item, Collection collection)
|
public void adjustBundleBitstreamPolicies(Context context, Item item, Collection collection)
|
||||||
throws SQLException, AuthorizeException;
|
throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust the Bundle and Bitstream policies to reflect what have been defined
|
||||||
|
* during the submission/workflow. The temporary SUBMISSION and WORKFLOW
|
||||||
|
* policies are removed and the policies defined at the item and collection
|
||||||
|
* level are copied and inherited as appropriate. Custom selected Item policies
|
||||||
|
* are copied to the bundle/bitstream only if no explicit custom policies were
|
||||||
|
* already applied to the bundle/bitstream. Collection's policies are inherited
|
||||||
|
* if there are no other policies defined or if the append mode is defined by
|
||||||
|
* the configuration via the core.authorization.installitem.inheritance-read.append-mode property
|
||||||
|
*
|
||||||
|
* @param context DSpace context object
|
||||||
|
* @param item Item to adjust policies on
|
||||||
|
* @param collection Collection
|
||||||
|
* @throws SQLException If database error
|
||||||
|
* @throws AuthorizeException If authorization error
|
||||||
|
*/
|
||||||
|
public void adjustBitstreamPolicies(Context context, Item item, Collection collection, Bitstream bitstream)
|
||||||
|
throws SQLException, AuthorizeException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjust the Item's policies to reflect what have been defined during the
|
* Adjust the Item's policies to reflect what have been defined during the
|
||||||
|
@@ -184,7 +184,7 @@ public class AccessConditionOption {
|
|||||||
* @param endDate End date of the resource policy. If {@link #getHasEndDate()}
|
* @param endDate End date of the resource policy. If {@link #getHasEndDate()}
|
||||||
* returns false, endDate should be null. Otherwise endDate may not be null.
|
* returns false, endDate should be null. Otherwise endDate may not be null.
|
||||||
*/
|
*/
|
||||||
private void validateResourcePolicy(Context context, String name, Date startDate, Date endDate)
|
public void validateResourcePolicy(Context context, String name, Date startDate, Date endDate)
|
||||||
throws SQLException, AuthorizeException, ParseException {
|
throws SQLException, AuthorizeException, ParseException {
|
||||||
if (getHasStartDate() && Objects.isNull(startDate)) {
|
if (getHasStartDate() && Objects.isNull(startDate)) {
|
||||||
throw new IllegalStateException("The access condition " + getName() + " requires a start date.");
|
throw new IllegalStateException("The access condition " + getName() + " requires a start date.");
|
||||||
|
@@ -86,4 +86,9 @@
|
|||||||
<property name="dspaceRunnableClass" value="org.dspace.app.itemexport.ItemExportCLI"/>
|
<property name="dspaceRunnableClass" value="org.dspace.app.itemexport.ItemExportCLI"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="bulk-access-control" class="org.dspace.app.bulkaccesscontrol.BulkAccessControlCliScriptConfiguration" primary="true">
|
||||||
|
<property name="description" value="Bulk access control"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.app.bulkaccesscontrol.BulkAccessControlCli"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -0,0 +1,437 @@
|
|||||||
|
/**
|
||||||
|
* 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.bulkaccesscontrol;
|
||||||
|
|
||||||
|
import static org.dspace.app.matcher.ResourcePolicyMatcher.matches;
|
||||||
|
import static org.dspace.authorize.ResourcePolicy.TYPE_CUSTOM;
|
||||||
|
import static org.dspace.core.Constants.READ;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.allOf;
|
||||||
|
import static org.hamcrest.Matchers.contains;
|
||||||
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.AssertTrue;
|
||||||
|
|
||||||
|
import org.apache.commons.io.file.PathUtils;
|
||||||
|
import org.dspace.AbstractIntegrationTestWithDatabase;
|
||||||
|
import org.dspace.app.launcher.ScriptLauncher;
|
||||||
|
import org.dspace.app.matcher.ResourcePolicyMatcher;
|
||||||
|
import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler;
|
||||||
|
import org.dspace.authorize.ResourcePolicy;
|
||||||
|
import org.dspace.builder.CollectionBuilder;
|
||||||
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.ItemBuilder;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.Community;
|
||||||
|
import org.dspace.content.Item;
|
||||||
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Constants;
|
||||||
|
import org.dspace.eperson.Group;
|
||||||
|
import org.dspace.eperson.GroupTest;
|
||||||
|
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||||
|
import org.dspace.eperson.service.GroupService;
|
||||||
|
import org.dspace.matcher.DateMatcher;
|
||||||
|
import org.dspace.util.MultiFormatDateParser;
|
||||||
|
import org.dspace.utils.DSpace;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic integration testing for the Bulk Access conditions Feature{@link BulkAccessControl}.
|
||||||
|
*
|
||||||
|
* @author Mohamed Eskander (mohamed.eskander at 4science.it)
|
||||||
|
*/
|
||||||
|
public class BulkAccessControlIT extends AbstractIntegrationTestWithDatabase {
|
||||||
|
private Path tempDir;
|
||||||
|
private String tempFilePath;
|
||||||
|
private Collection collection;
|
||||||
|
|
||||||
|
private ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
private GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("Parent Community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
collection = CollectionBuilder.createCollection(context, parentCommunity)
|
||||||
|
.withName("Collection")
|
||||||
|
.withEntityType("Publication")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
tempDir = Files.createTempDirectory("bulkAccessTest");
|
||||||
|
tempFilePath = tempDir + "/bulk-access.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
PathUtils.deleteDirectory(tempDir);
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void performBulkAccessWithoutRequiredParamTest() throws Exception {
|
||||||
|
|
||||||
|
buildJsonFile("");
|
||||||
|
|
||||||
|
String[] args = new String[] {"bulk-access-control", "-f", tempFilePath};
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), hasSize(1));
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void performBulkAccessWithEmptyJsonTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community community = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withName("collection")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).withTitle("title").build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
buildJsonFile("");
|
||||||
|
|
||||||
|
String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath};
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), hasSize(1));
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void performBulkAccessWithWrongModeOfItemValueTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community community = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withName("collection")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String json = "{ \"item\": {\n" +
|
||||||
|
" \"mode\": \"wrong\",\n" +
|
||||||
|
" \"accessConditions\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"name\": \"openaccess\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }}\n";
|
||||||
|
|
||||||
|
buildJsonFile(json);
|
||||||
|
|
||||||
|
String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath};
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), hasSize(1));
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void performBulkAccessWithWrongModeOfBitstreamValueTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community community = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withName("collection")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String json = "{ \"bitstream\": {\n" +
|
||||||
|
" \"mode\": \"wrong\",\n" +
|
||||||
|
" \"accessConditions\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"name\": \"openaccess\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }}\n";
|
||||||
|
|
||||||
|
buildJsonFile(json);
|
||||||
|
|
||||||
|
String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath};
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), hasSize(1));
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void performBulkAccessWithNotFoundAccessConditionNameTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
Community community = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withName("collection")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String json = "{ \"item\": {\n" +
|
||||||
|
" \"mode\": \"add\",\n" +
|
||||||
|
" \"accessConditions\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"name\": \"wrongAccess\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }}\n";
|
||||||
|
|
||||||
|
buildJsonFile(json);
|
||||||
|
|
||||||
|
String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath};
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), hasSize(1));
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void performBulkAccessWithInvalidAccessConditionDateTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community community = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collection = CollectionBuilder.createCollection(context, community)
|
||||||
|
.withName("collection")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Item item = ItemBuilder.createItem(context, collection).build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String jsonOne = "{ \"item\": {\n" +
|
||||||
|
" \"mode\": \"add\",\n" +
|
||||||
|
" \"accessConditions\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"name\": \"embargo\",\n" +
|
||||||
|
" \"endDate\": \"2024-06-24T23:59:59.999+0000\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }}\n";
|
||||||
|
|
||||||
|
buildJsonFile(jsonOne);
|
||||||
|
|
||||||
|
String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath};
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), hasSize(1));
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
|
||||||
|
String jsonTwo = "{ \"item\": {\n" +
|
||||||
|
" \"mode\": \"add\",\n" +
|
||||||
|
" \"accessConditions\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"name\": \"lease\",\n" +
|
||||||
|
" \"startDate\": \"2024-06-24T23:59:59.999+0000\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }}\n";
|
||||||
|
|
||||||
|
buildJsonFile(jsonTwo);
|
||||||
|
|
||||||
|
args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath};
|
||||||
|
|
||||||
|
testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), hasSize(1));
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void performBulkAccessWithValidJsonTest() throws Exception {
|
||||||
|
context.turnOffAuthorisationSystem();
|
||||||
|
|
||||||
|
Community parentCommunity = CommunityBuilder.createCommunity(context)
|
||||||
|
.withName("parent community")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Community subCommunityOne = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||||
|
.withName("sub community one")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Community subCommunityTwo = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||||
|
.withName("sub community two")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Community subCommunityThree = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||||
|
.withName("sub community two")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collectionOne = CollectionBuilder.createCollection(context, subCommunityOne)
|
||||||
|
.withName("collection one")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collectionTwo = CollectionBuilder.createCollection(context, subCommunityTwo)
|
||||||
|
.withName("collection two")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Collection collectionThree = CollectionBuilder.createCollection(context, subCommunityThree)
|
||||||
|
.withName("collection three")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ItemBuilder.createItem(context, collectionOne).build();
|
||||||
|
|
||||||
|
ItemBuilder.createItem(context, collectionTwo).build();
|
||||||
|
|
||||||
|
Item itemThree = ItemBuilder.createItem(context, collectionThree).withTitle("item three title").build();
|
||||||
|
|
||||||
|
Item itemFour = ItemBuilder.createItem(context, collectionThree).withTitle("item four title").build();
|
||||||
|
|
||||||
|
context.restoreAuthSystemState();
|
||||||
|
|
||||||
|
String jsonOne = "{ \"item\": {\n" +
|
||||||
|
" \"mode\": \"replace\",\n" +
|
||||||
|
" \"accessConditions\": [\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"name\": \"embargo\",\n" +
|
||||||
|
" \"startDate\": \"2024-06-24T00:00:00.000Z\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }}\n";
|
||||||
|
|
||||||
|
buildJsonFile(jsonOne);
|
||||||
|
|
||||||
|
String[] args = new String[] {
|
||||||
|
"bulk-access-control",
|
||||||
|
"-u", subCommunityOne.getID().toString(),
|
||||||
|
"-u", collectionTwo.getID().toString(),
|
||||||
|
"-u", itemThree.getID().toString(),
|
||||||
|
"-f", tempFilePath
|
||||||
|
};
|
||||||
|
|
||||||
|
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
|
||||||
|
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
|
||||||
|
|
||||||
|
assertThat(testDSpaceRunnableHandler.getErrorMessages(), empty());
|
||||||
|
assertThat(testDSpaceRunnableHandler.getWarningMessages(), empty());
|
||||||
|
|
||||||
|
Iterator<Item> itemIteratorOne = itemService.findByCollection(context, collectionOne);
|
||||||
|
Iterator<Item> itemIteratorTwo = itemService.findByCollection(context, collectionTwo);
|
||||||
|
itemThree = context.reloadEntity(itemThree);
|
||||||
|
itemFour = context.reloadEntity(itemFour);
|
||||||
|
|
||||||
|
Group anonymousGroup = groupService.findByName(context, Group.ANONYMOUS);
|
||||||
|
|
||||||
|
|
||||||
|
// matchItemsResourcePolicies(itemIteratorOne, anonymousGroup, "embargo", TYPE_CUSTOM, "2024-06-24", null);
|
||||||
|
// matchItemsResourcePolicies(itemIteratorTwo, anonymousGroup, "embargo", TYPE_CUSTOM, "2024-06-24", null);
|
||||||
|
// matchItemResourcePolicies(itemThree, anonymousGroup, "embargo", TYPE_CUSTOM, "2024-06-24", null);
|
||||||
|
|
||||||
|
assertThat(itemThree.getResourcePolicies(), hasSize(2));
|
||||||
|
assertThat(itemThree.getResourcePolicies(), containsInAnyOrder(
|
||||||
|
matches(Constants.READ, anonymousGroup, ResourcePolicy.TYPE_INHERITED),
|
||||||
|
matches(READ, anonymousGroup, "embargo", TYPE_CUSTOM, "2024-06-24T00:00:00.000Z", null, null)
|
||||||
|
));
|
||||||
|
|
||||||
|
// just a note here is working fine
|
||||||
|
assertThat(itemThree.getResourcePolicies(), hasItem(
|
||||||
|
matches(READ, anonymousGroup, "embargo", TYPE_CUSTOM,
|
||||||
|
itemThree.getResourcePolicies().get(0).getStartDate(), null, null)
|
||||||
|
));
|
||||||
|
|
||||||
|
assertThat(itemFour.getResourcePolicies().size(), is(1));
|
||||||
|
assertThat(itemFour.getResourcePolicies(), hasItem(
|
||||||
|
matches(Constants.READ, anonymousGroup, ResourcePolicy.TYPE_INHERITED)
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void matchItemsResourcePolicies(
|
||||||
|
Iterator<Item> itemIterator, Group group, String rpName, String rpType, String startDate, String endDate) {
|
||||||
|
while (itemIterator.hasNext()) {
|
||||||
|
Item item = itemIterator.next();
|
||||||
|
matchItemResourcePolicies(item, group, rpName, rpType, startDate, endDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void matchItemResourcePolicies(
|
||||||
|
Item item, Group group, String rpName, String rpType, String startDate, String endDate) {
|
||||||
|
|
||||||
|
assertThat(item.getResourcePolicies(), hasItem(
|
||||||
|
matches(READ, group, rpName, rpType, startDate, endDate, null)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildJsonFile(String json) throws IOException {
|
||||||
|
File file = new File(tempDir + "/bulk-access.json");
|
||||||
|
Path path = Paths.get(file.getAbsolutePath());
|
||||||
|
Files.writeString(path, json, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* 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.matcher;
|
||||||
|
|
||||||
|
import static org.dspace.util.MultiFormatDateParser.parse;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.dspace.authorize.ResourcePolicy;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.eperson.Group;
|
||||||
|
import org.hamcrest.Description;
|
||||||
|
import org.hamcrest.Matcher;
|
||||||
|
import org.hamcrest.TypeSafeMatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link Matcher} to match a ResourcePolicy.
|
||||||
|
*
|
||||||
|
* @author Luca Giamminonni (luca.giamminonni at 4science.it)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ResourcePolicyMatcher extends TypeSafeMatcher<ResourcePolicy> {
|
||||||
|
|
||||||
|
private final Matcher<Integer> actionId;
|
||||||
|
|
||||||
|
private final Matcher<EPerson> ePerson;
|
||||||
|
|
||||||
|
private final Matcher<Group> group;
|
||||||
|
|
||||||
|
private final Matcher<String> rptype;
|
||||||
|
|
||||||
|
private final Matcher<String> rpName;
|
||||||
|
|
||||||
|
private final Matcher<String> description;
|
||||||
|
|
||||||
|
private final Matcher<Date> startDate;
|
||||||
|
|
||||||
|
private final Matcher<Date> endDate;
|
||||||
|
|
||||||
|
public ResourcePolicyMatcher(Matcher<Integer> actionId, Matcher<EPerson> ePerson, Matcher<Group> group,
|
||||||
|
Matcher<String> rpName, Matcher<String> rptype, Matcher<Date> startDate,
|
||||||
|
Matcher<Date> endDate, Matcher<String> description) {
|
||||||
|
this.actionId = actionId;
|
||||||
|
this.ePerson = ePerson;
|
||||||
|
this.group = group;
|
||||||
|
this.rptype = rptype;
|
||||||
|
this.rpName = rpName;
|
||||||
|
this.description = description;
|
||||||
|
this.startDate = startDate;
|
||||||
|
this.endDate = endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describeTo(Description description) {
|
||||||
|
description.appendText("Resource policy with action id ").appendDescriptionOf(actionId)
|
||||||
|
.appendText(" and EPerson ").appendDescriptionOf(ePerson)
|
||||||
|
.appendText(" and Group ").appendDescriptionOf(group)
|
||||||
|
.appendText(" and rpType ").appendDescriptionOf(rptype)
|
||||||
|
.appendText(" and rpName ").appendDescriptionOf(rpName)
|
||||||
|
.appendText(" and description ").appendDescriptionOf(this.description)
|
||||||
|
.appendText(" and start date ").appendDescriptionOf(startDate)
|
||||||
|
.appendText(" and end date ").appendDescriptionOf(endDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourcePolicyMatcher matches(int actionId, EPerson ePerson, String rptype) {
|
||||||
|
return new ResourcePolicyMatcher(is(actionId), is(ePerson), nullValue(Group.class),
|
||||||
|
any(String.class), is(rptype), any(Date.class), any(Date.class), any(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourcePolicyMatcher matches(int actionId, EPerson ePerson, String rpName, String rptype) {
|
||||||
|
return new ResourcePolicyMatcher(is(actionId), is(ePerson), nullValue(Group.class),
|
||||||
|
is(rpName), is(rptype), any(Date.class), any(Date.class), any(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourcePolicyMatcher matches(int actionId, Group group, String rptype) {
|
||||||
|
return new ResourcePolicyMatcher(is(actionId), nullValue(EPerson.class), is(group),
|
||||||
|
any(String.class), is(rptype), any(Date.class), any(Date.class), any(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourcePolicyMatcher matches(int actionId, Group group, String rpName, String rptype) {
|
||||||
|
return new ResourcePolicyMatcher(is(actionId), nullValue(EPerson.class), is(group), is(rpName),
|
||||||
|
is(rptype), any(Date.class), any(Date.class), any(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourcePolicyMatcher matches(int actionId, Group group, String rpName, String rptype,
|
||||||
|
String description) {
|
||||||
|
return new ResourcePolicyMatcher(is(actionId), nullValue(EPerson.class), is(group), is(rpName),
|
||||||
|
is(rptype), any(Date.class), any(Date.class), is(description));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourcePolicyMatcher matches(int actionId, Group group, String rpName, String rpType, Date startDate,
|
||||||
|
Date endDate, String description) {
|
||||||
|
return new ResourcePolicyMatcher(is(actionId), nullValue(EPerson.class), is(group), is(rpName),
|
||||||
|
is(rpType), is(startDate), is(endDate), is(description));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourcePolicyMatcher matches(int actionId, Group group, String rpName, String rpType,
|
||||||
|
String startDate, String endDate, String description) {
|
||||||
|
return matches(actionId, group, rpName, rpType, startDate != null ? parse(startDate) : null,
|
||||||
|
endDate != null ? parse(endDate) : null, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean matchesSafely(ResourcePolicy resourcePolicy) {
|
||||||
|
return actionId.matches(resourcePolicy.getAction())
|
||||||
|
&& ePerson.matches(resourcePolicy.getEPerson())
|
||||||
|
&& group.matches(resourcePolicy.getGroup())
|
||||||
|
&& rptype.matches(resourcePolicy.getRpType())
|
||||||
|
&& rpName.matches(resourcePolicy.getRpName())
|
||||||
|
&& description.matches(resourcePolicy.getRpDescription())
|
||||||
|
&& startDate.matches(resourcePolicy.getStartDate())
|
||||||
|
&& endDate.matches(resourcePolicy.getEndDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Matcher<T> any(Class<T> clazz) {
|
||||||
|
return LambdaMatcher.matches((obj) -> true, "any value");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -43,4 +43,9 @@
|
|||||||
<property name="dspaceRunnableClass" value="org.dspace.app.itemexport.ItemExport"/>
|
<property name="dspaceRunnableClass" value="org.dspace.app.itemexport.ItemExport"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="bulk-access-control" class="org.dspace.app.bulkaccesscontrol.BulkAccessControlScriptConfiguration" primary="true">
|
||||||
|
<property name="description" value="Bulk access control"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.app.bulkaccesscontrol.BulkAccessControl"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -86,4 +86,9 @@
|
|||||||
<property name="dspaceRunnableClass" value="org.dspace.subscriptions.SubscriptionEmailNotificationCli"/>
|
<property name="dspaceRunnableClass" value="org.dspace.subscriptions.SubscriptionEmailNotificationCli"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="bulk-access-control" class="org.dspace.app.bulkaccesscontrol.BulkAccessControlCliScriptConfiguration" primary="true">
|
||||||
|
<property name="description" value="Bulk access control"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.app.bulkaccesscontrol.BulkAccessControlCli"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
@@ -63,4 +63,10 @@
|
|||||||
<property name="description" value="Batch Export to Simple Archive Format (SAF)"/>
|
<property name="description" value="Batch Export to Simple Archive Format (SAF)"/>
|
||||||
<property name="dspaceRunnableClass" value="org.dspace.app.itemexport.ItemExport"/>
|
<property name="dspaceRunnableClass" value="org.dspace.app.itemexport.ItemExport"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="bulk-access-control" class="org.dspace.app.bulkaccesscontrol.BulkAccessControlScriptConfiguration" primary="true">
|
||||||
|
<property name="description" value="Bulk access control"/>
|
||||||
|
<property name="dspaceRunnableClass" value="org.dspace.app.bulkaccesscontrol.BulkAccessControl"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
Reference in New Issue
Block a user